diff options
author | unknown <bk@work.mysql.com> | 2000-07-31 21:29:14 +0200 |
---|---|---|
committer | unknown <bk@work.mysql.com> | 2000-07-31 21:29:14 +0200 |
commit | 84626f52fb1ca40ebe0175dfda8cc1a2931651c7 (patch) | |
tree | d253a359142dfc1ed247d5d4365d86972ea31109 /mysys | |
parent | 3be46690f46f27f3e671de9a615d24d1554b9991 (diff) | |
download | mariadb-git-84626f52fb1ca40ebe0175dfda8cc1a2931651c7.tar.gz |
Import changeset
Docs/Flags/australia.eps:
First import - 3.23.10
Docs/Flags/australia.gif:
First import - 3.23.10
Docs/Flags/australia.txt:
First import - 3.23.10
Docs/Flags/austria.eps:
First import - 3.23.10
Docs/Flags/austria.gif:
First import - 3.23.10
Docs/Flags/austria.txt:
First import - 3.23.10
Docs/Flags/brazil.eps:
First import - 3.23.10
Docs/Flags/brazil.gif:
First import - 3.23.10
Docs/Flags/brazil.txt:
First import - 3.23.10
Docs/Flags/bulgaria.eps:
First import - 3.23.10
Docs/Flags/bulgaria.gif:
First import - 3.23.10
Docs/Flags/bulgaria.txt:
First import - 3.23.10
Docs/Flags/canada.eps:
First import - 3.23.10
Docs/Flags/canada.gif:
First import - 3.23.10
Docs/Flags/canada.txt:
First import - 3.23.10
Docs/Flags/chile.eps:
First import - 3.23.10
Docs/Flags/chile.gif:
First import - 3.23.10
Docs/Flags/chile.txt:
First import - 3.23.10
Docs/Flags/china.eps:
First import - 3.23.10
Docs/Flags/china.gif:
First import - 3.23.10
Docs/Flags/china.txt:
First import - 3.23.10
Docs/Flags/croatia.eps:
First import - 3.23.10
Docs/Flags/croatia.gif:
First import - 3.23.10
Docs/Flags/croatia.txt:
First import - 3.23.10
Docs/Flags/czech-republic.eps:
First import - 3.23.10
Docs/Flags/czech-republic.gif:
First import - 3.23.10
Docs/Flags/czech-republic.txt:
First import - 3.23.10
Docs/Flags/denmark.eps:
First import - 3.23.10
Docs/Flags/denmark.gif:
First import - 3.23.10
Docs/Flags/denmark.txt:
First import - 3.23.10
Docs/Flags/estonia.eps:
First import - 3.23.10
Docs/Flags/estonia.gif:
First import - 3.23.10
Docs/Flags/estonia.txt:
First import - 3.23.10
Docs/Flags/finland.eps:
First import - 3.23.10
Docs/Flags/finland.gif:
First import - 3.23.10
Docs/Flags/finland.txt:
First import - 3.23.10
Docs/Flags/france.eps:
First import - 3.23.10
Docs/Flags/france.gif:
First import - 3.23.10
Docs/Flags/france.txt:
First import - 3.23.10
Docs/Flags/germany.eps:
First import - 3.23.10
Docs/Flags/germany.gif:
First import - 3.23.10
Docs/Flags/germany.txt:
First import - 3.23.10
Docs/Flags/great-britain.eps:
First import - 3.23.10
Docs/Flags/great-britain.gif:
First import - 3.23.10
Docs/Flags/great-britain.txt:
First import - 3.23.10
Docs/Flags/greece.eps:
First import - 3.23.10
Docs/Flags/greece.gif:
First import - 3.23.10
Docs/Flags/greece.txt:
First import - 3.23.10
Docs/Flags/hungary.eps:
First import - 3.23.10
Docs/Flags/hungary.gif:
First import - 3.23.10
Docs/Flags/hungary.txt:
First import - 3.23.10
Docs/Flags/iceland.eps:
First import - 3.23.10
Docs/Flags/iceland.gif:
First import - 3.23.10
Docs/Flags/iceland.txt:
First import - 3.23.10
Docs/Flags/ireland.eps:
First import - 3.23.10
Docs/Flags/ireland.gif:
First import - 3.23.10
Docs/Flags/ireland.txt:
First import - 3.23.10
Docs/Flags/island.eps:
First import - 3.23.10
Docs/Flags/island.gif:
First import - 3.23.10
Docs/Flags/island.txt:
First import - 3.23.10
Docs/Flags/israel.eps:
First import - 3.23.10
Docs/Flags/israel.gif:
First import - 3.23.10
Docs/Flags/israel.txt:
First import - 3.23.10
Docs/Flags/italy.eps:
First import - 3.23.10
Docs/Flags/italy.gif:
First import - 3.23.10
Docs/Flags/italy.txt:
First import - 3.23.10
Docs/Flags/japan.eps:
First import - 3.23.10
Docs/Flags/japan.gif:
First import - 3.23.10
Docs/Flags/japan.txt:
First import - 3.23.10
Docs/Flags/kroatia.eps:
First import - 3.23.10
Docs/Flags/kroatia.gif:
First import - 3.23.10
Docs/Flags/kroatia.txt:
First import - 3.23.10
Docs/Flags/netherlands.eps:
First import - 3.23.10
Docs/Flags/netherlands.gif:
First import - 3.23.10
Docs/Flags/netherlands.txt:
First import - 3.23.10
Docs/Flags/poland.eps:
First import - 3.23.10
Docs/Flags/poland.gif:
First import - 3.23.10
Docs/Flags/poland.txt:
First import - 3.23.10
Docs/Flags/portugal.eps:
First import - 3.23.10
Docs/Flags/portugal.gif:
First import - 3.23.10
Docs/Flags/portugal.txt:
First import - 3.23.10
Docs/Flags/romania.eps:
First import - 3.23.10
Docs/Flags/romania.gif:
First import - 3.23.10
Docs/Flags/romania.txt:
First import - 3.23.10
Docs/Flags/russia.eps:
First import - 3.23.10
Docs/Flags/russia.gif:
First import - 3.23.10
Docs/Flags/russia.txt:
First import - 3.23.10
Docs/Flags/singapore.eps:
First import - 3.23.10
Docs/Flags/singapore.gif:
First import - 3.23.10
Docs/Flags/singapore.txt:
First import - 3.23.10
Docs/Flags/south-africa.eps:
First import - 3.23.10
Docs/Flags/south-africa.gif:
First import - 3.23.10
Docs/Flags/south-africa.txt:
First import - 3.23.10
Docs/Flags/south-africa1.eps:
First import - 3.23.10
Docs/Flags/south-africa1.gif:
First import - 3.23.10
Docs/Flags/south-africa1.txt:
First import - 3.23.10
Docs/Flags/south-korea.eps:
First import - 3.23.10
Docs/Flags/south-korea.gif:
First import - 3.23.10
Docs/Flags/south-korea.txt:
First import - 3.23.10
Docs/Flags/spain.eps:
First import - 3.23.10
Docs/Flags/spain.gif:
First import - 3.23.10
Docs/Flags/spain.txt:
First import - 3.23.10
Docs/Flags/sweden.eps:
First import - 3.23.10
Docs/Flags/sweden.gif:
First import - 3.23.10
Docs/Flags/sweden.txt:
First import - 3.23.10
Docs/Flags/switzerland.eps:
First import - 3.23.10
Docs/Flags/switzerland.gif:
First import - 3.23.10
Docs/Flags/switzerland.txt:
First import - 3.23.10
Docs/Flags/taiwan.eps:
First import - 3.23.10
Docs/Flags/taiwan.gif:
First import - 3.23.10
Docs/Flags/taiwan.txt:
First import - 3.23.10
Docs/Flags/ukraine.eps:
First import - 3.23.10
Docs/Flags/ukraine.gif:
First import - 3.23.10
Docs/Flags/ukraine.txt:
First import - 3.23.10
Docs/Flags/usa.eps:
First import - 3.23.10
Docs/Flags/usa.gif:
First import - 3.23.10
Docs/Flags/usa.txt:
First import - 3.23.10
Docs/Images/mysql-logo.gif:
First import - 3.23.10
Docs/To-be-included-in-the-manual/MySQL-for-dummies:
First import - 3.23.10
README:
First import - 3.23.10
config.guess:
First import - 3.23.10
dbug/dbug_long.h:
First import - 3.23.10
dbug/example1.c:
First import - 3.23.10
dbug/example2.c:
First import - 3.23.10
dbug/example3.c:
First import - 3.23.10
dbug/factorial.c:
First import - 3.23.10
dbug/main.c:
First import - 3.23.10
dbug/monty.doc:
First import - 3.23.10
dbug/readme.prof:
First import - 3.23.10
dbug/sanity.c:
First import - 3.23.10
dbug/user.r:
First import - 3.23.10
heap/ChangeLog:
First import - 3.23.10
install-sh:
First import - 3.23.10
ltconfig:
First import - 3.23.10
ltmain.sh:
First import - 3.23.10
missing:
First import - 3.23.10
mit-pthreads/COPYRIGHT:
First import - 3.23.10
mit-pthreads/FAQ:
First import - 3.23.10
mit-pthreads/NOTES_OSR5_BUILD_SKUNKWARE97:
First import - 3.23.10
mit-pthreads/NOTES:
First import - 3.23.10
mit-pthreads/README:
First import - 3.23.10
mit-pthreads/TODO-mysql:
First import - 3.23.10
mit-pthreads/Whats_New:
First import - 3.23.10
mit-pthreads/bin/Makefile.in:
First import - 3.23.10
mit-pthreads/bin/finger/Makefile.in:
First import - 3.23.10
mit-pthreads/bin/finger/finger.c:
First import - 3.23.10
mit-pthreads/bin/finger/net.c:
First import - 3.23.10
mit-pthreads/config/COPYING.GNU:
First import - 3.23.10
mit-pthreads/config/COPYRIGHT:
First import - 3.23.10
mit-pthreads/config/GNUmakefile.in:
First import - 3.23.10
mit-pthreads/config/Makefile.in:
First import - 3.23.10
mit-pthreads/config/acconfig.h:
First import - 3.23.10
mit-pthreads/config/aclocal.m4:
First import - 3.23.10
mit-pthreads/config/config.flags.in:
First import - 3.23.10
mit-pthreads/config/config.guess:
First import - 3.23.10
mit-pthreads/config/config.sub:
First import - 3.23.10
mit-pthreads/config/configure.org:
First import - 3.23.10
mit-pthreads/config/install-sh:
First import - 3.23.10
mit-pthreads/configure:
First import - 3.23.10
mit-pthreads/gen/GNUmakefile.inc:
First import - 3.23.10
mit-pthreads/gen/Makefile.inc:
First import - 3.23.10
mit-pthreads/gen/ctime.c:
First import - 3.23.10
mit-pthreads/gen/difftime.c:
First import - 3.23.10
mit-pthreads/gen/directory.c:
First import - 3.23.10
mit-pthreads/gen/eprintf.c:
First import - 3.23.10
mit-pthreads/gen/getcwd.c:
First import - 3.23.10
mit-pthreads/gen/getpwent.c:
First import - 3.23.10
mit-pthreads/gen/getpwnamuid.c:
First import - 3.23.10
mit-pthreads/gen/getwd.c:
First import - 3.23.10
mit-pthreads/gen/isatty.c:
First import - 3.23.10
mit-pthreads/gen/popen.c:
First import - 3.23.10
mit-pthreads/gen/pwd_internal.c:
First import - 3.23.10
mit-pthreads/gen/pwd_internal.h:
First import - 3.23.10
mit-pthreads/gen/syslog.c:
First import - 3.23.10
mit-pthreads/gen/time.c:
First import - 3.23.10
mit-pthreads/include/Makefile.inc:
First import - 3.23.10
mit-pthreads/include/arpa/inet.h:
First import - 3.23.10
mit-pthreads/include/arpa/nameser.h:
First import - 3.23.10
mit-pthreads/include/dirent.h:
First import - 3.23.10
mit-pthreads/include/endian.h:
First import - 3.23.10
mit-pthreads/include/errno.h:
First import - 3.23.10
mit-pthreads/include/math.h:
First import - 3.23.10
mit-pthreads/include/netdb.h:
First import - 3.23.10
mit-pthreads/include/pthread.h:
First import - 3.23.10
mit-pthreads/include/pthread/cleanup.h:
First import - 3.23.10
mit-pthreads/include/pthread/debug_out.h:
First import - 3.23.10
mit-pthreads/include/pthread/fd.h:
First import - 3.23.10
mit-pthreads/include/pthread/fd_pipe.h:
First import - 3.23.10
mit-pthreads/include/pthread/kernel.h:
First import - 3.23.10
mit-pthreads/include/pthread/kthread.h:
First import - 3.23.10
mit-pthreads/include/pthread/mutex.h:
First import - 3.23.10
mit-pthreads/include/pthread/prio_queue.h:
First import - 3.23.10
mit-pthreads/include/pthread/pthread_attr.h:
First import - 3.23.10
mit-pthreads/include/pthread/pthread_once.h:
First import - 3.23.10
mit-pthreads/include/pthread/queue.h:
First import - 3.23.10
mit-pthreads/include/pthread/sleep.h:
First import - 3.23.10
mit-pthreads/include/pthread/specific.h:
First import - 3.23.10
mit-pthreads/include/pthread/state.def:
First import - 3.23.10
mit-pthreads/include/pthread/types.h:
First import - 3.23.10
mit-pthreads/include/pthread/unistd.h:
First import - 3.23.10
mit-pthreads/include/pthread/util.h:
First import - 3.23.10
mit-pthreads/include/pthread/version.h:
First import - 3.23.10
mit-pthreads/include/pthread/xtypes.h:
First import - 3.23.10
mit-pthreads/include/pwd.h:
First import - 3.23.10
mit-pthreads/include/resolv.h:
First import - 3.23.10
mit-pthreads/include/sched.h:
First import - 3.23.10
mit-pthreads/include/signal.h:
First import - 3.23.10
mit-pthreads/include/stdio.h:
First import - 3.23.10
mit-pthreads/include/stdlib.h:
First import - 3.23.10
mit-pthreads/include/string.h:
First import - 3.23.10
mit-pthreads/include/syslog.h:
First import - 3.23.10
mit-pthreads/include/time.h:
First import - 3.23.10
mit-pthreads/include/timers.h:
First import - 3.23.10
mit-pthreads/include/tzfile.h:
First import - 3.23.10
mit-pthreads/include/unistd.h:
First import - 3.23.10
mit-pthreads/lib/Makefile.in:
First import - 3.23.10
mit-pthreads/lib/libpthreadutil/Makefile.in:
First import - 3.23.10
mit-pthreads/lib/libpthreadutil/pthread_atexit.c:
First import - 3.23.10
mit-pthreads/lib/libpthreadutil/pthread_tad.c:
First import - 3.23.10
mit-pthreads/lib/libpthreadutil/pthreadutil.h:
First import - 3.23.10
mit-pthreads/machdep/alpha-osf1/__math.h:
First import - 3.23.10
mit-pthreads/machdep/alpha-osf1/__signal.h:
First import - 3.23.10
mit-pthreads/machdep/alpha-osf1/__stdio.h:
First import - 3.23.10
mit-pthreads/machdep/alpha-osf1/__stdlib.h:
First import - 3.23.10
mit-pthreads/machdep/alpha-osf1/__string.h:
First import - 3.23.10
mit-pthreads/machdep/alpha-osf1/__time.h:
First import - 3.23.10
mit-pthreads/machdep/alpha-osf1/__unistd.h:
First import - 3.23.10
mit-pthreads/machdep/alpha-osf1/cdefs.h:
First import - 3.23.10
mit-pthreads/machdep/alpha-osf1/compat.h:
First import - 3.23.10
mit-pthreads/machdep/alpha-osf1/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/alpha-osf1/signal.h:
First import - 3.23.10
mit-pthreads/machdep/alpha-osf1/socket.h:
First import - 3.23.10
mit-pthreads/machdep/alpha-osf1/timers.h:
First import - 3.23.10
mit-pthreads/machdep/alpha-osf1/uio.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-1.1/compat.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-1.1/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-1.1/errno.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-1.1/socket.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-1.1/timers.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-2.0/__math.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-2.0/__path.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-2.0/__signal.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-2.0/__stdio.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-2.0/__stdlib.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-2.0/__string.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-2.0/__time.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-2.0/__unistd.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-2.0/compat.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-2.0/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-2.0/errno.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-2.0/time.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-2.0/timers.h:
First import - 3.23.10
mit-pthreads/machdep/bsdi-2.0/wait.h:
First import - 3.23.10
mit-pthreads/machdep/engine-alpha-netbsd-1.1.c:
First import - 3.23.10
mit-pthreads/machdep/engine-alpha-netbsd-1.1.h:
First import - 3.23.10
mit-pthreads/machdep/engine-alpha-netbsd-1.3.c:
First import - 3.23.10
mit-pthreads/machdep/engine-alpha-netbsd-1.3.h:
First import - 3.23.10
mit-pthreads/machdep/engine-alpha-osf1.c:
First import - 3.23.10
mit-pthreads/machdep/engine-alpha-osf1.h:
First import - 3.23.10
mit-pthreads/machdep/engine-arm32-netbsd-1.3.c:
First import - 3.23.10
mit-pthreads/machdep/engine-arm32-netbsd-1.3.h:
First import - 3.23.10
mit-pthreads/machdep/engine-hppa-hpux-10.20.c:
First import - 3.23.10
mit-pthreads/machdep/engine-hppa-hpux-10.20.h:
First import - 3.23.10
mit-pthreads/machdep/engine-hppa-hpux-9.03.c:
First import - 3.23.10
mit-pthreads/machdep/engine-hppa-hpux-9.03.h:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-bsdi-1.1.c:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-bsdi-1.1.h:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-bsdi-2.0.c:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-bsdi-2.0.h:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-freebsd-1.1.c:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-freebsd-1.1.h:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-freebsd-2.0.c:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-freebsd-2.0.h:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-linux-1.0.c:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-linux-1.0.h:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-netbsd-0.9.c:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-netbsd-0.9.h:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-netbsd-1.0.c:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-netbsd-1.0.h:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-netbsd-1.3.c:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-netbsd-1.3.h:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-openbsd-2.0.c:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-openbsd-2.0.h:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-sco-3.2v5.c:
First import - 3.23.10
mit-pthreads/machdep/engine-i386-sco-3.2v5.h:
First import - 3.23.10
mit-pthreads/machdep/engine-ip22-irix-5.2.c:
First import - 3.23.10
mit-pthreads/machdep/engine-ip22-irix-5.2.h:
First import - 3.23.10
mit-pthreads/machdep/engine-m68000-netbsd.c:
First import - 3.23.10
mit-pthreads/machdep/engine-m68000-netbsd.h:
First import - 3.23.10
mit-pthreads/machdep/engine-r2000-ultrix-4.2.c:
First import - 3.23.10
mit-pthreads/machdep/engine-r2000-ultrix-4.2.h:
First import - 3.23.10
mit-pthreads/machdep/engine-romp-bsd.c:
First import - 3.23.10
mit-pthreads/machdep/engine-romp-bsd.h:
First import - 3.23.10
mit-pthreads/machdep/engine-sparc-netbsd-1.3.c:
First import - 3.23.10
mit-pthreads/machdep/engine-sparc-netbsd-1.3.h:
First import - 3.23.10
mit-pthreads/machdep/engine-sparc-sunos-4.1.3.c:
First import - 3.23.10
mit-pthreads/machdep/engine-sparc-sunos-4.1.3.h:
First import - 3.23.10
mit-pthreads/machdep/engine-sparc-sunos-5.3.c:
First import - 3.23.10
mit-pthreads/machdep/engine-sparc-sunos-5.3.h:
First import - 3.23.10
mit-pthreads/machdep/freebsd-1.1/compat.h:
First import - 3.23.10
mit-pthreads/machdep/freebsd-1.1/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/freebsd-1.1/socket.h:
First import - 3.23.10
mit-pthreads/machdep/freebsd-1.1/timers.h:
First import - 3.23.10
mit-pthreads/machdep/freebsd-2.0/__math.h:
First import - 3.23.10
mit-pthreads/machdep/freebsd-2.0/__path.h:
First import - 3.23.10
mit-pthreads/machdep/freebsd-2.0/__signal.h:
First import - 3.23.10
mit-pthreads/machdep/freebsd-2.0/__stdio.h:
First import - 3.23.10
mit-pthreads/machdep/freebsd-2.0/__stdlib.h:
First import - 3.23.10
mit-pthreads/machdep/freebsd-2.0/__string.h:
First import - 3.23.10
mit-pthreads/machdep/freebsd-2.0/__time.h:
First import - 3.23.10
mit-pthreads/machdep/freebsd-2.0/__unistd.h:
First import - 3.23.10
mit-pthreads/machdep/freebsd-2.0/compat.h:
First import - 3.23.10
mit-pthreads/machdep/freebsd-2.0/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/freebsd-2.0/errno.h:
First import - 3.23.10
mit-pthreads/machdep/freebsd-2.0/timers.h:
First import - 3.23.10
mit-pthreads/machdep/freebsd-2.0/wait.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-10.20/__math.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-10.20/__signal.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-10.20/__stdio.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-10.20/__stdlib.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-10.20/__string.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-10.20/__time.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-10.20/__unistd.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-10.20/cdefs.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-10.20/compat.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-10.20/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-10.20/socket.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-10.20/stdtypes.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-10.20/time.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-10.20/timers.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-10.20/uio.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-10.20/wait.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-9.03/__math.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-9.03/__signal.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-9.03/__stdio.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-9.03/__stdlib.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-9.03/__string.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-9.03/__time.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-9.03/__unistd.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-9.03/cdefs.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-9.03/compat.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-9.03/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-9.03/socket.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-9.03/stdtypes.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-9.03/time.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-9.03/timers.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-9.03/uio.h:
First import - 3.23.10
mit-pthreads/machdep/hpux-9.03/wait.h:
First import - 3.23.10
mit-pthreads/machdep/i386-sco-3.2v5/__math.h:
First import - 3.23.10
mit-pthreads/machdep/i386-sco-3.2v5/__signal.h:
First import - 3.23.10
mit-pthreads/machdep/i386-sco-3.2v5/__stdio.h:
First import - 3.23.10
mit-pthreads/machdep/i386-sco-3.2v5/__stdlib.h:
First import - 3.23.10
mit-pthreads/machdep/i386-sco-3.2v5/__string.h:
First import - 3.23.10
mit-pthreads/machdep/i386-sco-3.2v5/__time.h:
First import - 3.23.10
mit-pthreads/machdep/i386-sco-3.2v5/__unistd.h:
First import - 3.23.10
mit-pthreads/machdep/i386-sco-3.2v5/compat.h:
First import - 3.23.10
mit-pthreads/machdep/i386-sco-3.2v5/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/i386-sco-3.2v5/posix/__signal.h:
First import - 3.23.10
mit-pthreads/machdep/i386-sco-3.2v5/socket.h:
First import - 3.23.10
mit-pthreads/machdep/i386-sco-3.2v5/syscall.h:
First import - 3.23.10
mit-pthreads/machdep/i386-sco-3.2v5/timers.h:
First import - 3.23.10
mit-pthreads/machdep/i386-sco-3.2v5/trash.can:
First import - 3.23.10
mit-pthreads/machdep/irix-5.2/__math.h:
First import - 3.23.10
mit-pthreads/machdep/irix-5.2/__signal.h:
First import - 3.23.10
mit-pthreads/machdep/irix-5.2/__stdio.h:
First import - 3.23.10
mit-pthreads/machdep/irix-5.2/__stdlib.h:
First import - 3.23.10
mit-pthreads/machdep/irix-5.2/__string.h:
First import - 3.23.10
mit-pthreads/machdep/irix-5.2/__time.h:
First import - 3.23.10
mit-pthreads/machdep/irix-5.2/__unistd.h:
First import - 3.23.10
mit-pthreads/machdep/irix-5.2/compat.h:
First import - 3.23.10
mit-pthreads/machdep/irix-5.2/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/irix-5.2/socket.h:
First import - 3.23.10
mit-pthreads/machdep/irix-5.2/timers.h:
First import - 3.23.10
mit-pthreads/machdep/irix-5.2/wait.h:
First import - 3.23.10
mit-pthreads/machdep/linux-1.0/__math.h:
First import - 3.23.10
mit-pthreads/machdep/linux-1.0/__path.h:
First import - 3.23.10
mit-pthreads/machdep/linux-1.0/__signal.h:
First import - 3.23.10
mit-pthreads/machdep/linux-1.0/__stdio.h:
First import - 3.23.10
mit-pthreads/machdep/linux-1.0/__stdlib.h:
First import - 3.23.10
mit-pthreads/machdep/linux-1.0/__string.h:
First import - 3.23.10
mit-pthreads/machdep/linux-1.0/__time.h:
First import - 3.23.10
mit-pthreads/machdep/linux-1.0/__unistd.h:
First import - 3.23.10
mit-pthreads/machdep/linux-1.0/cdefs.h:
First import - 3.23.10
mit-pthreads/machdep/linux-1.0/compat.h:
First import - 3.23.10
mit-pthreads/machdep/linux-1.0/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/linux-1.0/errno.h:
First import - 3.23.10
mit-pthreads/machdep/linux-1.0/socket.h:
First import - 3.23.10
mit-pthreads/machdep/linux-1.0/timers.h:
First import - 3.23.10
mit-pthreads/machdep/linux-1.0/uio.h:
First import - 3.23.10
mit-pthreads/machdep/linux-1.0/wait.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-0.9/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.0/__math.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.0/__path.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.0/__signal.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.0/__stdio.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.0/__stdlib.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.0/__string.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.0/__time.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.0/__unistd.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.0/compat.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.0/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.0/errno.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.0/time.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.0/timers.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.0/wait.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.1/__math.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.1/__path.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.1/__signal.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.1/__stdio.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.1/__stdlib.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.1/__string.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.1/__time.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.1/__unistd.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.1/compat.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.1/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.1/errno.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.1/time.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.1/timers.h:
First import - 3.23.10
mit-pthreads/machdep/netbsd-1.1/wait.h:
First import - 3.23.10
mit-pthreads/machdep/openbsd-2.0/__math.h:
First import - 3.23.10
mit-pthreads/machdep/openbsd-2.0/__path.h:
First import - 3.23.10
mit-pthreads/machdep/openbsd-2.0/__signal.h:
First import - 3.23.10
mit-pthreads/machdep/openbsd-2.0/__stdio.h:
First import - 3.23.10
mit-pthreads/machdep/openbsd-2.0/__stdlib.h:
First import - 3.23.10
mit-pthreads/machdep/openbsd-2.0/__string.h:
First import - 3.23.10
mit-pthreads/machdep/openbsd-2.0/__time.h:
First import - 3.23.10
mit-pthreads/machdep/openbsd-2.0/__unistd.h:
First import - 3.23.10
mit-pthreads/machdep/openbsd-2.0/compat.h:
First import - 3.23.10
mit-pthreads/machdep/openbsd-2.0/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/openbsd-2.0/errno.h:
First import - 3.23.10
mit-pthreads/machdep/openbsd-2.0/timers.h:
First import - 3.23.10
mit-pthreads/machdep/openbsd-2.0/wait.h:
First import - 3.23.10
mit-pthreads/machdep/posix-alpha-osf1.h:
First import - 3.23.10
mit-pthreads/machdep/posix-bsdi-1.1.h:
First import - 3.23.10
mit-pthreads/machdep/posix-bsdi-2.0.h:
First import - 3.23.10
mit-pthreads/machdep/posix-freebsd-1.1.h:
First import - 3.23.10
mit-pthreads/machdep/posix-freebsd-2.0.h:
First import - 3.23.10
mit-pthreads/machdep/posix-hpux-10.20.h:
First import - 3.23.10
mit-pthreads/machdep/posix-hpux-9.03.h:
First import - 3.23.10
mit-pthreads/machdep/posix-i386-sco-3.2v5.h:
First import - 3.23.10
mit-pthreads/machdep/posix-irix-5.2.h:
First import - 3.23.10
mit-pthreads/machdep/posix-linux-1.0.h:
First import - 3.23.10
mit-pthreads/machdep/posix-netbsd-0.9.h:
First import - 3.23.10
mit-pthreads/machdep/posix-netbsd-1.0.h:
First import - 3.23.10
mit-pthreads/machdep/posix-netbsd-1.1.h:
First import - 3.23.10
mit-pthreads/machdep/posix-openbsd-2.0.h:
First import - 3.23.10
mit-pthreads/machdep/posix-romp-bsd.h:
First import - 3.23.10
mit-pthreads/machdep/posix-sco-3.2v5.h:
First import - 3.23.10
mit-pthreads/machdep/posix-sunos-4.1.3.h:
First import - 3.23.10
mit-pthreads/machdep/posix-sunos-5.3.h:
First import - 3.23.10
mit-pthreads/machdep/posix-sunos-5.5.h:
First import - 3.23.10
mit-pthreads/machdep/posix-ultrix-4.2.h:
First import - 3.23.10
mit-pthreads/machdep/sco-3.2v5/__math.h:
First import - 3.23.10
mit-pthreads/machdep/sco-3.2v5/__signal.h:
First import - 3.23.10
mit-pthreads/machdep/sco-3.2v5/__stdio.h:
First import - 3.23.10
mit-pthreads/machdep/sco-3.2v5/__stdlib.h:
First import - 3.23.10
mit-pthreads/machdep/sco-3.2v5/__string.h:
First import - 3.23.10
mit-pthreads/machdep/sco-3.2v5/__time.h:
First import - 3.23.10
mit-pthreads/machdep/sco-3.2v5/__unistd.h:
First import - 3.23.10
mit-pthreads/machdep/sco-3.2v5/compat.h:
First import - 3.23.10
mit-pthreads/machdep/sco-3.2v5/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/sco-3.2v5/posix/__signal.h:
First import - 3.23.10
mit-pthreads/machdep/sco-3.2v5/socket.h:
First import - 3.23.10
mit-pthreads/machdep/sco-3.2v5/syscall.h:
First import - 3.23.10
mit-pthreads/machdep/sco-3.2v5/timers.h:
First import - 3.23.10
mit-pthreads/machdep/sco-3.2v5/trash.can:
First import - 3.23.10
mit-pthreads/machdep/sunos-4.1.3/__math.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-4.1.3/__path.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-4.1.3/__signal.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-4.1.3/__stdio.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-4.1.3/__stdlib.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-4.1.3/__string.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-4.1.3/__time.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-4.1.3/__unistd.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-4.1.3/cdefs.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-4.1.3/compat.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-4.1.3/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-4.1.3/fcntlcom.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-4.1.3/signal.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-4.1.3/stat.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-4.1.3/time.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-4.1.3/timers.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-4.1.3/wait.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.3/__math.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.3/__signal.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.3/__stdio.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.3/__stdlib.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.3/__string.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.3/__time.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.3/__unistd.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.3/cdefs.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.3/compat.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.3/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.3/socket.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.3/timers.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.3/uio.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.5/__math.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.5/__signal.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.5/__stdio.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.5/__stdlib.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.5/__string.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.5/__time.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.5/__unistd.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.5/cdefs.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.5/compat.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.5/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.5/socket.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.5/timers.h:
First import - 3.23.10
mit-pthreads/machdep/sunos-5.5/uio.h:
First import - 3.23.10
mit-pthreads/machdep/syscall-alpha-netbsd-1.1.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-alpha-netbsd-1.3.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-alpha-osf1.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-arm32-netbsd-1.3.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-hppa-hpux-10.20.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-hppa-hpux-9.03.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-i386-bsdi-1.1.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-i386-bsdi-2.0.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-i386-freebsd-1.1.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-i386-freebsd-2.0.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-i386-linux-1.0.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-i386-netbsd-0.9.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-i386-netbsd-1.0.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-i386-netbsd-1.1.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-i386-netbsd-1.3.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-i386-openbsd-2.0.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-i386-sco-3.2v5.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-ip22-irix-5.2.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-m68000-netbsd.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-r2000-ultrix-4.2.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-romp-bsd.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-sparc-netbsd-1.1.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-sparc-netbsd-1.3.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-sparc-sunos-4.1.3.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-sparc-sunos-5.3.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-sparc-sunos4.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-alpha-netbsd-1.1.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-alpha-netbsd-1.3.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-alpha-osf1.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-arm32-netbsd-1.3.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-hppa-hpux-10.20.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-hppa-hpux-9.03.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-i386-bsdi-2.0.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-i386-freebsd-2.0.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-i386-netbsd-1.1.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-i386-netbsd-1.3.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-i386-netbsd1.0.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-i386-openbsd-2.0.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-i386-sco-3.2v5.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-ip22-irix-5.2.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-m68000-netbsd.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-r2000-ultrix-4.2.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-sparc-netbsd-1.1.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-sparc-netbsd-1.3.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-sparc-sunos-5.3.S:
First import - 3.23.10
mit-pthreads/machdep/syscall-template-sparc-sunos4.S:
First import - 3.23.10
mit-pthreads/machdep/ultrix-4.2/__math.h:
First import - 3.23.10
mit-pthreads/machdep/ultrix-4.2/__signal.h:
First import - 3.23.10
mit-pthreads/machdep/ultrix-4.2/__stdio.h:
First import - 3.23.10
mit-pthreads/machdep/ultrix-4.2/__stdlib.h:
First import - 3.23.10
mit-pthreads/machdep/ultrix-4.2/__string.h:
First import - 3.23.10
mit-pthreads/machdep/ultrix-4.2/__time.h:
First import - 3.23.10
mit-pthreads/machdep/ultrix-4.2/__unistd.h:
First import - 3.23.10
mit-pthreads/machdep/ultrix-4.2/cdefs.h:
First import - 3.23.10
mit-pthreads/machdep/ultrix-4.2/compat.h:
First import - 3.23.10
mit-pthreads/machdep/ultrix-4.2/dirent.h:
First import - 3.23.10
mit-pthreads/machdep/ultrix-4.2/errno.h:
First import - 3.23.10
mit-pthreads/machdep/ultrix-4.2/time.h:
First import - 3.23.10
mit-pthreads/machdep/ultrix-4.2/timers.h:
First import - 3.23.10
mit-pthreads/machdep/ultrix-4.2/wait.h:
First import - 3.23.10
mit-pthreads/machdep/unistd-i386-freebsd-1.1.h:
First import - 3.23.10
mit-pthreads/machdep/unistd-i386-linux-1.0.h:
First import - 3.23.10
mit-pthreads/machdep/unistd-sparc-sunos-4.1.3.h:
First import - 3.23.10
mit-pthreads/net/GNUmakefile.inc:
First import - 3.23.10
mit-pthreads/net/gethostbyaddr.c:
First import - 3.23.10
mit-pthreads/net/gethostbyname.c:
First import - 3.23.10
mit-pthreads/net/gethostent.c:
First import - 3.23.10
mit-pthreads/net/getnetbyaddr.c:
First import - 3.23.10
mit-pthreads/net/getnetbyname.c:
First import - 3.23.10
mit-pthreads/net/getnetent.c:
First import - 3.23.10
mit-pthreads/net/getproto.c:
First import - 3.23.10
mit-pthreads/net/getprotoent.c:
First import - 3.23.10
mit-pthreads/net/getprotoname.c:
First import - 3.23.10
mit-pthreads/net/getservbyname.c:
First import - 3.23.10
mit-pthreads/net/getservbyport.c:
First import - 3.23.10
mit-pthreads/net/getservent.c:
First import - 3.23.10
mit-pthreads/net/herror.c:
First import - 3.23.10
mit-pthreads/net/inet_addr.c:
First import - 3.23.10
mit-pthreads/net/inet_lnaof.c:
First import - 3.23.10
mit-pthreads/net/inet_makeaddr.c:
First import - 3.23.10
mit-pthreads/net/inet_netof.c:
First import - 3.23.10
mit-pthreads/net/inet_network.c:
First import - 3.23.10
mit-pthreads/net/inet_ntoa.c:
First import - 3.23.10
mit-pthreads/net/net_internal.c:
First import - 3.23.10
mit-pthreads/net/net_internal.h:
First import - 3.23.10
mit-pthreads/net/proto_internal.c:
First import - 3.23.10
mit-pthreads/net/proto_internal.h:
First import - 3.23.10
mit-pthreads/net/res_comp.c:
First import - 3.23.10
mit-pthreads/net/res_debug.c:
First import - 3.23.10
mit-pthreads/net/res_init.c:
First import - 3.23.10
mit-pthreads/net/res_internal.c:
First import - 3.23.10
mit-pthreads/net/res_internal.h:
First import - 3.23.10
mit-pthreads/net/res_mkquery.c:
First import - 3.23.10
mit-pthreads/net/res_query.c:
First import - 3.23.10
mit-pthreads/net/res_querydomain.c:
First import - 3.23.10
mit-pthreads/net/res_search.c:
First import - 3.23.10
mit-pthreads/net/res_send.c:
First import - 3.23.10
mit-pthreads/net/serv_internal.c:
First import - 3.23.10
mit-pthreads/net/serv_internal.h:
First import - 3.23.10
mit-pthreads/patches/Streepy.html:
First import - 3.23.10
mit-pthreads/patches/Streepy2.html:
First import - 3.23.10
mit-pthreads/patches/bill_lear:
First import - 3.23.10
mit-pthreads/patches/chris_demetriou:
First import - 3.23.10
mit-pthreads/patches/mevans:
First import - 3.23.10
mit-pthreads/patches/p153:
First import - 3.23.10
mit-pthreads/patches/p155:
First import - 3.23.10
mit-pthreads/pg++:
First import - 3.23.10
mit-pthreads/pgcc:
First import - 3.23.10
mit-pthreads/pthreads/GNUmakefile.inc:
First import - 3.23.10
mit-pthreads/pthreads/Makefile.inc:
First import - 3.23.10
mit-pthreads/pthreads/_exit.c:
First import - 3.23.10
mit-pthreads/pthreads/cleanup.c:
First import - 3.23.10
mit-pthreads/pthreads/cond.c:
First import - 3.23.10
mit-pthreads/pthreads/condattr.c:
First import - 3.23.10
mit-pthreads/pthreads/dump_state.c:
First import - 3.23.10
mit-pthreads/pthreads/errno.c:
First import - 3.23.10
mit-pthreads/pthreads/fd_pipe.c:
First import - 3.23.10
mit-pthreads/pthreads/file.c:
First import - 3.23.10
mit-pthreads/pthreads/globals.c:
First import - 3.23.10
mit-pthreads/pthreads/info.c:
First import - 3.23.10
mit-pthreads/pthreads/init.cc:
First import - 3.23.10
mit-pthreads/pthreads/malloc.c:
First import - 3.23.10
mit-pthreads/pthreads/mutex.c:
First import - 3.23.10
mit-pthreads/pthreads/mutexattr.c:
First import - 3.23.10
mit-pthreads/pthreads/panic.c:
First import - 3.23.10
mit-pthreads/pthreads/prio_queue.c:
First import - 3.23.10
mit-pthreads/pthreads/process.c:
First import - 3.23.10
mit-pthreads/pthreads/pthread.c:
First import - 3.23.10
mit-pthreads/pthreads/pthread_attr.c:
First import - 3.23.10
mit-pthreads/pthreads/pthread_cancel.c:
First import - 3.23.10
mit-pthreads/pthreads/pthread_detach.c:
First import - 3.23.10
mit-pthreads/pthreads/pthread_init.c:
First import - 3.23.10
mit-pthreads/pthreads/pthread_join.c:
First import - 3.23.10
mit-pthreads/pthreads/pthread_kill.c:
First import - 3.23.10
mit-pthreads/pthreads/pthread_once.c:
First import - 3.23.10
mit-pthreads/pthreads/queue.c:
First import - 3.23.10
mit-pthreads/pthreads/readv.c:
First import - 3.23.10
mit-pthreads/pthreads/schedparam.c:
First import - 3.23.10
mit-pthreads/pthreads/select.c:
First import - 3.23.10
mit-pthreads/pthreads/sig.c:
First import - 3.23.10
mit-pthreads/pthreads/sleep.c:
First import - 3.23.10
mit-pthreads/pthreads/specific.c:
First import - 3.23.10
mit-pthreads/pthreads/stat.c:
First import - 3.23.10
mit-pthreads/pthreads/wait.c:
First import - 3.23.10
mit-pthreads/pthreads/writev.c:
First import - 3.23.10
mit-pthreads/scripts/GNUmakefile.inc:
First import - 3.23.10
mit-pthreads/scripts/Makefile.inc:
First import - 3.23.10
mit-pthreads/scripts/pgcc.sh:
First import - 3.23.10
mit-pthreads/stdio/GNUmakefile.inc:
First import - 3.23.10
mit-pthreads/stdio/Makefile.inc:
First import - 3.23.10
mit-pthreads/stdio/README:
First import - 3.23.10
mit-pthreads/stdio/clrerr.c:
First import - 3.23.10
mit-pthreads/stdio/fclose.c:
First import - 3.23.10
mit-pthreads/stdio/fdopen.c:
First import - 3.23.10
mit-pthreads/stdio/feof.c:
First import - 3.23.10
mit-pthreads/stdio/ferror.c:
First import - 3.23.10
mit-pthreads/stdio/fflush.c:
First import - 3.23.10
mit-pthreads/stdio/fgetc.c:
First import - 3.23.10
mit-pthreads/stdio/fgetline.c:
First import - 3.23.10
mit-pthreads/stdio/fgetpos.c:
First import - 3.23.10
mit-pthreads/stdio/fgets.c:
First import - 3.23.10
mit-pthreads/stdio/fileno.c:
First import - 3.23.10
mit-pthreads/stdio/findfp.c:
First import - 3.23.10
mit-pthreads/stdio/flags.c:
First import - 3.23.10
mit-pthreads/stdio/floatio.h:
First import - 3.23.10
mit-pthreads/stdio/fopen.c:
First import - 3.23.10
mit-pthreads/stdio/fprintf.c:
First import - 3.23.10
mit-pthreads/stdio/fpurge.c:
First import - 3.23.10
mit-pthreads/stdio/fputc.c:
First import - 3.23.10
mit-pthreads/stdio/fputs.c:
First import - 3.23.10
mit-pthreads/stdio/fread.c:
First import - 3.23.10
mit-pthreads/stdio/freopen.c:
First import - 3.23.10
mit-pthreads/stdio/fscanf.c:
First import - 3.23.10
mit-pthreads/stdio/fseek.c:
First import - 3.23.10
mit-pthreads/stdio/fsetpos.c:
First import - 3.23.10
mit-pthreads/stdio/ftell.c:
First import - 3.23.10
mit-pthreads/stdio/funopen.c:
First import - 3.23.10
mit-pthreads/stdio/fvwrite.c:
First import - 3.23.10
mit-pthreads/stdio/fvwrite.h:
First import - 3.23.10
mit-pthreads/stdio/fwalk.c:
First import - 3.23.10
mit-pthreads/stdio/fwrite.c:
First import - 3.23.10
mit-pthreads/stdio/getc.c:
First import - 3.23.10
mit-pthreads/stdio/getc_unlocked.c:
First import - 3.23.10
mit-pthreads/stdio/getchar.c:
First import - 3.23.10
mit-pthreads/stdio/getchar_unlocked.c:
First import - 3.23.10
mit-pthreads/stdio/gets.c:
First import - 3.23.10
mit-pthreads/stdio/getw.c:
First import - 3.23.10
mit-pthreads/stdio/glue.h:
First import - 3.23.10
mit-pthreads/stdio/local.h:
First import - 3.23.10
mit-pthreads/stdio/makebuf.c:
First import - 3.23.10
mit-pthreads/stdio/mktemp.c:
First import - 3.23.10
mit-pthreads/stdio/perror.c:
First import - 3.23.10
mit-pthreads/stdio/printf.c:
First import - 3.23.10
mit-pthreads/stdio/putc.c:
First import - 3.23.10
mit-pthreads/stdio/putc_unlocked.c:
First import - 3.23.10
mit-pthreads/stdio/putchar.c:
First import - 3.23.10
mit-pthreads/stdio/putchar_unlocked.c:
First import - 3.23.10
mit-pthreads/stdio/puts.c:
First import - 3.23.10
mit-pthreads/stdio/putw.c:
First import - 3.23.10
mit-pthreads/stdio/refill.c:
First import - 3.23.10
mit-pthreads/stdio/remove.c:
First import - 3.23.10
mit-pthreads/stdio/rewind.c:
First import - 3.23.10
mit-pthreads/stdio/rget.c:
First import - 3.23.10
mit-pthreads/stdio/scanf.c:
First import - 3.23.10
mit-pthreads/stdio/setbuf.c:
First import - 3.23.10
mit-pthreads/stdio/setbuffer.c:
First import - 3.23.10
mit-pthreads/stdio/setvbuf.c:
First import - 3.23.10
mit-pthreads/stdio/snprintf.c:
First import - 3.23.10
mit-pthreads/stdio/sprintf.c:
First import - 3.23.10
mit-pthreads/stdio/sscanf.c:
First import - 3.23.10
mit-pthreads/stdio/stdio.c:
First import - 3.23.10
mit-pthreads/stdio/strerror.c:
First import - 3.23.10
mit-pthreads/stdio/tempnam.c:
First import - 3.23.10
mit-pthreads/stdio/tmpfile.c:
First import - 3.23.10
mit-pthreads/stdio/tmpnam.c:
First import - 3.23.10
mit-pthreads/stdio/ungetc.c:
First import - 3.23.10
mit-pthreads/stdio/vfprintf.c:
First import - 3.23.10
mit-pthreads/stdio/vfscanf.c:
First import - 3.23.10
mit-pthreads/stdio/vprintf.c:
First import - 3.23.10
mit-pthreads/stdio/vscanf.c:
First import - 3.23.10
mit-pthreads/stdio/vsnprintf.c:
First import - 3.23.10
mit-pthreads/stdio/vsprintf.c:
First import - 3.23.10
mit-pthreads/stdio/vsscanf.c:
First import - 3.23.10
mit-pthreads/stdio/wbuf.c:
First import - 3.23.10
mit-pthreads/stdio/wsetup.c:
First import - 3.23.10
mit-pthreads/stdio/xprintf.c:
First import - 3.23.10
mit-pthreads/stdlib/GNUmakefile.inc:
First import - 3.23.10
mit-pthreads/stdlib/Makefile.inc:
First import - 3.23.10
mit-pthreads/stdlib/abort.c:
First import - 3.23.10
mit-pthreads/stdlib/atexit.h:
First import - 3.23.10
mit-pthreads/stdlib/exit.c:
First import - 3.23.10
mit-pthreads/stdlib/rand.c:
First import - 3.23.10
mit-pthreads/stdlib/random.c:
First import - 3.23.10
mit-pthreads/stdlib/strtod.c:
First import - 3.23.10
mit-pthreads/stdlib/strtol.c:
First import - 3.23.10
mit-pthreads/stdlib/strtoul.c:
First import - 3.23.10
mit-pthreads/stdlib/system.c:
First import - 3.23.10
mit-pthreads/string/GNUmakefile.inc:
First import - 3.23.10
mit-pthreads/string/Makefile.inc:
First import - 3.23.10
mit-pthreads/string/strtok.c:
First import - 3.23.10
mit-pthreads/tests/Makefile.in:
First import - 3.23.10
mit-pthreads/tests/README:
First import - 3.23.10
mit-pthreads/tests/bench_fcntl.c:
First import - 3.23.10
mit-pthreads/tests/bench_pipe.c:
First import - 3.23.10
mit-pthreads/tests/bench_read.c:
First import - 3.23.10
mit-pthreads/tests/p_bench_getpid.c:
First import - 3.23.10
mit-pthreads/tests/p_bench_mutex.c:
First import - 3.23.10
mit-pthreads/tests/p_bench_pthread_create.c:
First import - 3.23.10
mit-pthreads/tests/p_bench_read.c:
First import - 3.23.10
mit-pthreads/tests/p_bench_semaphore.c:
First import - 3.23.10
mit-pthreads/tests/p_bench_yield.c:
First import - 3.23.10
mit-pthreads/tests/test_create.c:
First import - 3.23.10
mit-pthreads/tests/test_cwd.c:
First import - 3.23.10
mit-pthreads/tests/test_execve.c:
First import - 3.23.10
mit-pthreads/tests/test_fcntl.c:
First import - 3.23.10
mit-pthreads/tests/test_fork.c:
First import - 3.23.10
mit-pthreads/tests/test_netdb.c:
First import - 3.23.10
mit-pthreads/tests/test_pause.c:
First import - 3.23.10
mit-pthreads/tests/test_preemption.c:
First import - 3.23.10
mit-pthreads/tests/test_preemption_float.c:
First import - 3.23.10
mit-pthreads/tests/test_pthread_cond_timedwait.c:
First import - 3.23.10
mit-pthreads/tests/test_pthread_join.c:
First import - 3.23.10
mit-pthreads/tests/test_pthread_mutex.c:
First import - 3.23.10
mit-pthreads/tests/test_pw.c:
First import - 3.23.10
mit-pthreads/tests/test_readdir.c:
First import - 3.23.10
mit-pthreads/tests/test_select.c:
First import - 3.23.10
mit-pthreads/tests/test_setjmp.c:
First import - 3.23.10
mit-pthreads/tests/test_sleep.c:
First import - 3.23.10
mit-pthreads/tests/test_sock_1.c:
First import - 3.23.10
mit-pthreads/tests/test_sock_2.c:
First import - 3.23.10
mit-pthreads/tests/test_sock_2a.c:
First import - 3.23.10
mit-pthreads/tests/test_stdio_1.c:
First import - 3.23.10
mit-pthreads/tests/test_switch.c:
First import - 3.23.10
mysys/COPYING.LIB:
First import - 3.23.10
mysys/getopt.c:
First import - 3.23.10
readline/COPYING:
First import - 3.23.10
readline/INSTALL:
First import - 3.23.10
readline/Makefile.am:
First import - 3.23.10
readline/README:
First import - 3.23.10
readline/ansi_stdlib.h:
First import - 3.23.10
readline/bind.c:
First import - 3.23.10
readline/callback.c:
First import - 3.23.10
readline/chardefs.h:
First import - 3.23.10
readline/configure.in:
First import - 3.23.10
readline/configure:
First import - 3.23.10
readline/display.c:
First import - 3.23.10
readline/emacs_keymap.c:
First import - 3.23.10
readline/funmap.c:
First import - 3.23.10
readline/histexpand.c:
First import - 3.23.10
readline/histfile.c:
First import - 3.23.10
readline/histlib.h:
First import - 3.23.10
readline/history.c:
First import - 3.23.10
readline/history.h:
First import - 3.23.10
readline/histsearch.c:
First import - 3.23.10
readline/input.c:
First import - 3.23.10
readline/isearch.c:
First import - 3.23.10
readline/keymaps.c:
First import - 3.23.10
readline/keymaps.h:
First import - 3.23.10
readline/kill.c:
First import - 3.23.10
readline/macro.c:
First import - 3.23.10
readline/nls.c:
First import - 3.23.10
readline/parens.c:
First import - 3.23.10
readline/posixdir.h:
First import - 3.23.10
readline/posixjmp.h:
First import - 3.23.10
readline/posixstat.h:
First import - 3.23.10
readline/readline.c:
First import - 3.23.10
readline/readline.h:
First import - 3.23.10
readline/rlconf.h:
First import - 3.23.10
readline/rldefs.h:
First import - 3.23.10
readline/rltty.c:
First import - 3.23.10
readline/rltty.h:
First import - 3.23.10
readline/rlwinsize.h:
First import - 3.23.10
readline/search.c:
First import - 3.23.10
readline/shell.c:
First import - 3.23.10
readline/signals.c:
First import - 3.23.10
readline/tcap.h:
First import - 3.23.10
readline/terminal.c:
First import - 3.23.10
readline/tilde.c:
First import - 3.23.10
readline/tilde.h:
First import - 3.23.10
readline/undo.c:
First import - 3.23.10
readline/util.c:
First import - 3.23.10
readline/vi_keymap.c:
First import - 3.23.10
readline/vi_mode.c:
First import - 3.23.10
readline/xmalloc.c:
First import - 3.23.10
regex/CHANGES:
First import - 3.23.10
regex/COPYRIGHT:
First import - 3.23.10
regex/README:
First import - 3.23.10
regex/WHATSNEW:
First import - 3.23.10
regex/cclass.h:
First import - 3.23.10
regex/cname.h:
First import - 3.23.10
regex/debug.c:
First import - 3.23.10
regex/debug.ih:
First import - 3.23.10
regex/engine.c:
First import - 3.23.10
regex/engine.ih:
First import - 3.23.10
regex/main.ih:
First import - 3.23.10
regex/regcomp.ih:
First import - 3.23.10
regex/regerror.c:
First import - 3.23.10
regex/regerror.ih:
First import - 3.23.10
regex/regex.3:
First import - 3.23.10
regex/regex.7:
First import - 3.23.10
regex/regex.h:
First import - 3.23.10
regex/regfree.c:
First import - 3.23.10
regex/reginit.c:
First import - 3.23.10
regex/split.c:
First import - 3.23.10
regex/tests:
First import - 3.23.10
scripts/msql2mysql.sh:
First import - 3.23.10
scripts/mysql_fix_privilege_tables.sh:
First import - 3.23.10
scripts/mysql_setpermission.sh:
First import - 3.23.10
scripts/mysqlaccess.conf:
First import - 3.23.10
scripts/mysqlbug.sh:
First import - 3.23.10
sql-bench/Data/ATIS/aircraft.txt:
First import - 3.23.10
sql-bench/Data/ATIS/airline.txt:
First import - 3.23.10
sql-bench/Data/ATIS/airport.txt:
First import - 3.23.10
sql-bench/Data/ATIS/airport_service.txt:
First import - 3.23.10
sql-bench/Data/ATIS/city.txt:
First import - 3.23.10
sql-bench/Data/ATIS/class_of_service.txt:
First import - 3.23.10
sql-bench/Data/ATIS/code_description.txt:
First import - 3.23.10
sql-bench/Data/ATIS/compound_class.txt:
First import - 3.23.10
sql-bench/Data/ATIS/connect_leg.txt:
First import - 3.23.10
sql-bench/Data/ATIS/connection.txt:
First import - 3.23.10
sql-bench/Data/ATIS/date_day.txt:
First import - 3.23.10
sql-bench/Data/ATIS/day_name.txt:
First import - 3.23.10
sql-bench/Data/ATIS/dual_carrier.txt:
First import - 3.23.10
sql-bench/Data/ATIS/fare.txt:
First import - 3.23.10
sql-bench/Data/ATIS/flight.txt:
First import - 3.23.10
sql-bench/Data/ATIS/flight_class.txt:
First import - 3.23.10
sql-bench/Data/ATIS/flight_day.txt:
First import - 3.23.10
sql-bench/Data/ATIS/flight_fare.txt:
First import - 3.23.10
sql-bench/Data/ATIS/food_service.txt:
First import - 3.23.10
sql-bench/Data/ATIS/ground_service.txt:
First import - 3.23.10
sql-bench/Data/ATIS/month_name.txt:
First import - 3.23.10
sql-bench/Data/ATIS/restrict_carrier.txt:
First import - 3.23.10
sql-bench/Data/ATIS/restrict_class.txt:
First import - 3.23.10
sql-bench/Data/ATIS/restriction.txt:
First import - 3.23.10
sql-bench/Data/ATIS/state.txt:
First import - 3.23.10
sql-bench/Data/ATIS/stop.txt:
First import - 3.23.10
sql-bench/Data/ATIS/stop1.txt:
First import - 3.23.10
sql-bench/Data/ATIS/time_interval.txt:
First import - 3.23.10
sql-bench/Data/ATIS/time_zone.txt:
First import - 3.23.10
sql-bench/Data/ATIS/transport.txt:
First import - 3.23.10
sql-bench/Data/Wisconsin/onek.data:
First import - 3.23.10
sql-bench/Data/Wisconsin/tenk.data:
First import - 3.23.10
sql-bench/README:
First import - 3.23.10
sql-bench/Results/ATIS-Adabas-Linux_2.0.35_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/ATIS-AdabasD-Linux_2.0.35_i686-cmp-adabasd,mysql:
First import - 3.23.10
sql-bench/Results/ATIS-msql-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/ATIS-mysql-3.21-Linux_2.2.1_i686:
First import - 3.23.10
sql-bench/Results/ATIS-mysql-HP_UX_B.10.20_9000_778:
First import - 3.23.10
sql-bench/Results/ATIS-mysql-Linux_2.0.35_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/ATIS-mysql-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/ATIS-mysql-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/ATIS-mysql-Linux_2.2.10_i686:
First import - 3.23.10
sql-bench/Results/ATIS-mysql-Linux_2.2.1_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/ATIS-mysql-SunOS_5.5.1_sun4u:
First import - 3.23.10
sql-bench/Results/ATIS-mysql-SunOS_5.6_sun4m:
***MISSING WEAVE***
sql-bench/Results/ATIS-mysql-SunOS_5.7_sun4m:
First import - 3.23.10
sql-bench/Results/ATIS-mysql-SunOS_5.7_sun4u:
First import - 3.23.10
sql-bench/Results/ATIS-mysql_3.21-Linux_2.0.35_i686:
First import - 3.23.10
sql-bench/Results/ATIS-mysql_fast-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/ATIS-mysql_odbc-win98:
First import - 3.23.10
sql-bench/Results/ATIS-oracle-Linux_2.0.36_i686-cmp-mysql,oracle:
First import - 3.23.10
sql-bench/Results/ATIS-oracle_fast-Linux_2.0.36_i686-cmp-mysql,oracle:
First import - 3.23.10
sql-bench/Results/ATIS-pg-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/ATIS-pg_fast-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/ATIS-solid-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/RUN-Adabas-Linux_2.0.35_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/RUN-msql-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/RUN-mysql-3.21-Linux_2.2.1_i686:
First import - 3.23.10
sql-bench/Results/RUN-mysql-HP_UX_B.10.20_9000_778:
First import - 3.23.10
sql-bench/Results/RUN-mysql-Linux_2.0.35_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/RUN-mysql-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/RUN-mysql-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/RUN-mysql-Linux_2.2.10_i686:
First import - 3.23.10
sql-bench/Results/RUN-mysql-Linux_2.2.1_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/RUN-mysql-SunOS_5.5.1_sun4u:
First import - 3.23.10
sql-bench/Results/RUN-mysql-SunOS_5.6_sun4m:
***MISSING WEAVE***
sql-bench/Results/RUN-mysql-SunOS_5.7_sun4m:
First import - 3.23.10
sql-bench/Results/RUN-mysql-SunOS_5.7_sun4u:
First import - 3.23.10
sql-bench/Results/RUN-mysql_3.21-Linux_2.0.35_i686:
First import - 3.23.10
sql-bench/Results/RUN-mysql_fast-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/RUN-mysql_odbc-win98:
First import - 3.23.10
sql-bench/Results/RUN-oracle-Linux_2.0.36_i686-cmp-mysql,oracle:
First import - 3.23.10
sql-bench/Results/RUN-oracle_fast-Linux_2.0.36_i686-cmp-mysql,oracle:
First import - 3.23.10
sql-bench/Results/RUN-pg-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/RUN-pg_fast-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/RUN-solid-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/alter-table-Adabas-Linux_2.0.35_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/alter-table-AdabasD-Linux_2.0.35_i686-cmp-adabasd,mysql:
First import - 3.23.10
sql-bench/Results/alter-table-msql-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/alter-table-mysql-3.21-Linux_2.2.1_i686:
First import - 3.23.10
sql-bench/Results/alter-table-mysql-HP_UX_B.10.20_9000_778:
First import - 3.23.10
sql-bench/Results/alter-table-mysql-Linux_2.0.35_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/alter-table-mysql-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/alter-table-mysql-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/alter-table-mysql-Linux_2.2.10_i686:
First import - 3.23.10
sql-bench/Results/alter-table-mysql-Linux_2.2.1_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/alter-table-mysql-SunOS_5.5.1_sun4u:
First import - 3.23.10
sql-bench/Results/alter-table-mysql-SunOS_5.6_sun4m:
***MISSING WEAVE***
sql-bench/Results/alter-table-mysql-SunOS_5.7_sun4m:
First import - 3.23.10
sql-bench/Results/alter-table-mysql-SunOS_5.7_sun4u:
First import - 3.23.10
sql-bench/Results/alter-table-mysql_3.21-Linux_2.0.35_i686:
First import - 3.23.10
sql-bench/Results/alter-table-mysql_fast-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/alter-table-mysql_odbc-win98:
First import - 3.23.10
sql-bench/Results/alter-table-oracle-Linux_2.0.36_i686-cmp-mysql,oracle:
First import - 3.23.10
sql-bench/Results/alter-table-oracle_fast-Linux_2.0.36_i686-cmp-mysql,oracle:
First import - 3.23.10
sql-bench/Results/alter-table-pg-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/alter-table-pg_fast-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/alter-table-solid-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/big-tables-Adabas-Linux_2.0.35_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/big-tables-msql-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/big-tables-mysql-3.21-Linux_2.2.1_i686:
First import - 3.23.10
sql-bench/Results/big-tables-mysql-HP_UX_B.10.20_9000_778:
First import - 3.23.10
sql-bench/Results/big-tables-mysql-Linux_2.0.35_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/big-tables-mysql-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/big-tables-mysql-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/big-tables-mysql-Linux_2.2.10_i686:
First import - 3.23.10
sql-bench/Results/big-tables-mysql-Linux_2.2.1_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/big-tables-mysql-SunOS_5.5.1_sun4u:
First import - 3.23.10
sql-bench/Results/big-tables-mysql-SunOS_5.6_sun4m:
***MISSING WEAVE***
sql-bench/Results/big-tables-mysql-SunOS_5.7_sun4m:
First import - 3.23.10
sql-bench/Results/big-tables-mysql-SunOS_5.7_sun4u:
First import - 3.23.10
sql-bench/Results/big-tables-mysql_3.21-Linux_2.0.35_i686:
First import - 3.23.10
sql-bench/Results/big-tables-mysql_fast-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/big-tables-mysql_odbc-win98:
First import - 3.23.10
sql-bench/Results/big-tables-oracle-Linux_2.0.36_i686-cmp-mysql,oracle:
First import - 3.23.10
sql-bench/Results/big-tables-oracle_fast-Linux_2.0.36_i686-cmp-mysql,oracle:
First import - 3.23.10
sql-bench/Results/big-tables-pg-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/big-tables-pg_fast-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/big-tables-solid-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/connect-Adabas-Linux_2.0.35_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/connect-msql-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/connect-mysql-3.21-Linux_2.2.1_i686:
First import - 3.23.10
sql-bench/Results/connect-mysql-HP_UX_B.10.20_9000_778:
First import - 3.23.10
sql-bench/Results/connect-mysql-Linux_2.0.35_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/connect-mysql-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/connect-mysql-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/connect-mysql-Linux_2.2.10_i686:
First import - 3.23.10
sql-bench/Results/connect-mysql-Linux_2.2.1_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/connect-mysql-SunOS_5.5.1_sun4u:
First import - 3.23.10
sql-bench/Results/connect-mysql-SunOS_5.6_sun4m:
***MISSING WEAVE***
sql-bench/Results/connect-mysql-SunOS_5.7_sun4m:
First import - 3.23.10
sql-bench/Results/connect-mysql-SunOS_5.7_sun4u:
First import - 3.23.10
sql-bench/Results/connect-mysql_3.21-Linux_2.0.35_i686:
First import - 3.23.10
sql-bench/Results/connect-mysql_fast-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/connect-mysql_odbc-win98:
First import - 3.23.10
sql-bench/Results/connect-oracle-Linux_2.0.36_i686-cmp-mysql,oracle:
First import - 3.23.10
sql-bench/Results/connect-pg-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/connect-pg_fast-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/connect-solid-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/create-Adabas-Linux_2.0.35_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/create-msql-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/create-mysql-3.21-Linux_2.2.1_i686:
First import - 3.23.10
sql-bench/Results/create-mysql-HP_UX_B.10.20_9000_778:
First import - 3.23.10
sql-bench/Results/create-mysql-Linux_2.0.35_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/create-mysql-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/create-mysql-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/create-mysql-Linux_2.2.10_i686:
First import - 3.23.10
sql-bench/Results/create-mysql-Linux_2.2.1_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/create-mysql-SunOS_5.5.1_sun4u:
First import - 3.23.10
sql-bench/Results/create-mysql-SunOS_5.6_sun4m:
***MISSING WEAVE***
sql-bench/Results/create-mysql-SunOS_5.7_sun4m:
First import - 3.23.10
sql-bench/Results/create-mysql-SunOS_5.7_sun4u:
First import - 3.23.10
sql-bench/Results/create-mysql_3.21-Linux_2.0.35_i686:
First import - 3.23.10
sql-bench/Results/create-mysql_fast-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/create-mysql_odbc-win98:
First import - 3.23.10
sql-bench/Results/create-oracle-Linux_2.0.36_i686-cmp-mysql,oracle:
First import - 3.23.10
sql-bench/Results/create-oracle_fast-Linux_2.0.36_i686-cmp-mysql,oracle:
First import - 3.23.10
sql-bench/Results/create-pg-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/create-pg_fast-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/insert-mysql-HP_UX_B.10.20_9000_778:
First import - 3.23.10
sql-bench/Results/select-mysql-HP_UX_B.10.20_9000_778:
First import - 3.23.10
sql-bench/Results/wisconsin-mysql-HP_UX_B.10.20_9000_778:
First import - 3.23.10
sql/md5.c:
First import - 3.23.10
sql/share/norwegian-ny/.cvsignore:
First import - 3.23.10
sql/share/norwegian/.cvsignore:
First import - 3.23.10
stamp-h.in:
First import - 3.23.10
strings/ChangeLog:
First import - 3.23.10
strings/bfill.c:
First import - 3.23.10
strings/bmove.c:
First import - 3.23.10
strings/strend.c:
First import - 3.23.10
strings/strstr.c:
First import - 3.23.10
strings/strxnmov.c:
First import - 3.23.10
tests/auto_increment.res:
First import - 3.23.10
tests/auto_increment.tst:
First import - 3.23.10
tests/function.res:
First import - 3.23.10
tests/function.tst:
First import - 3.23.10
tests/grant.res:
First import - 3.23.10
tests/lock_test.res:
First import - 3.23.10
tests/table_types.pl:
First import - 3.23.10
tests/udf_test.res:
First import - 3.23.10
tests/udf_test:
First import - 3.23.10
sql-bench/Results-linux/ATIS-mysql-Linux_2.0.33_i586-cmp-access,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/ATIS-mysql-Linux_2.0.33_i586-cmp-ms-sql,mysql,sybase:
***MISSING WEAVE***
sql-bench/Results-linux/RUN-mysql-Linux_2.0.33_i586-cmp-access,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/RUN-mysql-Linux_2.0.33_i586-cmp-ms-sql,mysql,sybase:
***MISSING WEAVE***
sql-bench/Results-linux/big-tables-mysql-Linux_2.0.33_i586-cmp-access,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/big-tables-mysql-Linux_2.0.33_i586-cmp-ms-sql,mysql,sybase:
***MISSING WEAVE***
sql-bench/Results-linux/connect-mysql-Linux_2.0.33_i586-cmp-access,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/connect-mysql-Linux_2.0.33_i586-cmp-ms-sql,mysql,sybase:
***MISSING WEAVE***
sql-bench/Results-linux/create-mysql-Linux_2.0.33_i586-cmp-access,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/create-mysql-Linux_2.0.33_i586-cmp-ms-sql,mysql,sybase:
***MISSING WEAVE***
sql-bench/Results-linux/insert-mysql-Linux_2.0.33_i586-cmp-access,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/insert-mysql-Linux_2.0.33_i586-cmp-ms-sql,mysql,sybase:
***MISSING WEAVE***
sql-bench/Results-linux/select-mysql-Linux_2.0.33_i586-cmp-access,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/select-mysql-Linux_2.0.33_i586-cmp-ms-sql,mysql,sybase:
***MISSING WEAVE***
sql-bench/Results-linux/wisconsin-mysql-Linux_2.0.33_i586-cmp-access,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/wisconsin-mysql-Linux_2.0.33_i586-cmp-ms-sql,mysql,sybase:
***MISSING WEAVE***
sql-bench/Results-win32/ATIS-db2_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/ATIS-informix_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/ATIS-ms-sql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/ATIS-mysql-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/ATIS-mysql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/ATIS-oracle_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/ATIS-solid_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/ATIS-sybase_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/RUN-db2_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/RUN-informix_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/RUN-ms-sql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/RUN-mysql-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/RUN-mysql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/RUN-oracle_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/RUN-solid_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/RUN-sybase_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/alter-table-db2_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/alter-table-informix_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/alter-table-ms-sql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/alter-table-mysql-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/alter-table-mysql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/alter-table-oracle_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/alter-table-solid_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/alter-table-sybase_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/big-tables-db2_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/big-tables-informix_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/big-tables-ms-sql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/big-tables-mysql-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/big-tables-mysql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/big-tables-oracle_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/big-tables-solid_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/big-tables-sybase_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/connect-db2_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/connect-informix_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/connect-ms-sql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/connect-mysql-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/connect-mysql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/connect-oracle_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/connect-solid_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/connect-sybase_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/create-db2_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/create-informix_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/create-ms-sql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/create-mysql-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/create-mysql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/create-oracle_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/create-solid_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/create-sybase_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/insert-db2_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/insert-informix_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/insert-ms-sql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/insert-mysql-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/insert-mysql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/insert-oracle_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/insert-solid_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/insert-sybase_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/select-db2_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/select-informix_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/select-ms-sql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/select-mysql-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/select-mysql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/select-oracle_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/select-solid_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/wisconsin-db2_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/wisconsin-informix_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/wisconsin-ms-sql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/wisconsin-mysql-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/wisconsin-mysql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/wisconsin-oracle_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results-win32/wisconsin-solid_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase:
First import - 3.23.10
sql-bench/Results/create-solid-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/insert-Adabas-Linux_2.0.35_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/insert-msql-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/insert-mysql-3.21-Linux_2.2.1_i686:
First import - 3.23.10
sql-bench/Results/insert-mysql-Linux_2.0.35_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/insert-mysql-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/insert-mysql-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/insert-mysql-Linux_2.2.10_i686:
First import - 3.23.10
sql-bench/Results/insert-mysql-Linux_2.2.1_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/insert-mysql-SunOS_5.5.1_sun4u:
First import - 3.23.10
sql-bench/Results/insert-mysql-SunOS_5.6_sun4m:
***MISSING WEAVE***
sql-bench/Results/insert-mysql-SunOS_5.7_sun4m:
First import - 3.23.10
sql-bench/Results/insert-mysql-SunOS_5.7_sun4u:
First import - 3.23.10
sql-bench/Results/insert-mysql_3.21-Linux_2.0.35_i686:
First import - 3.23.10
sql-bench/Results/insert-mysql_fast-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/insert-mysql_odbc-win98:
First import - 3.23.10
sql-bench/Results/insert-oracle-Linux_2.0.36_i686-cmp-mysql,oracle:
First import - 3.23.10
sql-bench/Results/insert-oracle_fast-Linux_2.0.36_i686-cmp-mysql,oracle:
First import - 3.23.10
sql-bench/Results/insert-pg-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/insert-pg_fast-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/insert-solid-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/select-Adabas-Linux_2.0.35_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/select-msql-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/select-mysql-3.21-Linux_2.2.1_i686:
First import - 3.23.10
sql-bench/Results/select-mysql-Linux_2.0.35_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/select-mysql-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/select-mysql-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/select-mysql-Linux_2.2.10_i686:
First import - 3.23.10
sql-bench/Results/select-mysql-Linux_2.2.1_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/select-mysql-SunOS_5.5.1_sun4u:
First import - 3.23.10
sql-bench/Results/select-mysql-SunOS_5.6_sun4m:
***MISSING WEAVE***
sql-bench/Results/select-mysql-SunOS_5.7_sun4m:
First import - 3.23.10
sql-bench/Results/select-mysql-SunOS_5.7_sun4u:
First import - 3.23.10
sql-bench/Results/select-mysql_3.21-Linux_2.0.35_i686:
First import - 3.23.10
sql-bench/Results/select-mysql_fast-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/select-mysql_odbc-win98:
First import - 3.23.10
sql-bench/Results/select-oracle-Linux_2.0.36_i686-cmp-mysql,oracle:
First import - 3.23.10
sql-bench/Results/select-oracle_fast-Linux_2.0.36_i686-cmp-mysql,oracle:
First import - 3.23.10
sql-bench/Results/select-pg-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/select-pg_fast-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/select-solid-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/wisconsin-Adabas-Linux_2.0.35_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/wisconsin-msql-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/wisconsin-mysql-3.21-Linux_2.2.1_i686:
First import - 3.23.10
sql-bench/Results/wisconsin-mysql-Linux_2.0.35_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/wisconsin-mysql-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/wisconsin-mysql-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/wisconsin-mysql-Linux_2.2.10_i686:
First import - 3.23.10
sql-bench/Results/wisconsin-mysql-Linux_2.2.1_i686-cmp-adabas,mysql:
First import - 3.23.10
sql-bench/Results/wisconsin-mysql-SunOS_5.5.1_sun4u:
First import - 3.23.10
sql-bench/Results/wisconsin-mysql-SunOS_5.6_sun4m:
***MISSING WEAVE***
sql-bench/Results/wisconsin-mysql-SunOS_5.7_sun4m:
First import - 3.23.10
sql-bench/Results/wisconsin-mysql-SunOS_5.7_sun4u:
First import - 3.23.10
sql-bench/Results/wisconsin-mysql_3.21-Linux_2.0.35_i686:
First import - 3.23.10
sql-bench/Results/wisconsin-mysql_fast-Linux_2.2.10_i686-cmp-msql,mysql:
First import - 3.23.10
sql-bench/Results/wisconsin-mysql_odbc-win98:
First import - 3.23.10
sql-bench/Results/wisconsin-oracle-Linux_2.0.36_i686-cmp-mysql,oracle:
First import - 3.23.10
sql-bench/Results/wisconsin-oracle_fast-Linux_2.0.36_i686-cmp-mysql,oracle:
First import - 3.23.10
sql-bench/Results/wisconsin-pg-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/wisconsin-pg_fast-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/Results/wisconsin-solid-Linux_2.0.36_i686-cmp-mysql,pg,solid:
First import - 3.23.10
sql-bench/limits/Adabas.cfg:
First import - 3.23.10
sql-bench/limits/Adabas.comment:
First import - 3.23.10
sql-bench/limits/Informix.cfg:
First import - 3.23.10
sql-bench/limits/Informix.comment:
First import - 3.23.10
sql-bench/limits/access.comment:
First import - 3.23.10
sql-bench/limits/access_odbc.cfg:
First import - 3.23.10
sql-bench/limits/db2.cfg:
First import - 3.23.10
sql-bench/limits/empress.cfg:
First import - 3.23.10
sql-bench/limits/empress.comment:
First import - 3.23.10
sql-bench/limits/ms-sql65.cfg:
First import - 3.23.10
sql-bench/limits/msql.cfg:
First import - 3.23.10
sql-bench/limits/mysql-3.22.cfg:
First import - 3.23.10
sql-bench/limits/pg.comment:
First import - 3.23.10
sql-bench/limits/solid-nt4.cfg:
First import - 3.23.10
sql-bench/limits/solid.cfg:
First import - 3.23.10
sql-bench/limits/sybase.cfg:
First import - 3.23.10
support-files/binary-configure.sh:
First import - 3.23.10
support-files/mysql-log-rotate.sh:
First import - 3.23.10
mkinstalldirs:
Update to 3.23.11
Docs/mysqld_error.txt:
Update to 3.23.11
man/mysql.1:
Update to 3.23.11
mysys/ChangeLog:
Update to 3.23.11
scripts/mysqlaccess.sh:
Update to 3.23.11
strings/Attic/ptr_cmp.c:
Update to 3.23.11
dbug/dbug_analyze.c:
Update for 3.23.12
dbug/doinstall.sh:
Update for 3.23.12
dbug/install.sh:
Update for 3.23.12
dbug/mklintlib.sh:
Update for 3.23.12
dbug/qmake.cmd:
Update for 3.23.12
dbug/vargs.h:
Update for 3.23.12
isam/test_all.res:
Update for 3.23.12
isam/test_all:
Update for 3.23.12
myisam/NEWS:
Update for 3.23.12
myisam/common_words:
***MISSING WEAVE***
myisam/mi_test_all.res:
Update for 3.23.12
myisam/test_pack:
Update for 3.23.12
scripts/safe_mysqld-watch.sh:
Update for 3.23.12
sql/ha_hash.h:
Update for 3.23.12
sql/nt_servc.h:
Update for 3.23.12
strings/READ-ME:
Update for 3.23.12
strings/bzero.c:
Update for 3.23.12
strings/latin2.def:
Update for 3.23.12
strings/memset.c:
Update for 3.23.12
strings/strcat.c:
Update for 3.23.12
strings/strchr.c:
Update for 3.23.12
strings/strcmp.c:
Update for 3.23.12
strings/string.doc:
Update for 3.23.12
strings/strings-not-used.h:
Update for 3.23.12
strings/strlen.c:
Update for 3.23.12
strings/strrchr.c:
Update for 3.23.12
strings/t_ctype.h:
Update for 3.23.12
Build-tools/Do-create-perl-rpms:
Initial checkin of MySQL build environment.
Build-tools/Do-local-patch-file:
Initial checkin of MySQL build environment.
Build-tools/newest:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql-01.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql-02.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql-03.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql-04.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql-05.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql-06.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql-07.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql-08.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql-09.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql-10.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql-11.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql-12.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql-13.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql-14.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql-15.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql-16.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql-17.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql-compatible.jpg:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql_anim-01.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql_anim-02.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql_anim-03.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql_anim-04.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql_anim-05.gif:
Initial checkin of MySQL build environment.
Docs/MySQL-logos/mysql_anim-06.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/afghanistan.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/albania.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/algeria.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/andorra.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/angola.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/antartica.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/antigua-and-barbuda.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/argentina.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/armenia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/australia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/austria.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/azerbaijan.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/bahamas.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/bahrein.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/bangladesh.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/barbados.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/belarus.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/belgium.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/belize.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/benin.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/bermuda.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/bhutan.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/bolivia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/bosnia-and-herzegovina.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/botswana.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/brazil.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/brunei.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/bulgaria.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/burkina-faso.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/burma.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/burundi.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/cambodia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/cameroon.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/canada.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/cape-verde.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/central-african-republic.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/chad.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/chile.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/china.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/colombia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/comoros.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/congo.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/costa-rica.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/cote-d-ivoire.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/croatia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/cuba.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/cyprus.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/czech-republic.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/denmark-original-incorrect.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/denmark.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/djibouti.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/dominica.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/dominican-republic.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/ecuador.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/egypt.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/el-salvador.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/equatorial-guinea.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/eritrea.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/estonia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/ethiopia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/fiji.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/finland.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/france.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/gabon.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/gambia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/georgia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/germany.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/ghana.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/great-britain.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/greece.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/greenland.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/grenada.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/guatemala.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/guinea-bissau.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/guinea.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/guyana.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/haiti.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/honduras.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/hungary.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/iceland.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/india.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/indonesia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/iran.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/iraq.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/ireland.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/israel.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/italy.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/jamaica.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/japan.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/jordan.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/kazakhstan.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/kenya.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/kiribati.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/kuwait.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/kyrgyzstan.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/laos.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/latvia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/lebanon.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/lesotho.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/liberia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/libya.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/liechtenstein.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/lithuania.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/luxembourg.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/macedonia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/madagascar.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/malawi.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/malaysia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/maldives.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/mali.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/malta.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/marshall.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/mauritania.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/mauritius.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/mexico.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/micronesia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/moldova.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/monaco.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/mongolia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/morocco.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/mozambique.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/namibia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/nauru.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/nepal.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/netherlands.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/new-zealand.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/nicaragua.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/niger.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/nigeria.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/north-korea.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/norway.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/oman.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/pakistan.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/panama.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/papua-new-guinea.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/paraguay.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/peru.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/philippines.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/poland.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/portugal.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/qatar.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/romania.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/russia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/rwanda.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/saint-kitts-and-nevis.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/saint-lucia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/samoa.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/sao-tome-and-principe.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/saudi-arabia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/senegal.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/seychelles.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/sierra-leone.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/singapore.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/slovakia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/slovenia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/solomon-islands.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/somalia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/south-africa.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/south-korea.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/spain.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/sri-lanka.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/sudan.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/suriname.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/swaziland.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/sweden.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/sweden2.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/switzerland.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/syria.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/taiwan.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/tajikistan.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/tanzania.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/thailand.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/togo.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/tonga.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/trinidad-and-tobago.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/tunisia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/turkey.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/turkmenistan.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/tuvalu.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/uganda.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/ukraine.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/united-arab-emirates.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/united-states-of-america.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/uruguay.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/usa.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/uzbekistan.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/vanuatu.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/venezuela.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/vietnam.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/vincent-and-grenadines.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/yemen.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/yugoslavia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/zaire.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/zambia.gif:
Initial checkin of MySQL build environment.
Docs/Raw-Flags/zimbabwe.gif:
Initial checkin of MySQL build environment.
Docs/Support/generate-flag-images:
Initial checkin of MySQL build environment.
Docs/Support/generate-mirror-listing.pl:
Initial checkin of MySQL build environment.
Docs/Support/generate-text-files.pl:
Initial checkin of MySQL build environment.
Docs/Support/make-makefile:
Initial checkin of MySQL build environment.
Docs/Support/texinfo.tex:
Initial checkin of MySQL build environment.
Docs/Translations/myodbc-br.texi:
Initial checkin of MySQL build environment.
man/.cvsignore:
Initial checkin of MySQL build environment.
mit-pthreads/include/pthread/config.h:
Initial checkin of MySQL build environment.
readline/.cvsignore:
Initial checkin of MySQL build environment.
sql/share/.cvsignore:
Initial checkin of MySQL build environment.
tests/.cvsignore:
Initial checkin of MySQL build environment.
libmysql/acconfig.h:
***MISSING WEAVE***
libmysql/acinclude.m4:
Configure stuff for libmysql.
libmysql/configure.in:
Configure stuff for libmysql.
mit-pthreads/.cvsignore:
More work on initial build
mit-pthreads/include/pthread/cond.h:
Update to 3.23.12
mit-pthreads/machdep/engine-i386-linux-2.0.c:
Update to 3.23.12
mit-pthreads/machdep/engine-i386-linux-2.0.h:
Update to 3.23.12
mit-pthreads/machdep/posix-linux-2.0.h:
Update to 3.23.12
mit-pthreads/machdep/unistd-i386-linux-2.0.h:
Update to 3.23.12
sql/add_errmsg:
Update to 3.23.12
sql/watchdog_mysqld:
Update to 3.23.12
strings/Attic/memory.h:
Update to 3.23.12
dbug/.cvsignore:
Update to 3.23.12
heap/.cvsignore:
Update to 3.23.12
merge/.cvsignore:
Update to 3.23.12
mit-pthreads/bin/.cvsignore:
Update to 3.23.12
mit-pthreads/bin/finger/.cvsignore:
Update to 3.23.12
mit-pthreads/lib/.cvsignore:
Update to 3.23.12
mit-pthreads/lib/libpthreadutil/.cvsignore:
Update to 3.23.12
mit-pthreads/machdep/linux-2.0/__math.h:
Update to 3.23.12
mit-pthreads/machdep/linux-2.0/__path.h:
Update to 3.23.12
mit-pthreads/machdep/linux-2.0/__signal.h:
Update to 3.23.12
mit-pthreads/machdep/linux-2.0/__stdio.h:
Update to 3.23.12
mit-pthreads/machdep/linux-2.0/__stdlib.h:
Update to 3.23.12
mit-pthreads/machdep/linux-2.0/__string.h:
Update to 3.23.12
mit-pthreads/machdep/linux-2.0/__time.h:
Update to 3.23.12
mit-pthreads/machdep/linux-2.0/cdefs.h:
Update to 3.23.12
mit-pthreads/machdep/linux-2.0/compat.h:
Update to 3.23.12
mit-pthreads/machdep/linux-2.0/dirent.h:
Update to 3.23.12
mit-pthreads/machdep/linux-2.0/errno.h:
Update to 3.23.12
mit-pthreads/machdep/linux-2.0/socket.h:
Update to 3.23.12
mit-pthreads/machdep/linux-2.0/socketcall.h:
Update to 3.23.12
mit-pthreads/machdep/linux-2.0/timers.h:
Update to 3.23.12
mit-pthreads/machdep/linux-2.0/uio.h:
Update to 3.23.12
mit-pthreads/machdep/linux-2.0/wait.h:
Update to 3.23.12
mit-pthreads/tests/.cvsignore:
Update to 3.23.12
myisammrg/.cvsignore:
Update to 3.23.12
regex/.cvsignore:
Update to 3.23.12
mit-pthreads/machdep/linux-2.0/extra/bits/local_lim.h:
Update to 3.23.12
mit-pthreads/machdep/linux-2.0/extra/bits/socket.h:
Update to 3.23.12
vio/.cvsignore:
Update for 3.23.12
vio/Vio.cc:
Update for 3.23.12
vio/VioAcceptorFd.cc:
Update for 3.23.12
vio/VioAcceptorFd.h:
Update for 3.23.12
vio/VioConnectorFd.cc:
Update for 3.23.12
vio/VioConnectorFd.h:
Update for 3.23.12
vio/VioFd.cc:
Update for 3.23.12
vio/VioFd.h:
Update for 3.23.12
vio/VioPipe.cc:
Update for 3.23.12
vio/VioSSL.cc:
Update for 3.23.12
vio/VioSSL.h:
Update for 3.23.12
vio/VioSSLAcceptorFd.cc:
Update for 3.23.12
vio/VioSSLFactoriesFd.cc:
Update for 3.23.12
vio/VioSSLFactoriesFd.h:
Update for 3.23.12
vio/VioSocket.cc:
Update for 3.23.12
vio/VioSocket.h:
Update for 3.23.12
vio/version.cc:
Update for 3.23.12
vio/vio-global.h:
Update for 3.23.12
vio/vioelitexx.cc:
Update for 3.23.12
vio/viotest-ssl.cc:
Update for 3.23.12
vio/viotest-sslconnect.cc:
Update for 3.23.12
vio/viotest.cc:
Update for 3.23.12
vio/viotypes.h:
Update for 3.23.12
strings/strxmov.c:
Update to 3.23.12a
sql/md5.h:
Lots of patches for Alpha-Linux
Docs/Images/empty.png:
*** empty log message ***
Docs/Images/flag-background.pnm:
*** empty log message ***
NEW-RPMS/.cvsignore:
Changes for new build environment
sql-bench/example.bat:
Update for 3.23.12a
sql-bench/pwd.bat:
Update for 3.23.12a
sql-bench/uname.bat:
Update for 3.23.12a
sql-bench/Results/Attic/ATIS-mysql-Linux_2.2.12_20smp_i686:
***MISSING WEAVE***
sql-bench/Results/Attic/RUN-mysql-Linux_2.2.12_20smp_i686:
***MISSING WEAVE***
sql-bench/Results/Attic/alter-table-mysql-Linux_2.2.12_20smp_i686:
***MISSING WEAVE***
sql-bench/Results/Attic/big-tables-mysql-Linux_2.2.12_20smp_i686:
***MISSING WEAVE***
sql-bench/Results/Attic/connect-mysql-Linux_2.2.12_20smp_i686:
***MISSING WEAVE***
sql-bench/Results/Attic/create-mysql-Linux_2.2.12_20smp_i686:
***MISSING WEAVE***
sql-bench/Results/Attic/insert-mysql-Linux_2.2.12_20smp_i686:
***MISSING WEAVE***
sql-bench/Results/Attic/select-mysql-Linux_2.2.12_20smp_i686:
***MISSING WEAVE***
sql-bench/Results/Attic/wisconsin-mysql-Linux_2.2.12_20smp_i686:
***MISSING WEAVE***
sql-bench/Results-linux/ATIS-mysql-Linux_2.2.12_20smp_i686:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/ATIS-mysql-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/ATIS-mysql-Linux_dynamic:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/ATIS-mysql-Linux_pgcc:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/ATIS-mysql-Linux_static:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/ATIS-mysql_fast-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/ATIS-mysql_local_tcp-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/ATIS-mysql_new-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/RUN-mysql-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/RUN-mysql-Linux_dynamic:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/RUN-mysql-Linux_pgcc:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/RUN-mysql-Linux_static:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/RUN-mysql_fast-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/RUN-mysql_local_tcp-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/RUN-mysql_new-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/big-tables-mysql-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/big-tables-mysql-Linux_dynamic:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/big-tables-mysql-Linux_pgcc:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/big-tables-mysql-Linux_static:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/big-tables-mysql_fast-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/big-tables-mysql_local_tcp-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/big-tables-mysql_new-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/connect-mysql-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/connect-mysql-Linux_dynamic:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/connect-mysql-Linux_pgcc:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/connect-mysql-Linux_static:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/connect-mysql_fast-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/connect-mysql_local_tcp-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/connect-mysql_new-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/create-mysql-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/create-mysql-Linux_dynamic:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/create-mysql-Linux_pgcc:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/create-mysql-Linux_static:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/create-mysql_fast-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/create-mysql_local_tcp-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/create-mysql_new-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/insert-mysql-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/insert-mysql-Linux_dynamic:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/insert-mysql-Linux_pgcc:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/insert-mysql-Linux_static:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/insert-mysql_fast-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/insert-mysql_local_tcp-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/insert-mysql_new-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/select-mysql-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/select-mysql-Linux_dynamic:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/select-mysql-Linux_pgcc:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/select-mysql-Linux_static:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/select-mysql_fast-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/select-mysql_local_tcp-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/select-mysql_new-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/wisconsin-mysql-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/wisconsin-mysql-Linux_dynamic:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/wisconsin-mysql-Linux_pgcc:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/wisconsin-mysql-Linux_static:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/wisconsin-mysql_fast-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/wisconsin-mysql_local_tcp-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/Attic/wisconsin-mysql_new-Linux_2.0.33_i586:
***MISSING WEAVE***
sql-bench/Results-linux/alter-table-mysql-Linux_2.2.12_20smp_i686:
***MISSING WEAVE***
sql-bench/Results-linux/big-tables-mysql-Linux_2.2.12_20smp_i686:
***MISSING WEAVE***
sql-bench/Results-linux/connect-mysql-Linux_2.2.12_20smp_i686:
***MISSING WEAVE***
sql-bench/Results-linux/insert-mysql-Linux_2.2.12_20smp_i686:
***MISSING WEAVE***
sql-bench/Results-linux/select-mysql-Linux_2.2.12_20smp_i686:
***MISSING WEAVE***
sql-bench/Results-linux/wisconsin-mysql-Linux_2.2.12_20smp_i686:
***MISSING WEAVE***
sql-bench/.cvsignore:
Update of benchmarks
sql-bench/Results-win32/ATIS-access_odbc-win98-cmp-access,mysql:
Update of benchmarks
sql-bench/Results-win32/ATIS-mysql-win98-cmp-access,mysql:
Update of benchmarks
sql-bench/Results-win32/RUN-access_odbc-win98-cmp-access,mysql:
Update of benchmarks
sql-bench/Results-win32/RUN-mysql-win98-cmp-access,mysql:
Update of benchmarks
sql-bench/Results-win32/alter-table-access_odbc-win98-cmp-access,mysql:
Update of benchmarks
sql-bench/Results-win32/alter-table-mysql-win98-cmp-access,mysql:
Update of benchmarks
sql-bench/Results-win32/big-tables-access_odbc-win98-cmp-access,mysql:
Update of benchmarks
sql-bench/Results-win32/big-tables-mysql-win98-cmp-access,mysql:
Update of benchmarks
sql-bench/Results-win32/connect-access_odbc-win98-cmp-access,mysql:
Update of benchmarks
sql-bench/Results-win32/connect-mysql-win98-cmp-access,mysql:
Update of benchmarks
sql-bench/Results-win32/create-access_odbc-win98-cmp-access,mysql:
Update of benchmarks
sql-bench/Results-win32/create-mysql-win98-cmp-access,mysql:
Update of benchmarks
sql-bench/Results-win32/insert-access_odbc-win98-cmp-access,mysql:
Update of benchmarks
sql-bench/Results-win32/insert-mysql-win98-cmp-access,mysql:
Update of benchmarks
sql-bench/Results-win32/select-access_odbc-win98-cmp-access,mysql:
Update of benchmarks
sql-bench/Results-win32/select-mysql-win98-cmp-access,mysql:
Update of benchmarks
sql-bench/Results-win32/wisconsin-access_odbc-win98-cmp-access,mysql:
Update of benchmarks
sql-bench/Results-win32/wisconsin-mysql-win98-cmp-access,mysql:
Update of benchmarks
sql-bench/Results-linux/RUN-mysql-Linux_2.2.12_20smp_i686:
***MISSING WEAVE***
sql-bench/Results-linux/create-mysql-Linux_2.2.12_20smp_i686:
***MISSING WEAVE***
Docs/Images/Attic/mysql5.gif:
Second copy
Docs/Images/Attic/html-fs.gif:
Moved to web...icons
Docs/Images/Attic/mysql-01.gif:
Moved to web...icons
Docs/Images/Attic/mysql-02.gif:
Moved to web...icons
Docs/Images/Attic/mysql-03.gif:
Moved to web...icons
Docs/Images/Attic/mysql-04.gif:
Moved to web...icons
Docs/Images/Attic/mysql-05.gif:
Moved to web...icons
Docs/Images/Attic/mysql-06.gif:
Moved to web...icons
Docs/Images/Attic/mysql-07.gif:
Moved to web...icons
Docs/Images/Attic/mysql-08.gif:
Moved to web...icons
Docs/Images/Attic/mysql-09.gif:
Moved to web...icons
Docs/Images/Attic/mysql-10.gif:
Moved to web...icons
Docs/Images/Attic/mysql-11.gif:
Moved to web...icons
Docs/Images/Attic/mysql-12.gif:
Moved to web...icons
Docs/Images/Attic/mysql-13.gif:
Moved to web...icons
Docs/Images/Attic/mysql-14.gif:
Moved to web...icons
Docs/Images/Attic/mysql-15.gif:
Moved to web...icons
Docs/Images/Attic/mysql-16.gif:
Moved to web...icons
Docs/Images/Attic/mysql-17.gif:
Moved to web...icons
Docs/Images/Attic/mysql-18.gif:
Moved to web...icons
Docs/Images/Attic/mysql-19.gif:
Moved to web...icons
Docs/Images/Attic/mysql-compatible.jpg:
Moved to web...icons
Docs/Images/Attic/mysql_anim-01.gif:
Moved to web...icons
Docs/Images/Attic/mysql_anim-02.gif:
Moved to web...icons
Docs/Images/Attic/mysql_anim-03.gif:
Moved to web...icons
Docs/Images/Attic/mysql_anim-04.gif:
Moved to web...icons
Docs/Images/Attic/mysql_anim-05.gif:
Moved to web...icons
Docs/Images/Attic/mysql_anim-06.gif:
Moved to web...icons
Docs/Images/Attic/powered-by-MySQL-transparent.gif:
Moved to web...icons
scripts/mysql_zap.sh:
Fixes from the Debian maintainer
Build-tools/Do-patch-file:
Update at work
myisam/TODO:
Fixes for raid + other things
regex/utils.h:
Renamed some portability defines
heap/make-ccc:
First version
isam/make-ccc:
First version
merge/make-ccc:
First version
myisam/make-ccc:
First version
myisammrg/make-ccc:
First version
mysys/make-ccc:
First version
regex/make-ccc:
First version
strings/make-ccc:
First version
sql/share/romanian/errmsg.sys:
***MISSING WEAVE***
Docs/manual-license-spanish.texi:
Update to 3.23.13
BUILD/test-alpha-ccc:
Bug patches from mailing list
sql-bench/Results-win32/ATIS-mysql-win98:
Bug patches from mailing list
sql-bench/Results-win32/RUN-mysql-win98:
Bug patches from mailing list
sql-bench/Results-win32/alter-table-mysql-win98:
Bug patches from mailing list
sql-bench/Results-win32/big-tables-mysql-win98:
Bug patches from mailing list
sql-bench/Results-win32/connect-mysql-win98:
Bug patches from mailing list
sql-bench/Results-win32/create-mysql-win98:
Bug patches from mailing list
sql-bench/Results-win32/insert-mysql-win98:
Bug patches from mailing list
sql-bench/Results-win32/select-mysql-win98:
Bug patches from mailing list
sql-bench/Results-win32/wisconsin-mysql-win98:
Bug patches from mailing list
mit-pthreads/Changes-mysql:
Updated for Linux
mit-pthreads/config/config.h.in:
Updated for Linux
mit-pthreads/config/configure.in:
Updated for Linux
mit-pthreads/config/configure:
Updated for Linux
mit-pthreads/gen/ttyname.c:
Updated for Linux
mit-pthreads/machdep/syscall-i386-linux-2.0.S:
Updated for Linux
mit-pthreads/machdep/linux-2.0/__unistd.h:
Updated for Linux
mit-pthreads/net/Makefile.inc:
Updated for Linux
mit-pthreads/pthreads/fd.c:
Updated for Linux
mit-pthreads/pthreads/fd_kern.c:
Updated for Linux
mit-pthreads/pthreads/fd_sysv.c:
Updated for Linux
mit-pthreads/pthreads/signal.c:
Updated for Linux
mit-pthreads/pthreads/wrapper.c:
Updated for Linux
mit-pthreads/stdlib/getopt.c:
Updated for Linux
sql/share/charsets/cp1251.conf:
Updates for 3.23.14
sql/share/charsets/croat.conf:
Updates for 3.23.14
sql/share/charsets/danish.conf:
Updates for 3.23.14
sql/share/charsets/dec8.conf:
Updates for 3.23.14
sql/share/charsets/dos.conf:
Updates for 3.23.14
sql/share/charsets/german1.conf:
Updates for 3.23.14
sql/share/charsets/greek.conf:
Updates for 3.23.14
sql/share/charsets/hebrew.conf:
Updates for 3.23.14
sql/share/charsets/hp8.conf:
Updates for 3.23.14
sql/share/charsets/hungarian.conf:
Updates for 3.23.14
sql/share/charsets/koi8_ru.conf:
Updates for 3.23.14
sql/share/charsets/koi8_ukr.conf:
Updates for 3.23.14
sql/share/charsets/latin1.conf:
Updates for 3.23.14
sql/share/charsets/latin2.conf:
Updates for 3.23.14
sql/share/charsets/swe7.conf:
Updates for 3.23.14
sql/share/charsets/usa7.conf:
Updates for 3.23.14
sql/share/charsets/win1251.conf:
Updates for 3.23.14
sql/share/charsets/win1251ukr.conf:
Updates for 3.23.14
sql/Attic/mybinlogdump.cc:
Fix for binary log
include/Attic/m_ctype.h.in:
Update for dynamic character sets
strings/Attic/ct_init.c:
Update for dynamic character sets
strings/Attic/ctype-cp1251.c:
Update for dynamic character sets
strings/Attic/ctype-cp1257.c:
Update for dynamic character sets
strings/Attic/ctype-croat.c:
Update for dynamic character sets
strings/Attic/ctype-danish.c:
Update for dynamic character sets
strings/Attic/ctype-dec8.c:
Update for dynamic character sets
strings/Attic/ctype-dos.c:
Update for dynamic character sets
strings/Attic/ctype-estonia.c:
Update for dynamic character sets
strings/Attic/ctype-german1.c:
Update for dynamic character sets
strings/Attic/ctype-greek.c:
Update for dynamic character sets
strings/Attic/ctype-hebrew.c:
Update for dynamic character sets
strings/Attic/ctype-hp8.c:
Update for dynamic character sets
strings/Attic/ctype-hungarian.c:
Update for dynamic character sets
strings/Attic/ctype-koi8_ru.c:
Update for dynamic character sets
strings/Attic/ctype-koi8_ukr.c:
Update for dynamic character sets
strings/Attic/ctype-latin1.c:
Update for dynamic character sets
strings/Attic/ctype-latin2.c:
Update for dynamic character sets
strings/Attic/ctype-swe7.c:
Update for dynamic character sets
strings/Attic/ctype-usa7.c:
Update for dynamic character sets
strings/Attic/ctype-win1250.c:
Update for dynamic character sets
strings/Attic/ctype-win1251.c:
Update for dynamic character sets
strings/Attic/ctype-win1251ukr.c:
Update for dynamic character sets
mysys/.cvsignore:
Update for dynamic character set handling
client/Attic/libmysql.c:
Update of new character sets.
sql/share/charsets/Index:
Update to 3.23.14
sql/share/charsets/README:
Update to 3.23.14
sql/share/charsets/cp1257.conf:
Update to 3.23.14
sql/share/charsets/estonia.conf:
Update to 3.23.14
sql/share/charsets/win1250.conf:
Update to 3.23.14
strings/.cvsignore:
Update to 3.23.14
strings/Attic/bootstrap-ctype.c:
Update to 3.23.14
strings/Attic/ctype.c.in:
Update to 3.23.14
strings/ctype-ujis.c:
Update to 3.23.14
BUILD/.cvsignore:
Portability changes
libmysql/.cvsignore:
Portability changes
mit-pthreads/GNUmakefile:
Modifications to get MySQL 3.23.14 to build
mit-pthreads/config.flags:
***MISSING WEAVE***
mit-pthreads/include/pthread/ac-types.h:
Modifications to get MySQL 3.23.14 to build
mit-pthreads/include/pthread/paths.h:
Modifications to get MySQL 3.23.14 to build
regex/main.c:
Portability fixes
sql/Attic/mini_client_errors.c:
fixed up dependencies and symlinking in mini_client
Build-tools/cvs-sanity-check:
added a script to do a build from fresh CVS for sanity checking - make Tim, Tonu, and everybody else who has had problems with the stuff out of CVS not compiling happy
include/t_ctype.h:
Small updates by monty
include/.cvsignore:
Update to 3.23.15
include/mysql_version.h.in:
Update to 3.23.15
isam/ChangeLog:
Update to 3.23.15
sql-bench/limits/interbase.cfg:
character sets patches + fix of order by
sql-bench/Results-linux/ATIS-interbase-Linux_2.2.14_5.0_i686:
***MISSING WEAVE***
sql-bench/Results-linux/RUN-interbase-Linux_2.2.14_5.0_i686:
***MISSING WEAVE***
sql-bench/Results-linux/alter-table-interbase-Linux_2.2.14_5.0_i686:
***MISSING WEAVE***
sql-bench/Results-linux/big-tables-interbase-Linux_2.2.14_5.0_i686:
***MISSING WEAVE***
sql-bench/Results-linux/create-interbase-Linux_2.2.14_5.0_i686:
***MISSING WEAVE***
sql-bench/Results-linux/insert-interbase-Linux_2.2.14_5.0_i686:
***MISSING WEAVE***
sql-bench/Results-linux/select-interbase-Linux_2.2.14_5.0_i686:
***MISSING WEAVE***
sql-bench/Results-linux/wisconsin-interbase-Linux_2.2.14_5.0_i686:
***MISSING WEAVE***
Docs/net_doc.txt:
Fixes for Win32
sql/share/Makefile.am:
Update at work to get MySQL to configure
include/Attic/mysql_com.h.in:
Update of benchmarks and other small stuff
sql-bench/Results-linux/ATIS-interbase-Linux_2.2.14_5.0_i686-cmp-interbase,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/ATIS-mysql-Linux_2.2.14_5.0_i686-cmp-interbase,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/RUN-interbase-Linux_2.2.14_5.0_i686-cmp-interbase,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/RUN-mysql-Linux_2.2.14_5.0_i686-cmp-interbase,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/alter-table-interbase-Linux_2.2.14_5.0_i686-cmp-interbase,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/alter-table-mysql-Linux_2.2.14_5.0_i686-cmp-interbase,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/big-tables-interbase-Linux_2.2.14_5.0_i686-cmp-interbase,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/big-tables-mysql-Linux_2.2.14_5.0_i686-cmp-interbase,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/connect-interbase-Linux_2.2.14_5.0_i686-cmp-interbase,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/connect-interbase-Linux_2.2.14_5.0_i686:
***MISSING WEAVE***
sql-bench/Results-linux/connect-mysql-Linux_2.2.14_5.0_i686-cmp-interbase,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/create-interbase-Linux_2.2.14_5.0_i686-cmp-interbase,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/create-mysql-Linux_2.2.14_5.0_i686-cmp-interbase,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/insert-interbase-Linux_2.2.14_5.0_i686-cmp-interbase,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/insert-mysql-Linux_2.2.14_5.0_i686-cmp-interbase,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/select-interbase-Linux_2.2.14_5.0_i686-cmp-interbase,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/select-mysql-Linux_2.2.14_5.0_i686-cmp-interbase,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/wisconsin-interbase-Linux_2.2.14_5.0_i686-cmp-interbase,mysql:
***MISSING WEAVE***
sql-bench/Results-linux/wisconsin-mysql-Linux_2.2.14_5.0_i686-cmp-interbase,mysql:
***MISSING WEAVE***
sql-bench/limits/mimer.cfg:
Update of benchmarks and other small stuff
sql/Attic/mini_client.c:
Update to get Berkeley db to work.
sql/Attic/net_serv.c:
Update to get Berkeley db to work.
sql/Attic/lex_hash.h:
lex_hash.h is a pain in the neck for cvs diff
scripts/mysql_convert_table_format.sh:
Update for 3.23.16
include/getopt.h:
Update for 3.23.16
Docs/Support/.cvsignore:
Update for build
scripts/mysqlhotcopy.sh:
Update for 3.23.16
Docs/Attic/myisam.doc:
Mirror addition, Broken Image fix, renamed myisam.doc -> myisam.txt (because it's really text. :).
Docs/myisam.txt:
Mirror addition, Broken Image fix, renamed myisam.doc -> myisam.txt (because it's really text. :).
sql-bench/ChangeLog:
Updates for 3.23.17
tests/big_record.pl:
Updates for 3.23.17
tests/export.pl:
Updates for 3.23.17
tests/fork2_test.pl:
Updates for 3.23.17
tests/fork3_test.pl:
Updates for 3.23.17
tests/fork_test.pl:
Updates for 3.23.17
tests/grant.pl:
Updates for 3.23.17
tests/insert_and_repair.pl:
Updates for 3.23.17
tests/lock_test.pl:
Updates for 3.23.17
tests/pmail.pl:
Updates for 3.23.17
sql/.cvsignore:
Update for 3.23.17
sql-bench/Results/Attic/ATIS-mysql-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/ATIS-mysql-Linux_2.2.1_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/ATIS-mysql_fast-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/ATIS-pg-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/ATIS-pg_fast-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/RUN-mysql-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/RUN-mysql-Linux_2.2.1_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/RUN-mysql_fast-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/RUN-pg-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/RUN-pg_fast-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/alter-table-mysql-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/alter-table-mysql-Linux_2.2.1_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/alter-table-mysql_fast-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/alter-table-pg-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/alter-table-pg_fast-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/big-tables-mysql-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/big-tables-mysql-Linux_2.2.1_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/big-tables-mysql_fast-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/big-tables-pg-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/big-tables-pg_fast-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/connect-mysql-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/connect-mysql-Linux_2.2.1_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/connect-mysql_fast-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/connect-pg-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/connect-pg_fast-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/create-mysql-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/create-mysql-Linux_2.2.1_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/create-mysql_fast-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/create-pg-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/create-pg_fast-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/insert-mysql-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/insert-mysql-Linux_2.2.1_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/insert-mysql_fast-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/insert-pg-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/insert-pg_fast-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/select-mysql-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/select-mysql-Linux_2.2.1_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/select-mysql_fast-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/select-pg-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/select-pg_fast-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/wisconsin-mysql-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/wisconsin-mysql-Linux_2.2.1_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/wisconsin-mysql_fast-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/wisconsin-pg-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/Attic/wisconsin-pg_fast-Linux_2.2.10_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/ATIS-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/RUN-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/alter-table-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/big-tables-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/connect-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/create-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/insert-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/select-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/wisconsin-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
support-files/Attic/my-example.cnf.sh:
Updates to 3.23.17
support-files/Attic/my-huge.cfg.sh:
Update for 3.23.17
support-files/Attic/my-large.cfg.sh:
Update for 3.23.17
support-files/Attic/my-medium.cfg.sh:
Update for 3.23.17
support-files/Attic/my-small.cfg.sh:
Update for 3.23.17
sql-bench/limits/pg.cfg:
Updates to 3.23.17
support-files/my-small.cnf.sh:
Updates to 3.23.17
dbug/dbug.c:
update 3.23.17 for Monty
mysys/getopt1.c:
update 3.23.17 for Monty
readline/complete.c:
update 3.23.17 for Monty
regex/regcomp.c:
update 3.23.17 for Monty
regex/regex2.h:
update 3.23.17 for Monty
regex/regexec.c:
update 3.23.17 for Monty
regex/regexp.c:
update 3.23.17 for Monty
sql-bench/Results/ATIS-mysql-win98:
update 3.23.17 for Monty
sql-bench/Results/RUN-mysql-win98:
update 3.23.17 for Monty
sql-bench/Results/alter-table-mysql-win98:
update 3.23.17 for Monty
sql-bench/Results/big-tables-mysql-win98:
update 3.23.17 for Monty
sql-bench/Results/connect-mysql-win98:
update 3.23.17 for Monty
sql-bench/Results/create-mysql-win98:
update 3.23.17 for Monty
sql-bench/Results/insert-mysql-win98:
update 3.23.17 for Monty
sql-bench/Results/select-mysql-win98:
update 3.23.17 for Monty
sql-bench/Results/wisconsin-mysql-win98:
update 3.23.17 for Monty
sql-bench/Results-linux/ATIS-mysql_fast-Linux_2.2.13_SMP_alpha:
***MISSING WEAVE***
sql-bench/Results-linux/alter-table-mysql_fast-Linux_2.2.13_SMP_alpha:
***MISSING WEAVE***
sql-bench/Results-linux/big-tables-mysql_fast-Linux_2.2.13_SMP_alpha:
***MISSING WEAVE***
sql-bench/Results-linux/create-mysql_fast-Linux_2.2.13_SMP_alpha:
***MISSING WEAVE***
sql-bench/Results-linux/insert-mysql_fast-Linux_2.2.13_SMP_alpha:
***MISSING WEAVE***
sql-bench/Results-linux/wisconsin-mysql_fast-Linux_2.2.13_SMP_alpha:
***MISSING WEAVE***
tests/test_delayed_insert.pl:
update 3.23.17 for Monty
vio/Vio.h:
update 3.23.17 for Monty
vio/VioPipe.h:
update 3.23.17 for Monty
vio/violite.h:
update 3.23.17 for Monty
sql-bench/limits/access.cfg:
Update for 3.23.17
sql-bench/limits/ms-sql.cfg:
Update for 3.23.17
sql-bench/limits/oracle.cfg:
Update for 3.23.17
BUILD/compile-alpha-ccc:
Update to 3.23.18
BUILD/compile-alpha-debug:
Update to 3.23.18
BUILD/compile-alpha:
Update to 3.23.18
BUILD/compile-pentium-gcov:
Update to 3.23.18
BUILD/compile-pentium-myodbc:
Update to 3.23.18
BUILD/compile-pentium:
Update to 3.23.18
BUILD/compile-solaris-sparc-purify:
Update to 3.23.18
BUILD/compile-solaris-sparc:
Update to 3.23.18
client/Attic/net.c:
Update to 3.23.18
sql-bench/Results/ATIS-mysql-Linux_2.2.14_i686_xeon:
Update to 3.23.18
sql-bench/Results/RUN-mysql-Linux_2.2.14_i686_xeon:
Update to 3.23.18
sql-bench/Results/alter-table-mysql-Linux_2.2.14_i686_xeon:
Update to 3.23.18
sql-bench/Results/big-tables-mysql-Linux_2.2.14_i686_xeon:
Update to 3.23.18
sql-bench/Results/connect-mysql-Linux_2.2.14_i686_xeon:
Update to 3.23.18
sql-bench/Results/create-mysql-Linux_2.2.14_i686_xeon:
Update to 3.23.18
sql-bench/Results/insert-mysql-Linux_2.2.14_i686_xeon:
Update to 3.23.18
sql-bench/Results/select-mysql-Linux_2.2.14_i686_xeon:
Update to 3.23.18
sql-bench/Results/wisconsin-mysql-Linux_2.2.14_i686_xeon:
Update to 3.23.18
sql-bench/Results-linux/RUN-mysql_fast-Linux_2.2.13_SMP_alpha:
***MISSING WEAVE***
sql-bench/Results-linux/connect-mysql_fast-Linux_2.2.13_SMP_alpha:
***MISSING WEAVE***
sql-bench/Results-linux/select-mysql_fast-Linux_2.2.13_SMP_alpha:
***MISSING WEAVE***
mysql-test/mybin/mysql-test_install_db:
Initial checkin of mysql-test subdir.
mysql-test/mysql-test-run:
Quick commit before I checkout a new tree.
Docs/Tutorial-MySQL-final.txt:
Update for 3.23.19-beta
Build-tools/Do-rpm:
Fix of wrong CVS update
sql-bench/Results/ATIS-mysql-NT_4.0:
Fix of wrong CVS update
sql-bench/Results/RUN-mysql-NT_4.0:
Fix of wrong CVS update
sql-bench/Results/alter-table-mysql-NT_4.0:
Fix of wrong CVS update
sql-bench/Results/big-tables-mysql-NT_4.0:
Fix of wrong CVS update
sql-bench/Results/connect-mysql-NT_4.0:
Fix of wrong CVS update
sql-bench/Results/create-mysql-NT_4.0:
Fix of wrong CVS update
sql-bench/Results/insert-mysql-NT_4.0:
Fix of wrong CVS update
sql-bench/Results/select-mysql-NT_4.0:
Fix of wrong CVS update
sql-bench/Results/wisconsin-mysql-NT_4.0:
Fix of wrong CVS update
acconfig.h:
Change of copyright to GPL/LGPL
client/.cvsignore:
Change of copyright to GPL/LGPL
client/completion_hash.h:
Change of copyright to GPL/LGPL
client/connect_test.c:
Change of copyright to GPL/LGPL
client/errmsg.c:
Change of copyright to GPL/LGPL
client/insert_test.c:
Change of copyright to GPL/LGPL
client/list_test.c:
Change of copyright to GPL/LGPL
client/my_readline.h:
Change of copyright to GPL/LGPL
client/password.c:
Change of copyright to GPL/LGPL
client/readline.cc:
Change of copyright to GPL/LGPL
client/select_test.c:
Change of copyright to GPL/LGPL
client/showdb_test.c:
Change of copyright to GPL/LGPL
client/sql_string.cc:
Change of copyright to GPL/LGPL
client/sql_string.h:
Change of copyright to GPL/LGPL
client/ssl_test.c:
Change of copyright to GPL/LGPL
client/thread_test.c:
Change of copyright to GPL/LGPL
client/violite.c:
Change of copyright to GPL/LGPL
dbug/Makefile.am:
Change of copyright to GPL/LGPL
extra/comp_err.c:
Change of copyright to GPL/LGPL
extra/perror.c:
Change of copyright to GPL/LGPL
extra/replace.c:
Change of copyright to GPL/LGPL
extra/resolveip.c:
Change of copyright to GPL/LGPL
heap/Makefile.am:
Change of copyright to GPL/LGPL
heap/_check.c:
Change of copyright to GPL/LGPL
heap/_rectest.c:
Change of copyright to GPL/LGPL
heap/heapdef.h:
Change of copyright to GPL/LGPL
heap/hp_block.c:
Change of copyright to GPL/LGPL
heap/hp_clear.c:
Change of copyright to GPL/LGPL
heap/hp_close.c:
Change of copyright to GPL/LGPL
heap/hp_create.c:
Change of copyright to GPL/LGPL
heap/hp_delete.c:
Change of copyright to GPL/LGPL
heap/hp_extra.c:
Change of copyright to GPL/LGPL
heap/hp_hash.c:
Change of copyright to GPL/LGPL
heap/hp_info.c:
Change of copyright to GPL/LGPL
heap/hp_open.c:
Change of copyright to GPL/LGPL
heap/hp_panic.c:
Change of copyright to GPL/LGPL
heap/hp_rename.c:
Change of copyright to GPL/LGPL
heap/hp_rfirst.c:
Change of copyright to GPL/LGPL
heap/hp_rlast.c:
Change of copyright to GPL/LGPL
heap/hp_rnext.c:
Change of copyright to GPL/LGPL
heap/hp_rprev.c:
Change of copyright to GPL/LGPL
heap/hp_rrnd.c:
Change of copyright to GPL/LGPL
heap/hp_rsame.c:
Change of copyright to GPL/LGPL
heap/hp_scan.c:
Change of copyright to GPL/LGPL
heap/hp_static.c:
Change of copyright to GPL/LGPL
heap/hp_test1.c:
Change of copyright to GPL/LGPL
heap/hp_test2.c:
Change of copyright to GPL/LGPL
heap/hp_update.c:
Change of copyright to GPL/LGPL
heap/hp_write.c:
Change of copyright to GPL/LGPL
include/dbug.h:
Change of copyright to GPL/LGPL
include/hash.h:
Change of copyright to GPL/LGPL
include/heap.h:
Change of copyright to GPL/LGPL
include/m_ctype.h:
Change of copyright to GPL/LGPL
include/m_string.h:
Change of copyright to GPL/LGPL
include/merge.h:
Change of copyright to GPL/LGPL
include/my_alarm.h:
Change of copyright to GPL/LGPL
include/my_dir.h:
Change of copyright to GPL/LGPL
include/my_list.h:
Change of copyright to GPL/LGPL
include/my_net.h:
Change of copyright to GPL/LGPL
include/my_no_pthread.h:
Change of copyright to GPL/LGPL
include/my_nosys.h:
Change of copyright to GPL/LGPL
include/my_pthread.h:
Change of copyright to GPL/LGPL
include/my_sys.h:
Change of copyright to GPL/LGPL
include/my_tree.h:
Change of copyright to GPL/LGPL
include/myisammrg.h:
Change of copyright to GPL/LGPL
include/myisampack.h:
Change of copyright to GPL/LGPL
include/mysys_err.h:
Change of copyright to GPL/LGPL
include/nisam.h:
Change of copyright to GPL/LGPL
include/queues.h:
Change of copyright to GPL/LGPL
include/raid.h:
Change of copyright to GPL/LGPL
include/sslopt-case.h:
Change of copyright to GPL/LGPL
include/sslopt-longopts.h:
Change of copyright to GPL/LGPL
include/sslopt-usage.h:
Change of copyright to GPL/LGPL
include/sslopt-vars.h:
Change of copyright to GPL/LGPL
include/thr_alarm.h:
Change of copyright to GPL/LGPL
include/thr_lock.h:
Change of copyright to GPL/LGPL
include/violite.h:
Change of copyright to GPL/LGPL
isam/Makefile.am:
Change of copyright to GPL/LGPL
isam/_cache.c:
Change of copyright to GPL/LGPL
isam/_dynrec.c:
Change of copyright to GPL/LGPL
isam/_key.c:
Change of copyright to GPL/LGPL
isam/_locking.c:
Change of copyright to GPL/LGPL
isam/_packrec.c:
Change of copyright to GPL/LGPL
isam/_page.c:
Change of copyright to GPL/LGPL
isam/_search.c:
Change of copyright to GPL/LGPL
isam/_statrec.c:
Change of copyright to GPL/LGPL
isam/changed.c:
Change of copyright to GPL/LGPL
isam/close.c:
Change of copyright to GPL/LGPL
isam/create.c:
Change of copyright to GPL/LGPL
isam/delete.c:
Change of copyright to GPL/LGPL
isam/extra.c:
Change of copyright to GPL/LGPL
isam/isamchk.c:
Change of copyright to GPL/LGPL
isam/isamlog.c:
Change of copyright to GPL/LGPL
isam/log.c:
Change of copyright to GPL/LGPL
isam/open.c:
Change of copyright to GPL/LGPL
isam/pack_isam.c:
Change of copyright to GPL/LGPL
isam/panic.c:
Change of copyright to GPL/LGPL
isam/range.c:
Change of copyright to GPL/LGPL
isam/rfirst.c:
Change of copyright to GPL/LGPL
isam/rkey.c:
Change of copyright to GPL/LGPL
isam/rlast.c:
Change of copyright to GPL/LGPL
isam/rnext.c:
Change of copyright to GPL/LGPL
isam/rprev.c:
Change of copyright to GPL/LGPL
isam/rrnd.c:
Change of copyright to GPL/LGPL
isam/rsame.c:
Change of copyright to GPL/LGPL
isam/rsamepos.c:
Change of copyright to GPL/LGPL
isam/sort.c:
Change of copyright to GPL/LGPL
isam/static.c:
Change of copyright to GPL/LGPL
isam/test1.c:
Change of copyright to GPL/LGPL
isam/test3.c:
Change of copyright to GPL/LGPL
libmysql/Makefile.am:
Change of copyright to GPL/LGPL
libmysql/conf_to_src.c:
Change of copyright to GPL/LGPL
libmysql/dll.c:
Change of copyright to GPL/LGPL
libmysql/get_password.c:
Change of copyright to GPL/LGPL
libmysql/password.c:
Change of copyright to GPL/LGPL
libmysql/violite.c:
Change of copyright to GPL/LGPL
man/Makefile.am:
Change of copyright to GPL/LGPL
merge/Makefile.am:
Change of copyright to GPL/LGPL
merge/_locking.c:
Change of copyright to GPL/LGPL
merge/close.c:
Change of copyright to GPL/LGPL
merge/create.c:
Change of copyright to GPL/LGPL
merge/delete.c:
Change of copyright to GPL/LGPL
merge/extra.c:
Change of copyright to GPL/LGPL
merge/info.c:
Change of copyright to GPL/LGPL
merge/mrgdef.h:
Change of copyright to GPL/LGPL
merge/open.c:
Change of copyright to GPL/LGPL
merge/panic.c:
Change of copyright to GPL/LGPL
merge/rrnd.c:
Change of copyright to GPL/LGPL
merge/rsame.c:
Change of copyright to GPL/LGPL
merge/static.c:
Change of copyright to GPL/LGPL
merge/update.c:
Change of copyright to GPL/LGPL
myisam/ft_eval.c:
Change of copyright to GPL/LGPL
myisam/ft_eval.h:
Change of copyright to GPL/LGPL
myisam/ft_parser.c:
Change of copyright to GPL/LGPL
myisam/ft_static.c:
Change of copyright to GPL/LGPL
myisam/ft_stem.c:
Change of copyright to GPL/LGPL
myisam/ft_stopwords.c:
Change of copyright to GPL/LGPL
myisam/ft_test1.c:
Change of copyright to GPL/LGPL
myisam/ft_test1.h:
Change of copyright to GPL/LGPL
myisam/ftdefs.h:
Change of copyright to GPL/LGPL
myisam/fulltext.h:
Change of copyright to GPL/LGPL
myisam/mi_cache.c:
Change of copyright to GPL/LGPL
myisam/mi_changed.c:
Change of copyright to GPL/LGPL
myisam/mi_checksum.c:
Change of copyright to GPL/LGPL
myisam/mi_dbug.c:
Change of copyright to GPL/LGPL
myisam/mi_delete_all.c:
Change of copyright to GPL/LGPL
myisam/mi_delete_table.c:
Change of copyright to GPL/LGPL
myisam/mi_dynrec.c:
Change of copyright to GPL/LGPL
myisam/mi_info.c:
Change of copyright to GPL/LGPL
myisam/mi_key.c:
Change of copyright to GPL/LGPL
myisam/mi_packrec.c:
Change of copyright to GPL/LGPL
myisam/mi_page.c:
Change of copyright to GPL/LGPL
myisam/mi_range.c:
Change of copyright to GPL/LGPL
myisam/mi_rename.c:
Change of copyright to GPL/LGPL
myisam/mi_rfirst.c:
Change of copyright to GPL/LGPL
myisam/mi_rkey.c:
Change of copyright to GPL/LGPL
myisam/mi_rlast.c:
Change of copyright to GPL/LGPL
myisam/mi_rnext.c:
Change of copyright to GPL/LGPL
myisam/mi_rprev.c:
Change of copyright to GPL/LGPL
myisam/mi_rrnd.c:
Change of copyright to GPL/LGPL
myisam/mi_rsame.c:
Change of copyright to GPL/LGPL
myisam/mi_rsamepos.c:
Change of copyright to GPL/LGPL
myisam/mi_scan.c:
Change of copyright to GPL/LGPL
myisam/mi_static.c:
Change of copyright to GPL/LGPL
myisam/mi_statrec.c:
Change of copyright to GPL/LGPL
myisam/mi_test1.c:
Change of copyright to GPL/LGPL
myisam/mi_test2.c:
Change of copyright to GPL/LGPL
myisam/mi_test3.c:
Change of copyright to GPL/LGPL
myisam/mi_unique.c:
Change of copyright to GPL/LGPL
myisam/myisamlog.c:
Change of copyright to GPL/LGPL
myisam/sort.c:
Change of copyright to GPL/LGPL
myisammrg/Makefile.am:
Change of copyright to GPL/LGPL
myisammrg/mymrgdef.h:
Change of copyright to GPL/LGPL
myisammrg/myrg_close.c:
Change of copyright to GPL/LGPL
myisammrg/myrg_create.c:
Change of copyright to GPL/LGPL
myisammrg/myrg_delete.c:
Change of copyright to GPL/LGPL
myisammrg/myrg_extra.c:
Change of copyright to GPL/LGPL
myisammrg/myrg_info.c:
Change of copyright to GPL/LGPL
myisammrg/myrg_locking.c:
Change of copyright to GPL/LGPL
myisammrg/myrg_open.c:
Change of copyright to GPL/LGPL
myisammrg/myrg_panic.c:
Change of copyright to GPL/LGPL
myisammrg/myrg_rrnd.c:
Change of copyright to GPL/LGPL
myisammrg/myrg_rsame.c:
Change of copyright to GPL/LGPL
myisammrg/myrg_static.c:
Change of copyright to GPL/LGPL
myisammrg/myrg_update.c:
Change of copyright to GPL/LGPL
mysys/Makefile.am:
Change of copyright to GPL/LGPL
mysys/array.c:
Change of copyright to GPL/LGPL
mysys/charset.c:
Change of copyright to GPL/LGPL
mysys/checksum.c:
Change of copyright to GPL/LGPL
mysys/default.c:
Change of copyright to GPL/LGPL
mysys/errors.c:
Change of copyright to GPL/LGPL
mysys/getvar.c:
Change of copyright to GPL/LGPL
mysys/hash.c:
Change of copyright to GPL/LGPL
mysys/list.c:
Change of copyright to GPL/LGPL
mysys/make-conf.c:
Change of copyright to GPL/LGPL
mysys/mf_brkhant.c:
Change of copyright to GPL/LGPL
mysys/mf_cache.c:
Change of copyright to GPL/LGPL
mysys/mf_casecnv.c:
Change of copyright to GPL/LGPL
mysys/mf_dirname.c:
Change of copyright to GPL/LGPL
mysys/mf_fn_ext.c:
Change of copyright to GPL/LGPL
mysys/mf_format.c:
Change of copyright to GPL/LGPL
mysys/mf_getdate.c:
Change of copyright to GPL/LGPL
mysys/mf_iocache.c:
Change of copyright to GPL/LGPL
mysys/mf_keycache.c:
Change of copyright to GPL/LGPL
mysys/mf_loadpath.c:
Change of copyright to GPL/LGPL
mysys/mf_pack2.c:
Change of copyright to GPL/LGPL
mysys/mf_path.c:
Change of copyright to GPL/LGPL
mysys/mf_qsort.c:
Change of copyright to GPL/LGPL
mysys/mf_qsort2.c:
Change of copyright to GPL/LGPL
mysys/mf_radix.c:
Change of copyright to GPL/LGPL
mysys/mf_reccache.c:
***MISSING WEAVE***
mysys/mf_same.c:
Change of copyright to GPL/LGPL
mysys/mf_sleep.c:
Change of copyright to GPL/LGPL
mysys/mf_sort.c:
Change of copyright to GPL/LGPL
mysys/mf_soundex.c:
Change of copyright to GPL/LGPL
mysys/mf_stripp.c:
Change of copyright to GPL/LGPL
mysys/mf_unixpath.c:
Change of copyright to GPL/LGPL
mysys/mf_util.c:
Change of copyright to GPL/LGPL
mysys/mf_wcomp.c:
Change of copyright to GPL/LGPL
mysys/mf_wfile.c:
Change of copyright to GPL/LGPL
mysys/mulalloc.c:
Change of copyright to GPL/LGPL
mysys/my_alarm.c:
Change of copyright to GPL/LGPL
mysys/my_alloc.c:
Change of copyright to GPL/LGPL
mysys/my_append.c:
Change of copyright to GPL/LGPL
mysys/my_chsize.c:
Change of copyright to GPL/LGPL
mysys/my_clock.c:
Change of copyright to GPL/LGPL
mysys/my_compress.c:
Change of copyright to GPL/LGPL
mysys/my_copy.c:
Change of copyright to GPL/LGPL
mysys/my_create.c:
Change of copyright to GPL/LGPL
mysys/my_delete.c:
Change of copyright to GPL/LGPL
mysys/my_div.c:
Change of copyright to GPL/LGPL
mysys/my_error.c:
Change of copyright to GPL/LGPL
mysys/my_fopen.c:
Change of copyright to GPL/LGPL
mysys/my_fstream.c:
Change of copyright to GPL/LGPL
mysys/my_getwd.c:
Change of copyright to GPL/LGPL
mysys/my_init.c:
Change of copyright to GPL/LGPL
mysys/my_lib.c:
Change of copyright to GPL/LGPL
mysys/my_lock.c:
Change of copyright to GPL/LGPL
mysys/my_lockmem.c:
Change of copyright to GPL/LGPL
mysys/my_lread.c:
Change of copyright to GPL/LGPL
mysys/my_lwrite.c:
Change of copyright to GPL/LGPL
mysys/my_malloc.c:
Change of copyright to GPL/LGPL
mysys/my_messnc.c:
Change of copyright to GPL/LGPL
mysys/my_mkdir.c:
Change of copyright to GPL/LGPL
mysys/my_net.c:
Change of copyright to GPL/LGPL
mysys/my_once.c:
Change of copyright to GPL/LGPL
mysys/my_open.c:
Change of copyright to GPL/LGPL
mysys/my_pread.c:
Change of copyright to GPL/LGPL
mysys/my_pthread.c:
Change of copyright to GPL/LGPL
mysys/my_quick.c:
Change of copyright to GPL/LGPL
mysys/my_read.c:
Change of copyright to GPL/LGPL
mysys/my_realloc.c:
Change of copyright to GPL/LGPL
mysys/my_redel.c:
Change of copyright to GPL/LGPL
mysys/my_rename.c:
Change of copyright to GPL/LGPL
mysys/my_seek.c:
Change of copyright to GPL/LGPL
mysys/my_static.c:
Change of copyright to GPL/LGPL
mysys/my_static.h:
Change of copyright to GPL/LGPL
mysys/my_tempnam.c:
Change of copyright to GPL/LGPL
mysys/my_vsnprintf.c:
Change of copyright to GPL/LGPL
mysys/my_wincond.c:
Change of copyright to GPL/LGPL
mysys/my_winthread.c:
Change of copyright to GPL/LGPL
mysys/my_write.c:
Change of copyright to GPL/LGPL
mysys/mysys_priv.h:
Change of copyright to GPL/LGPL
mysys/ptr_cmp.c:
Change of copyright to GPL/LGPL
mysys/queues.c:
Change of copyright to GPL/LGPL
mysys/raid.cc:
Change of copyright to GPL/LGPL
mysys/safemalloc.c:
Change of copyright to GPL/LGPL
mysys/string.c:
Change of copyright to GPL/LGPL
mysys/test_charset.c:
Change of copyright to GPL/LGPL
mysys/test_dir.c:
Change of copyright to GPL/LGPL
mysys/test_fn.c:
Change of copyright to GPL/LGPL
mysys/test_vsnprintf.c:
Change of copyright to GPL/LGPL
mysys/testhash.c:
Change of copyright to GPL/LGPL
mysys/thr_alarm.c:
Change of copyright to GPL/LGPL
mysys/thr_lock.c:
Change of copyright to GPL/LGPL
mysys/thr_mutex.c:
Change of copyright to GPL/LGPL
mysys/thr_rwlock.c:
Change of copyright to GPL/LGPL
mysys/tree.c:
Change of copyright to GPL/LGPL
mysys/typelib.c:
Change of copyright to GPL/LGPL
regex/Makefile.am:
Change of copyright to GPL/LGPL
sql/cache_manager.cc:
Change of copyright to GPL/LGPL
sql/cache_manager.h:
Change of copyright to GPL/LGPL
sql/convert.cc:
Change of copyright to GPL/LGPL
sql/custom_conf.h:
Change of copyright to GPL/LGPL
sql/derror.cc:
Change of copyright to GPL/LGPL
sql/field_conv.cc:
Change of copyright to GPL/LGPL
sql/frm_crypt.cc:
Change of copyright to GPL/LGPL
sql/ha_heap.cc:
Change of copyright to GPL/LGPL
sql/ha_heap.h:
Change of copyright to GPL/LGPL
sql/ha_isam.cc:
Change of copyright to GPL/LGPL
sql/ha_isammrg.cc:
Change of copyright to GPL/LGPL
sql/hash_filo.cc:
Change of copyright to GPL/LGPL
sql/hash_filo.h:
Change of copyright to GPL/LGPL
sql/hostname.cc:
Change of copyright to GPL/LGPL
sql/init.cc:
Change of copyright to GPL/LGPL
sql/item_buff.cc:
Change of copyright to GPL/LGPL
sql/item_cmpfunc.h:
Change of copyright to GPL/LGPL
sql/item_create.cc:
Change of copyright to GPL/LGPL
sql/item_create.h:
Change of copyright to GPL/LGPL
sql/item_strfunc.cc:
Change of copyright to GPL/LGPL
sql/item_strfunc.h:
Change of copyright to GPL/LGPL
sql/item_sum.cc:
Change of copyright to GPL/LGPL
sql/item_sum.h:
Change of copyright to GPL/LGPL
sql/item_uniq.cc:
Change of copyright to GPL/LGPL
sql/item_uniq.h:
Change of copyright to GPL/LGPL
sql/key.cc:
Change of copyright to GPL/LGPL
sql/lex_symbol.h:
Change of copyright to GPL/LGPL
sql/lock.cc:
Change of copyright to GPL/LGPL
sql/matherr.c:
Change of copyright to GPL/LGPL
sql/mf_iocache.cc:
Change of copyright to GPL/LGPL
sql/mini_client.h:
Change of copyright to GPL/LGPL
sql/my_lock.c:
Change of copyright to GPL/LGPL
sql/opt_sum.cc:
Change of copyright to GPL/LGPL
sql/password.c:
Change of copyright to GPL/LGPL
sql/procedure.cc:
Change of copyright to GPL/LGPL
sql/procedure.h:
Change of copyright to GPL/LGPL
sql/sql_acl.h:
Change of copyright to GPL/LGPL
sql/sql_analyse.cc:
Change of copyright to GPL/LGPL
sql/sql_cache.cc:
Change of copyright to GPL/LGPL
sql/sql_crypt.cc:
Change of copyright to GPL/LGPL
sql/sql_crypt.h:
Change of copyright to GPL/LGPL
sql/sql_list.cc:
Change of copyright to GPL/LGPL
sql/sql_list.h:
Change of copyright to GPL/LGPL
sql/sql_map.cc:
Change of copyright to GPL/LGPL
sql/sql_map.h:
Change of copyright to GPL/LGPL
sql/sql_string.h:
Change of copyright to GPL/LGPL
sql/sql_test.cc:
Change of copyright to GPL/LGPL
sql/sql_udf.cc:
Change of copyright to GPL/LGPL
sql/sql_udf.h:
Change of copyright to GPL/LGPL
sql/thr_malloc.cc:
Change of copyright to GPL/LGPL
sql/udf_example.cc:
Change of copyright to GPL/LGPL
sql/unireg.cc:
Change of copyright to GPL/LGPL
sql/unireg.h:
Change of copyright to GPL/LGPL
sql/violite.c:
Change of copyright to GPL/LGPL
sql-bench/Makefile.am:
Change of copyright to GPL/LGPL
sql-bench/bench-init.pl.sh:
Change of copyright to GPL/LGPL
sql-bench/copy-db.sh:
Change of copyright to GPL/LGPL
sql-bench/run-all-tests.sh:
Change of copyright to GPL/LGPL
sql-bench/server-cfg.sh:
Change of copyright to GPL/LGPL
sql-bench/test-ATIS.sh:
Change of copyright to GPL/LGPL
sql-bench/test-alter-table.sh:
Change of copyright to GPL/LGPL
sql-bench/test-big-tables.sh:
Change of copyright to GPL/LGPL
sql-bench/test-connect.sh:
Change of copyright to GPL/LGPL
sql-bench/test-create.sh:
Change of copyright to GPL/LGPL
sql-bench/test-insert.sh:
Change of copyright to GPL/LGPL
sql-bench/test-select.sh:
Change of copyright to GPL/LGPL
sql-bench/test-wisconsin.sh:
Change of copyright to GPL/LGPL
sql-bench/Results/ATIS-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/ATIS-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/ATIS-pg_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/ATIS-pg_fast-Linux_2.2.14_5.0_i686:
***MISSING WEAVE***
sql-bench/Results/RUN-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/RUN-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/RUN-pg_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/RUN-pg_fast-Linux_2.2.14_5.0_i686:
***MISSING WEAVE***
sql-bench/Results/alter-table-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/alter-table-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/alter-table-pg_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/alter-table-pg_fast-Linux_2.2.14_5.0_i686:
***MISSING WEAVE***
sql-bench/Results/big-tables-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/big-tables-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/big-tables-pg_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/big-tables-pg_fast-Linux_2.2.14_5.0_i686:
***MISSING WEAVE***
sql-bench/Results/connect-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/connect-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/connect-pg_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/connect-pg_fast-Linux_2.2.14_5.0_i686:
***MISSING WEAVE***
sql-bench/Results/create-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/create-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/create-pg_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/create-pg_fast-Linux_2.2.14_5.0_i686:
***MISSING WEAVE***
sql-bench/Results/insert-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/insert-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/insert-pg_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/select-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/select-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/select-pg_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/wisconsin-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/wisconsin-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
sql-bench/Results/wisconsin-pg_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg:
***MISSING WEAVE***
strings/Makefile.am:
Change of copyright to GPL/LGPL
strings/README:
Change of copyright to GPL/LGPL
strings/atof.c:
Change of copyright to GPL/LGPL
strings/bchange.c:
Change of copyright to GPL/LGPL
strings/bcmp.c:
Change of copyright to GPL/LGPL
strings/bcopy-duff.c:
Change of copyright to GPL/LGPL
strings/bmove512.c:
Change of copyright to GPL/LGPL
strings/bmove_upp-sparc.s:
Change of copyright to GPL/LGPL
strings/bmove_upp.c:
Change of copyright to GPL/LGPL
strings/conf_to_src.c:
Change of copyright to GPL/LGPL
strings/ctype-big5.c:
Change of copyright to GPL/LGPL
strings/ctype-euc_kr.c:
Change of copyright to GPL/LGPL
strings/ctype-gb2312.c:
Change of copyright to GPL/LGPL
strings/ctype-sjis.c:
Change of copyright to GPL/LGPL
strings/ctype.c:
Change of copyright to GPL/LGPL
strings/do_ctype.c:
Change of copyright to GPL/LGPL
strings/int2str.c:
Change of copyright to GPL/LGPL
strings/is_prefix.c:
Change of copyright to GPL/LGPL
strings/llstr.c:
Change of copyright to GPL/LGPL
strings/longlong2str-x86.s:
Change of copyright to GPL/LGPL
strings/longlong2str.c:
Change of copyright to GPL/LGPL
strings/macros.asm:
Change of copyright to GPL/LGPL
strings/memcmp.c:
Change of copyright to GPL/LGPL
strings/memcpy.c:
Change of copyright to GPL/LGPL
strings/ptr_cmp.asm:
Change of copyright to GPL/LGPL
strings/str2int.c:
Change of copyright to GPL/LGPL
strings/str_test.c:
Change of copyright to GPL/LGPL
strings/strappend-sparc.s:
Change of copyright to GPL/LGPL
strings/strappend.c:
Change of copyright to GPL/LGPL
strings/strcend.c:
Change of copyright to GPL/LGPL
strings/strcont.c:
Change of copyright to GPL/LGPL
strings/strend-sparc.s:
Change of copyright to GPL/LGPL
strings/strfill.c:
Change of copyright to GPL/LGPL
strings/strings-x86.s:
Change of copyright to GPL/LGPL
strings/strings.asm:
Change of copyright to GPL/LGPL
strings/strinstr-sparc.s:
Change of copyright to GPL/LGPL
strings/strinstr.c:
Change of copyright to GPL/LGPL
strings/strmake-sparc.s:
Change of copyright to GPL/LGPL
strings/strmake.c:
Change of copyright to GPL/LGPL
strings/strmov-sparc.s:
Change of copyright to GPL/LGPL
strings/strmov.c:
Change of copyright to GPL/LGPL
strings/strnmov-sparc.s:
Change of copyright to GPL/LGPL
strings/strnmov.c:
Change of copyright to GPL/LGPL
strings/strstr-sparc.s:
Change of copyright to GPL/LGPL
strings/strto.c:
Change of copyright to GPL/LGPL
strings/strtol.c:
Change of copyright to GPL/LGPL
strings/strtoll.c:
Change of copyright to GPL/LGPL
strings/strtoul.c:
Change of copyright to GPL/LGPL
strings/strtoull.c:
Change of copyright to GPL/LGPL
strings/strxmov-sparc.s:
Change of copyright to GPL/LGPL
strings/strxmov.asm:
Change of copyright to GPL/LGPL
strings/udiv.c:
Change of copyright to GPL/LGPL
support-files/Makefile.am:
Change of copyright to GPL/LGPL
tests/Makefile.am:
Change of copyright to GPL/LGPL
vio/Makefile.am:
Change of copyright to GPL/LGPL
isam/.cvsignore:
Updates for 3.23.19
myisam/.cvsignore:
Updates for 3.23.19
sql-bench/Results/insert-pg_fast-Linux_2.2.14_5.0_i686:
***MISSING WEAVE***
sql-bench/Results/select-pg_fast-Linux_2.2.14_5.0_i686:
***MISSING WEAVE***
sql-bench/Results/wisconsin-pg_fast-Linux_2.2.14_5.0_i686:
***MISSING WEAVE***
sql/sql_analyse.h:
Fix bug when memory wasn't freed
sql/mysqlbinlog.cc:
Small fixes
sql/share/romanian/errmsg.txt:
***MISSING WEAVE***
include/mysql_com.h:
Replication update/LOAD TABLE FROM MASTER + other fixes
client/mysql-test.c:
***MISSING WEAVE***
myisam/Attic/ft_global.h:
This file is now in include/
extra/Attic/print_defaults.c:
Updates for text search + ORDER BY
extra/Makefile.am:
Updates for text search + ORDER BY
extra/my_print_defaults.c:
Updates for text search + ORDER BY
include/mysqld_error.h:
Updates for text search + ORDER BY
sql/item_cmpfunc.cc:
Updates for text search + ORDER BY
sql/opt_range.h:
Updates for text search + ORDER BY
sql/sql_lex.cc:
Updates for text search + ORDER BY
sql-bench/crash-me.sh:
Updates for text search + ORDER BY
sql-bench/limits/mysql.cfg:
Updates for text search + ORDER BY
sql/share/czech/errmsg.sys:
Updates for text search + ORDER BY
sql/share/czech/errmsg.txt:
Updates for text search + ORDER BY
sql/share/danish/errmsg.sys:
Updates for text search + ORDER BY
sql/share/danish/errmsg.txt:
Updates for text search + ORDER BY
sql/share/dutch/errmsg.sys:
Updates for text search + ORDER BY
sql/share/dutch/errmsg.txt:
Updates for text search + ORDER BY
sql/share/english/errmsg.sys:
Updates for text search + ORDER BY
sql/share/english/errmsg.txt:
Updates for text search + ORDER BY
sql/share/estonia/errmsg.sys:
Updates for text search + ORDER BY
sql/share/estonia/errmsg.txt:
Updates for text search + ORDER BY
sql/share/french/errmsg.sys:
Updates for text search + ORDER BY
sql/share/french/errmsg.txt:
Updates for text search + ORDER BY
sql/share/german/errmsg.sys:
Updates for text search + ORDER BY
sql/share/german/errmsg.txt:
Updates for text search + ORDER BY
sql/share/greek/errmsg.sys:
Updates for text search + ORDER BY
sql/share/greek/errmsg.txt:
Updates for text search + ORDER BY
sql/share/hungarian/errmsg.sys:
Updates for text search + ORDER BY
sql/share/hungarian/errmsg.txt:
Updates for text search + ORDER BY
sql/share/japanese/errmsg.sys:
Updates for text search + ORDER BY
sql/share/japanese/errmsg.txt:
Updates for text search + ORDER BY
sql/share/korean/errmsg.sys:
Updates for text search + ORDER BY
sql/share/korean/errmsg.txt:
Updates for text search + ORDER BY
sql/share/norwegian/errmsg.txt:
Updates for text search + ORDER BY
sql/share/norwegian-ny/errmsg.txt:
Updates for text search + ORDER BY
sql/share/polish/errmsg.sys:
Updates for text search + ORDER BY
sql/share/polish/errmsg.txt:
Updates for text search + ORDER BY
sql/share/portuguese/errmsg.sys:
Updates for text search + ORDER BY
sql/share/portuguese/errmsg.txt:
Updates for text search + ORDER BY
sql/share/romania/errmsg.sys:
Updates for text search + ORDER BY
sql/share/romania/errmsg.txt:
Updates for text search + ORDER BY
sql/share/russian/errmsg.sys:
Updates for text search + ORDER BY
sql/share/russian/errmsg.txt:
Updates for text search + ORDER BY
sql/share/slovak/errmsg.sys:
Updates for text search + ORDER BY
sql/share/slovak/errmsg.txt:
Updates for text search + ORDER BY
sql/share/spanish/errmsg.sys:
Updates for text search + ORDER BY
sql/share/spanish/errmsg.txt:
Updates for text search + ORDER BY
sql/share/swedish/errmsg.OLD:
Updates for text search + ORDER BY
sql/share/swedish/errmsg.sys:
Updates for text search + ORDER BY
sql/share/swedish/errmsg.txt:
Updates for text search + ORDER BY
support-files/mysql.server-sys5.sh:
Updates for text search + ORDER BY
extra/.cvsignore:
Fix for update + BDB tables
isam/_dbug.c:
Fix for update + BDB tables
myisam/mi_delete.c:
Fix for update + BDB tables
myisam/mi_rnext_same.c:
Fix for update + BDB tables
myisam/mi_search.c:
Fix for update + BDB tables
sql/table.cc:
Fix of core dump bugs
myisam/Makefile.am:
Aded missing file
sql/ha_berkeley.h:
Fix DELETE FROM table_name problem
Build-tools/Do-all-build-steps:
Update to final 3.23.20
Build-tools/mysql-copyright-2:
Update to final 3.23.20
Build-tools/mysql-copyright:
Update to final 3.23.20
Docs/.cvsignore:
Update to final 3.23.20
scripts/make_binary_distribution.sh:
Update to final 3.23.20
Docs/internals.texi:
Fix of licenses issues.
sql/ha_isam.h:
Added patch by Sergei for MATCH + some bug fixes.
sql/ha_isammrg.h:
Added patch by Sergei for MATCH + some bug fixes.
sql/ha_myisammrg.h:
Added patch by Sergei for MATCH + some bug fixes.
myisam/ft_search.c:
Fix of portability bug
include/ft_global.h:
Fix of portability bug
sql/log_event.cc:
One more safety fix
sql/log_event.h:
One more safety fix
isam/test2.c:
Update to 3.23.21
isam/update.c:
Update to 3.23.21
myisam/ChangeLog:
Update to 3.23.21
myisam/mi_test_all.sh:
Update to 3.23.21
myisam/mi_update.c:
Update to 3.23.21
myisam/mi_write.c:
Update to 3.23.21
scripts/.cvsignore:
Update to 3.23.21
scripts/mysql_config.sh:
Update to 3.23.21
sql/filesort.cc:
Update to 3.23.21
Docs/Support/texi2html:
removed NOSAVE attrib from TABLE tags, non-standard HTML.
include/Attic/config-win32.h:
Made update log ASCII 0 safe
myisam/mi_test_all:
***MISSING WEAVE***
sql/sql_acl.cc:
Made update log ASCII 0 safe
sql/sql_db.cc:
Made update log ASCII 0 safe
sql/sql_delete.cc:
Made update log ASCII 0 safe
sql/sql_insert.cc:
Made update log ASCII 0 safe
sql/sql_load.cc:
Made update log ASCII 0 safe
sql/sql_select.h:
Made update log ASCII 0 safe
sql/sql_update.cc:
Made update log ASCII 0 safe
sql/table.h:
Made update log ASCII 0 safe
strings/ctype-czech.c:
Made update log ASCII 0 safe
support-files/maxsql.spec.sh:
Made update log ASCII 0 safe
client/mysqlimport.c:
Update to 3.23.21
client/mysqlshow.c:
Update to 3.23.21
include/mysql.h:
Added mysql_character_set_name()
mit-pthreads/net/gethostname.c:
Added mysql_character_set_name()
scripts/Makefile.am:
Added mysql_character_set_name()
client/Makefile.am:
portability fixes
scripts/mysql_install_db.sh:
portability fixes
support-files/mysql.spec.sh:
Added mysql_config
config.h.in:
***MISSING WEAVE***
client/mysqldump.c:
Small fixes
heap/hp_rkey.c:
Small fixes
sql-bench/compare-results.sh:
Small fixes
tests/mail_to_db.pl:
Small fixes
acinclude.m4:
Configure updates for 3.23.22
BUILD/compile-pentium-debug:
Configure updates for 3.23.22
Docs/Makefile.am:
Configure updates for 3.23.22
client/get_password.c:
Configure updates for 3.23.22
client/mysqladmin.c:
Configure updates for 3.23.22
include/Makefile.am:
Configure updates for 3.23.22
include/my_global.h:
***MISSING WEAVE***
isam/info.c:
Configure updates for 3.23.22
isam/isamdef.h:
Configure updates for 3.23.22
isam/write.c:
Configure updates for 3.23.22
sql/records.cc:
Configure updates for 3.23.22
sql-bench/print-limit-table:
Configure updates for 3.23.22
sql-bench/limits/mysql-3.23.cfg:
Configure updates for 3.23.22
support-files/my-huge.cnf.sh:
Configure updates for 3.23.22
support-files/my-large.cnf.sh:
Configure updates for 3.23.22
support-files/my-medium.cnf.sh:
Configure updates for 3.23.22
myisam/ft_update.c:
This is to make ft-code to ignore keyseg.length at all
and to index the whole VARCHAR/BLOB instead...
Makefile.am:
Fixed gen_lex_hash recursion
myisam/myisampack.c:
Fixes for 3.23.22
sql/ChangeLog:
Fixes for 3.23.22
sql/nt_servc.cc:
Fixes for 3.23.22
sql/sql_class.cc:
Fixes for 3.23.22
include/my_base.h:
Fix for BDB and MERGE tables
sql/ha_myisammrg.cc:
Fix for BDB and MERGE tables
Docs/LICENSE:
Update for 3.23.22
config.sub:
Update for ia64
Build-tools/Do-compile-all:
***MISSING WEAVE***
scripts/safe_mysqld.sh:
Small bug fixes for 3.23.22
support-files/.cvsignore:
Small bug fixes for 3.23.22
scripts/mysql_find_rows.sh:
Critical bug fixes
sql/sql_class.h:
SHOW SLAVE STATUS, change in SHOW MASTER STATUS
repl-tests/include/master-slave.inc:
Replication test cases
repl-tests/test-dump/run.test:
Replication test cases
repl-tests/test-dump/table-dump-check.master:
Replication test cases
repl-tests/test-dump/table-dump-select.master:
Replication test cases
repl-tests/test-repl-ts/repl-timestamp.master:
Replication test cases
repl-tests/test-repl-ts/run.test:
Replication test cases
repl-tests/test-repl/foo-dump-master.master:
Replication test cases
repl-tests/test-repl/foo-dump-slave.master:
Replication test cases
repl-tests/test-repl/run.test:
Replication test cases
repl-tests/test-repl/sum-wlen-master.master:
Replication test cases
repl-tests/test-repl/sum-wlen-slave.master:
Replication test cases
Images/.cvsignore:
Update of div reported bugs
include/config-win.h:
Update of div reported bugs
mysys/mf_pack.c:
Update of div reported bugs
sql/field.cc:
Update of div reported bugs
sql/field.h:
Update of div reported bugs
sql/ha_myisam.h:
Update of div reported bugs
sql/handler.h:
Update of div reported bugs
sql/item.cc:
Update of div reported bugs
sql/item_func.h:
Update of div reported bugs
sql/item_timefunc.cc:
Update of div reported bugs
sql/item_timefunc.h:
Update of div reported bugs
sql/sql_string.cc:
Update of div reported bugs
sql/sql_table.cc:
Update of div reported bugs
sql/structs.h:
Update of div reported bugs
sql/time.cc:
Update of div reported bugs
strings/ctype-gbk.c:
Update of div reported bugs
strings/ctype-tis620.c:
Update of div reported bugs
strings/r_strinstr.c:
Update of div reported bugs
strings/strnlen.c:
Update of div reported bugs
support-files/mysql.server.sh:
Update of div reported bugs
myisam/mi_locking.c:
Small bug fixes
myisam/myisamdef.h:
Small bug fixes
mysys/my_thr_init.c:
Small bug fixes
myisam/mi_close.c:
Changed mutex THR_lock_isam -> THR_lock_myisam
myisam/mi_create.c:
Changed mutex THR_lock_isam -> THR_lock_myisam
myisam/mi_extra.c:
Changed mutex THR_lock_isam -> THR_lock_myisam
myisam/mi_log.c:
Changed mutex THR_lock_isam -> THR_lock_myisam
myisam/mi_open.c:
Changed mutex THR_lock_isam -> THR_lock_myisam
myisam/mi_panic.c:
Changed mutex THR_lock_isam -> THR_lock_myisam
myisam/myisamchk.c:
Changed mutex THR_lock_isam -> THR_lock_myisam
sql/item_func.cc:
Don't let MySQL use ft-keys in non-ft way
sql/opt_range.cc:
Don't let MySQL use ft-keys in non-ft way
sql-bench/Results-linux/ATIS-mysql-Linux_2.2.13_SMP_alpha:
***MISSING WEAVE***
sql-bench/Results-linux/RUN-mysql-Linux_2.2.13_SMP_alpha:
***MISSING WEAVE***
sql-bench/Results-linux/alter-table-mysql-Linux_2.2.13_SMP_alpha:
***MISSING WEAVE***
sql-bench/Results-linux/big-tables-mysql-Linux_2.2.13_SMP_alpha:
***MISSING WEAVE***
sql-bench/Results-linux/connect-mysql-Linux_2.2.13_SMP_alpha:
***MISSING WEAVE***
sql-bench/Results-linux/create-mysql-Linux_2.2.13_SMP_alpha:
***MISSING WEAVE***
sql-bench/Results-linux/insert-mysql-Linux_2.2.13_SMP_alpha:
***MISSING WEAVE***
sql-bench/Results-linux/select-mysql-Linux_2.2.13_SMP_alpha:
***MISSING WEAVE***
sql-bench/Results-linux/wisconsin-mysql-Linux_2.2.13_SMP_alpha:
***MISSING WEAVE***
sql/share/italian/errmsg.sys:
new translated error messages
sql/share/italian/errmsg.txt:
new translated error messages
libmysql/errmsg.c:
Fix to get 'Too big packet' error + fixes for Ia64
libmysql/libmysql.c:
Fix to get 'Too big packet' error + fixes for Ia64
libmysql/net.c:
Fix to get 'Too big packet' error + fixes for Ia64
include/errmsg.h:
Fix to get 'Too big packet'
mysql.proj:
Update for 3.23.22
client/mysql.cc:
Fix for rehash on reconnect (By Jeremey)
readline/rlstdc.h:
portability fixes
sql/Makefile.am:
Hack to force lex_hash.h to be generated
sql/ha_berkeley.cc:
Fixes for Berekely DB
sql/handler.cc:
Fixes for Berekely DB
sql/item.h:
Small fixes for 3.23.22
sql/net_serv.cc:
Small fixes for 3.23.22
client/completion_hash.cc:
Fixes for Ia64
sql/mini_client.cc:
Fixes for Ia64
sql/sql_select.cc:
Fixes for Ia64
.cvsignore:
Update at work for release
myisam/mi_check.c:
Fix bug in ANALYZE TABLE
sql/ha_myisam.cc:
Fix bug in ANALYZE TABLE
include/myisam.h:
Fix bug in ANALYZE TABLE
configure.in:
Fix for AIX 4.3
Build-tools/Do-compile:
Fix for local perl libraries
sql/sql_show.cc:
Fix for show processlist on SCO
include/global.h:
Fix for AIX 4.3
BUILD/compile-ia64-O0-sgicc:
Last minute updates for 3.23.22
BUILD/compile-ia64-O0:
Last minute updates for 3.23.22
BUILD/compile-ia64-O2-sgicc:
Last minute updates for 3.23.22
BUILD/compile-ia64-O2:
Last minute updates for 3.23.22
BUILD/compile-ia64-O6:
Last minute updates for 3.23.22
Docs/manual.texi:
Added paragraph in introduction pointing to SQL and MySQL books, for newbies.
sql/gen_lex_hash.cc:
CHANGE MASTER TO and other fixes
sql/lex.h:
CHANGE MASTER TO and other fixes
sql/log.cc:
CHANGE MASTER TO and other fixes
sql/mysql_priv.h:
CHANGE MASTER TO and other fixes
sql/mysqld.cc:
CHANGE MASTER TO and other fixes
sql/net_pkg.cc:
CHANGE MASTER TO and other fixes
sql/slave.cc:
CHANGE MASTER TO and other fixes
sql/sql_base.cc:
CHANGE MASTER TO and other fixes
sql/sql_lex.h:
CHANGE MASTER TO and other fixes
sql/sql_parse.cc:
CHANGE MASTER TO and other fixes
sql/sql_yacc.yy:
CHANGE MASTER TO and other fixes
Diffstat (limited to 'mysys')
101 files changed, 17970 insertions, 0 deletions
diff --git a/mysys/.cvsignore b/mysys/.cvsignore new file mode 100644 index 00000000000..056ecc2691c --- /dev/null +++ b/mysys/.cvsignore @@ -0,0 +1,10 @@ +.deps +.libs +Makefile +Makefile.in +st35l1t6 +test_charset +test_thr_alarm +test_thr_lock +test_vsnprintf +testhash diff --git a/mysys/COPYING.LIB b/mysys/COPYING.LIB new file mode 100755 index 00000000000..eb685a5ec98 --- /dev/null +++ b/mysys/COPYING.LIB @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/mysys/ChangeLog b/mysys/ChangeLog new file mode 100644 index 00000000000..e24fc00b493 --- /dev/null +++ b/mysys/ChangeLog @@ -0,0 +1,221 @@ +2000-02-16 Michael Widenius <monty@monty.pp.sci.fi> + +* Added an extra argument to the compare routine for queues to allow + more advanced key compare functions. + +2000-02-10 Michael Widenius <monty@monty.pp.sci.fi> + +* Added THR_READ_NO_INSERT lock privilege to thr_lock. + +1999-08-21 Michael Widenius <monty@tik.pp.sci.fi> + +* Fix that '-1.49 or -1.49' is true +* Allow negative hexadecimal numbers (like -0x0f). +* Fixed problem with auto_increment on float and double. + +Wed Dec 17 02:13:58 1997 <monty@monty.pp.sci.fi> + +* Faster flush of keycache. + +Sat Dec 2 21:36:20 1995 Michael Widenius (monty@bitch) + + * array.c push_element & alloc_element. + +Wed Mar 3 00:54:20 1993 Michael Widenius (monty@bitch) + + * Removed automatic O_TRUNC from my_create. + +Wed Oct 28 02:10:56 1992 Michael Widenius (monty@bitch) + + * Enabled ASNYNC_IO on SUN. + +Mon Aug 31 23:51:13 1992 Michael Widenius (monty@bitch) + + * Changed tree_insert to return element if ok. + * Added new define tree_set_pointer(). + * Chagned delete_queue() to not free if allready freed. + +Mon Aug 17 01:46:36 1992 Michael Widenius (monty@bitch) + + * Added ny cashing-rutine mf_iocash for quicker io. + +Wed Aug 12 13:41:18 1992 Michael Widenius (monty@bitch) + + * Added new function get_copy_of_memory for combined malloc/copy. + * Splitted my_malloc to three files. + +Thu Jan 23 22:02:37 1992 Michael Widenius (monty at LYNX) + + * Added range-checks and aligned checks on ptrs to + safe_malloc:free and safe_malloc:realloc to catch more + error nicely without core-dumps. + +Wed Nov 13 01:52:18 1991 Michael Widenius (monty at LYNX) + + * Added use of mysys as a shared library. + +Sat Nov 9 14:38:21 1991 Michael Widenius (monty at LYNX) + + * Added expand of ~username to unpack_dirname. + +Tue Sep 17 21:15:08 1991 Michael Widenius (monty at LYNX) + + * Don't free null-pointers if passed to my_free + +Fri May 17 20:11:27 1991 Michael Widenius (monty at LYNX) + + * Changed all char * to string. (Can't change const char * because + of bug in C-definition. + +Tue Apr 30 01:32:56 1991 Michael Widenius (monty at LYNX) + + * my_path now examines environment for posix variable "_" if + progname is given and has no path. + +Mon Apr 22 16:12:56 1991 Michael Widenius (monty at LYNX) + + * Added function my_load_path() to fix path to a hard-path. + +Mon Apr 15 22:08:58 1991 Michael Widenius (monty at LYNX) + + * Added more info on DBUG-stream when freeing unallocated data. + +Wed Apr 3 18:41:28 1991 Michael Widenius (monty at LYNX) + + * Added global flag sf_malloc_no_sanity to make it possibly + to avoid sanity-checks in right code with uses malloc a lot. + +Tue Mar 26 15:09:45 1991 Mikael WIDENIUS (monty at panther) + + * Made soundex look nicer + +Sat Mar 23 10:49:49 1991 Michael Widenius (monty at LYNX) + + * Added init of alarm variables to skipp some warnings from gcc. + +Tue Mar 5 16:50:34 1991 Michael Widenius (monty at LYNX) + + * Our qsort now only test if compare() function returns >= 0 + and is optimized for compare() returning > 0. + +Fri Nov 23 23:53:46 1990 Michael Widenius (monty at LYNX) + + * Added function my_set_alarm_variable to get a variable set + on some time. + my_alarm.h added for functions who want to print stat after + a given time or after a number of loops. + Changed my_lock to use new function and use defines in my_alarm.h + +Mon Oct 1 13:16:15 1990 Michael Widenius (monty at LYNX) + + * Added use of asynchronic io in read_cash_record(). + * Added write_cash and flush_write_cash to record cashing. + +Sun Sep 16 22:05:25 1990 Michael Widenius (monty at LYNX) + + * Added optional alarm to my_lock if one has FCNTL_LOCK. Added new + defines to my_sys.h. + +Mon Aug 27 22:20:38 1990 Michael Widenius (monty at lynx) + + * my_end() now can print output about executed program. + * Added parameter-defines for my_end in my_sys.h + +Sun Apr 1 23:29:47 1990 Monty (monty at monty) + + * Changed mf_keydisk.c to have separate functions for read and write. + Read can now return pointer to intern key-buffer to skipp + unessessary memcpy-s. + +Fri Mar 23 23:03:39 1990 Monty (monty at monty) + + * function test_if_hard_pathname() added in dirname.c + * my_getwd now only saves changed current dir if dir is a + hard pathname. + * changed my_path() to use test_if_hard_pathname() + +Thu Mar 1 14:47:59 1990 Monty (monty at monty) + + * New function my_path(). + +Sat Feb 24 02:54:35 1990 Monty (monty at monty) + + * Added print of my_progname in my_mess.c + +Sun Feb 11 17:55:58 1990 David Axmark (davida at isil) + + * Concatenated libarys my_func and my_sys because of to much + crosswise dependencies. + * Fixed varagrs code in mf_fixadr.c + +Mon Dec 4 17:36:16 1989 Monty (monty at monty) + + * Changed safemalloc() to use my_message() if out of memory and + to check MY_WME if we want this error-messages. + * Changed my_setwd() to use dos_setdrive() insted of system(). + +Wed Oct 25 02:56:07 1989 Monty (monty at monty) + + * Changed my_mktmp1() to work like tempnam() with default dirname. + * Changed name of my_mktmp1.c to my_tempnam.c + +Thu Oct 19 16:39:27 1989 David Axmark (davida at isil) + + * Removed libary mysysnc. Instead added a hook to my_error that + can call my_message if needed. + +Thu Oct 5 01:33:29 1989 David Axmark (davida at isil) + + * Use MY_SEEK_{SET,CUR,END} as arguments to my_seek + + * Added a a array of structs that holds properties of open files. + Removed include file extras.h + +Wed Jun 21 01:34:04 1989 Monty (monty at monty) + + * Added two new malloc-functions: my_once_alloc() and + my_once_free(). These give easyer and quicker startup. + +Mon May 22 14:03:44 1989 Monty (monty at monty) + + * Fixed my_getwd and my_setwd so they work. + * Added extern variabel curr_char[] with is set to current + directory after my_getwd() or my_setwd(); + +Mon Jan 23 03:38:50 1989 Monty (monty at monty) + + * Changed my_chsize to check if NO_CHSIZE is defined. If new file + should be shorter it fills unused part with null. + * Changed my_lock to not check for arg 0 (Functions should use + LK_TO_EOF to lock all file. + +Tue Dec 6 15:09:44 1988 Monty (monty at monty) + + * Added DBUG_PRINT if error in my_seek. + +Mon Dec 5 15:58:48 1988 Monty (monty at monty) + + * Added DBUG_PRINT if not all byte read/written in my_read(), + my_fread(), my_write() and my_fwrite(); + +Sat Dec 3 01:48:03 1988 Monty (monty at monty) + + * Fixed bug in Makefile; quick did't work. + * Changed safemalloc to use bmove, bfill and memcpy when handling + memoryblocks. + +Fri Dec 2 03:29:21 1988 Monty (monty at monty) + + * Added more defines under MEMORY in my_func.h + * Added functions to llib-lmysys. + * Removed RCS/* files and installed ewerything as stable. + (Because errors in old RCS-files. + +Wed Nov 9 00:32:33 1988 Monty (monty at monty) + + * Changed realloc for MSDOS; Previous version freed old block on + * error, new version (of compiler) dosn't. + +Wed Oct 26 21:07:27 1988 Monty (monty at monty) + + * Fixed missing updateing of my_stream_opened; diff --git a/mysys/Makefile.am b/mysys/Makefile.am new file mode 100644 index 00000000000..658b68d6861 --- /dev/null +++ b/mysys/Makefile.am @@ -0,0 +1,93 @@ +# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +MYSQLDATAdir = $(localstatedir) +MYSQLSHAREdir = $(pkgdatadir) +MYSQLBASEdir= $(prefix) +INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include -I.. +pkglib_LIBRARIES = libmysys.a +LDADD = libmysys.a ../dbug/libdbug.a \ + ../strings/libmystrings.a +noinst_HEADERS = mysys_priv.h my_static.h +libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\ + mf_path.c mf_loadpath.c\ + my_open.c my_create.c my_seek.c my_read.c \ + my_pread.c my_write.c \ + mf_reccache.c mf_keycache.c mf_iocache.c mf_cache.c \ + my_lock.c mf_brkhant.c my_alarm.c \ + my_malloc.c my_realloc.c my_once.c mulalloc.c \ + my_alloc.c safemalloc.c my_fopen.c my_fstream.c \ + my_error.c errors.c my_div.c my_messnc.c \ + mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \ + mf_pack.c mf_pack2.c mf_unixpath.c mf_stripp.c \ + mf_casecnv.c mf_soundex.c mf_wcomp.c mf_wfile.c \ + mf_qsort.c mf_qsort2.c mf_sort.c \ + ptr_cmp.c mf_radix.c queues.c \ + tree.c list.c hash.c array.c string.c typelib.c \ + my_copy.c my_append.c my_lib.c \ + my_delete.c my_rename.c my_redel.c my_tempnam.c \ + my_chsize.c my_lread.c my_lwrite.c my_clock.c \ + my_quick.c my_lockmem.c my_static.c \ + getopt.c getopt1.c getvar.c my_mkdir.c \ + default.c my_compress.c checksum.c raid.cc my_net.c \ + my_vsnprintf.c charset.c +EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \ + thr_mutex.c thr_rwlock.c +libmysys_a_LIBADD = @THREAD_LOBJECTS@ +# test_fn removed 980815 since it not upp to date test_dir +noinst_PROGRAMS = testhash test_charset @THREAD_LPROGRAMS@ +# test_dir_DEPENDENCIES= $(LIBRARIES) +testhash_DEPENDENCIES= $(LIBRARIES) +test_charset_DEPENDENCIES= $(LIBRARIES) +EXTRA_PROGRAMS = +DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \ + -DDATADIR="\"$(MYSQLDATAdir)\"" \ + -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \ + -DDATADIR="\"$(MYSQLDATAdir)\"" \ + -DSHAREDIR="\"$(MYSQLSHAREdir)\"" \ + @DEFS@ + +getopt1.o: @THREAD_LOBJECTS@ + +OMIT_DEPENDENCIES = pthread.h stdio.h __stdio.h stdlib.h __stdlib.h math.h\ + __math.h time.h __time.h unistd.h __unistd.h types.h \ + xtypes.h ac-types.h posix.h string.h __string.h \ + errno.h socket.h inet.h dirent.h netdb.h \ + cleanup.h cond.h debug_out.h fd.h kernel.h mutex.h \ + prio_queue.h pthread_attr.h pthread_once.h queue.h\ + sleep.h specific.h version.h pwd.h timers.h uio.h \ + cdefs.h machdep.h signal.h __signal.h util.h + +# I hope this always does the right thing. Otherwise this is only test programs +FLAGS=$(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) + +test_thr_alarm: thr_alarm.c $(LIBRARIES) + $(LINK) $(FLAGS) -DMAIN $(srcdir)/thr_alarm.c $(LDADD) $(LIBS) + +test_thr_lock: thr_lock.c $(LIBRARIES) + $(LINK) $(FLAGS) -DMAIN $(srcdir)/thr_lock.c $(LDADD) $(LIBS) + +test_dir: test_dir.c $(LIBRARIES) + $(LINK) $(FLAGS) -DMAIN $(srcdir)/test_dir.c $(LDADD) $(LIBS) + +test_charset: test_charset.c $(LIBRARIES) + $(LINK) $(FLAGS) -DMAIN $(srcdir)/test_charset.c $(LDADD) $(LIBS) + +test_vsnprintf: my_vsnprintf.c $(LIBRARIES) + $(LINK) $(FLAGS) -DMAIN $(srcdir)/my_vsnprintf.c $(LDADD) $(LIBS) + +test_hash: test_hash.c $(LIBRARIES) + $(LINK) $(FLAGS) -DMAIN $(srcdir)/test_dir.c $(LDADD) $(LIBS) diff --git a/mysys/array.c b/mysys/array.c new file mode 100644 index 00000000000..17e5ded322b --- /dev/null +++ b/mysys/array.c @@ -0,0 +1,177 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Handling of arrays that can grow dynamicly. */ + +#if defined(WIN32) || defined(__WIN__) +#undef SAFEMALLOC /* Problems with threads */ +#endif + +#include "mysys_priv.h" +#include "m_string.h" + +/* + Initiate array and alloc space for init_alloc elements. Array is usable + even if space allocation failed +*/ + +my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size, + uint init_alloc, uint alloc_increment) +{ + DBUG_ENTER("init_dynamic_array"); + if (!alloc_increment) + { + alloc_increment=max((8192-MALLOC_OVERHEAD)/element_size,16); + if (init_alloc > 8 && alloc_increment > init_alloc * 2) + alloc_increment=init_alloc*2; + } + + if (!init_alloc) + init_alloc=alloc_increment; + array->elements=0; + array->max_element=init_alloc; + array->alloc_increment=alloc_increment; + array->size_of_element=element_size; + if (!(array->buffer=(char*) my_malloc(element_size*init_alloc,MYF(MY_WME)))) + { + array->max_element=0; + DBUG_RETURN(TRUE); + } + DBUG_RETURN(FALSE); +} + + +my_bool insert_dynamic(DYNAMIC_ARRAY *array, gptr element) +{ + gptr buffer; + if (array->elements == array->max_element) + { /* Call only when nessesary */ + if (!(buffer=alloc_dynamic(array))) + return TRUE; + } + else + { + buffer=array->buffer+(array->elements * array->size_of_element); + array->elements++; + } + memcpy(buffer,element,(size_t) array->size_of_element); + return FALSE; +} + + + /* Alloc room for one element */ + +byte *alloc_dynamic(DYNAMIC_ARRAY *array) +{ + if (array->elements == array->max_element) + { + char *new_ptr; + if (!(new_ptr=(char*) my_realloc(array->buffer,(array->max_element+ + array->alloc_increment)* + array->size_of_element, + MYF(MY_WME | MY_ALLOW_ZERO_PTR)))) + return 0; + array->buffer=new_ptr; + array->max_element+=array->alloc_increment; + } + return array->buffer+(array->elements++ * array->size_of_element); +} + + + /* remove last element from array and return it */ + +byte *pop_dynamic(DYNAMIC_ARRAY *array) +{ + if (array->elements) + return array->buffer+(--array->elements * array->size_of_element); + return 0; +} + + +my_bool set_dynamic(DYNAMIC_ARRAY *array, gptr element, uint idx) +{ + if (idx >= array->elements) + { + if (idx >= array->max_element) + { + uint size; + char *new_ptr; + size=(idx+array->alloc_increment)/array->alloc_increment; + size*= array->alloc_increment; + if (!(new_ptr=(char*) my_realloc(array->buffer,size* + array->size_of_element, + MYF(MY_WME | MY_ALLOW_ZERO_PTR)))) + return TRUE; + array->buffer=new_ptr; + array->max_element=size; + } + bzero((gptr) (array->buffer+array->elements*array->size_of_element), + (idx - array->elements)*array->size_of_element); + array->elements=idx+1; + } + memcpy(array->buffer+(idx * array->size_of_element),element, + (size_t) array->size_of_element); + return FALSE; +} + + +void get_dynamic(DYNAMIC_ARRAY *array, gptr element, uint idx) +{ + if (idx >= array->elements) + { + DBUG_PRINT("warning",("To big array idx: %d, array size is %d", + idx,array->elements)); + bzero(element,array->size_of_element); + return; + } + memcpy(element,array->buffer+idx*array->size_of_element, + (size_t) array->size_of_element); +} + + +void delete_dynamic(DYNAMIC_ARRAY *array) +{ + if (array->buffer) + { + my_free(array->buffer,MYF(MY_WME)); + array->buffer=0; + array->elements=array->max_element=0; + } +} + + +void delete_dynamic_element(DYNAMIC_ARRAY *array, uint idx) +{ + char *ptr=array->buffer+array->size_of_element*idx; + array->elements--; + memmove(ptr,ptr+array->size_of_element, + (array->elements-idx)*array->size_of_element); +} + + +void freeze_size(DYNAMIC_ARRAY *array) +{ + uint elements=max(array->elements,1); + + if (array->buffer && array->max_element != elements) + { + array->buffer=(char*) my_realloc(array->buffer, + elements*array->size_of_element, + MYF(MY_WME)); + array->max_element=elements; + } +} diff --git a/mysys/charset.c b/mysys/charset.c new file mode 100644 index 00000000000..88b0972431e --- /dev/null +++ b/mysys/charset.c @@ -0,0 +1,532 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include "mysys_err.h" +#include <m_ctype.h> +#include <m_string.h> +#include <my_dir.h> + +const char *charsets_dir = NULL; +static DYNAMIC_ARRAY cs_info_table; +static TYPELIB available_charsets; +static int charset_initialized=0; + +#define MAX_LINE 1024 + +#define CTYPE_TABLE_SIZE 257 +#define TO_LOWER_TABLE_SIZE 256 +#define TO_UPPER_TABLE_SIZE 256 +#define SORT_ORDER_TABLE_SIZE 256 + +struct simpleconfig_buf_st { + FILE *f; + char buf[MAX_LINE]; + char *p; +}; + +/* Defined in strings/ctype.c */ + +CHARSET_INFO *find_compiled_charset(uint cs_number); +uint compiled_charset_number(const char *name); +const char *compiled_charset_name(uint charset_number); + + +static my_bool get_word(struct simpleconfig_buf_st *fb, char *buf) +{ + char *endptr=fb->p; + + for (;;) + { + while (isspace(*endptr)) + ++endptr; + if (*endptr && *endptr != '#') /* Not comment */ + break; /* Found something */ + if ((fgets(fb->buf, sizeof(fb->buf), fb->f)) == NULL) + return TRUE; /* end of file */ + endptr = fb->buf; + } + + while (!isspace(*endptr)) + *buf++= *endptr++; + *buf=0; + fb->p = endptr; + + return FALSE; +} + + +static char *get_charsets_dir(char *buf) +{ + const char *sharedir = SHAREDIR; + DBUG_ENTER("get_charsets_dir"); + + if (charsets_dir != NULL) + strnmov(buf, charsets_dir, FN_REFLEN); + else + { + if (test_if_hard_path(sharedir) || + is_prefix(sharedir, DEFAULT_CHARSET_HOME)) + strxmov(buf, sharedir, "/", CHARSET_DIR, NullS); + else + strxmov(buf, DEFAULT_CHARSET_HOME, "/", sharedir, "/", CHARSET_DIR, + NullS); + } + convert_dirname(buf); + DBUG_PRINT("info",("charsets dir='%s'", buf)); + DBUG_RETURN(strend(buf)); +} + + +static my_bool read_charset_index(TYPELIB *charsets, myf myflags) +{ + struct simpleconfig_buf_st fb; + char buf[MAX_LINE]; + DYNAMIC_ARRAY cs; + my_string s; + + strmov(get_charsets_dir(buf), "Index"); + + if ((fb.f = my_fopen(buf, O_RDONLY, myflags)) == NULL) + return TRUE; + fb.buf[0] = '\0'; + fb.p = fb.buf; + + if (init_dynamic_array(&cs, sizeof(my_string), 32, 32)) + return TRUE; + + while (!get_word(&fb, buf)) + { + uint length; + if (!(s= (char*) my_once_alloc(length=strlen(buf)+1, myflags))) + { + my_fclose(fb.f,myflags); + return TRUE; + } + memcpy(s,buf,length); + insert_dynamic(&cs, (gptr) &s); + } + my_fclose(fb.f,myflags); + + /* I seriously doubt this is the best way to initialize this + * TYPELIB from the Index file. But it's the best way I could + * come up with right now. */ + + charsets->count = cs.elements; + charsets->name = ""; + if (!(charsets->type_names = + (const char **) my_once_alloc((cs.elements + 1) * sizeof(const char *), + myflags))) + return TRUE; + /* unwarranted chumminess with dynamic_array implementation? */ + memcpy((char*) charsets->type_names, cs.buffer, + cs.elements * sizeof(my_string *)); + charsets->type_names[cs.elements] = NullS; + delete_dynamic(&cs); + + return FALSE; +} + + +static my_bool init_available_charsets(myf myflags) +{ + my_bool error=0; + /* + We have to use charset_initialized to not lock on THR_LOCK_charset + inside get_internal_charset... + */ + if (!charset_initialized) + { + /* + To make things thread safe we are not allowing other threads to interfere + while we may changing the cs_info_table + */ + pthread_mutex_lock(&THR_LOCK_charset); + if (!cs_info_table.buffer) /* If not initialized */ + { + init_dynamic_array(&cs_info_table, sizeof(CHARSET_INFO*), 16, 8); + error = read_charset_index(&available_charsets, myflags); + } + charset_initialized=1; + pthread_mutex_unlock(&THR_LOCK_charset); + } + return error || available_charsets.count == 0; +} + + +void free_charsets(void) +{ + delete_dynamic(&cs_info_table); +} + + +static my_bool fill_array(uchar *array, int sz, struct simpleconfig_buf_st *fb) +{ + char buf[MAX_LINE]; + while (sz--) + { + if (get_word(fb, buf)) + { + DBUG_PRINT("error",("get_word failed, expecting %d more words", sz + 1)); + return 1; + } + *array++ = (uchar) strtol(buf, NULL, 16); + } + return 0; +} + + +static void get_charset_conf_name(uint cs_number, char *buf) +{ + strxmov(get_charsets_dir(buf), + get_type(&available_charsets, cs_number - 1), ".conf", NullS); +} + + +static my_bool read_charset_file(uint cs_number, CHARSET_INFO *set, + myf myflags) +{ + struct simpleconfig_buf_st fb; + char buf[FN_REFLEN]; + my_bool result; + DBUG_ENTER("read_charset_file"); + DBUG_PRINT("enter",("cs_number: %d", cs_number)); + + if (cs_number <= 0) + DBUG_RETURN(TRUE); + + get_charset_conf_name(cs_number, buf); + DBUG_PRINT("info",("file name: %s", buf)); + + if ((fb.f = my_fopen(buf, O_RDONLY, myflags)) == NULL) + DBUG_RETURN(TRUE); + + fb.buf[0] = '\0'; /* Init for get_word */ + fb.p = fb.buf; + + result=FALSE; + if (fill_array(set->ctype, CTYPE_TABLE_SIZE, &fb) || + fill_array(set->to_lower, TO_LOWER_TABLE_SIZE, &fb) || + fill_array(set->to_upper, TO_UPPER_TABLE_SIZE, &fb) || + fill_array(set->sort_order, SORT_ORDER_TABLE_SIZE, &fb)) + result=TRUE; + + my_fclose(fb.f, MYF(0)); + DBUG_RETURN(result); +} + + +uint get_charset_number(const char *charset_name) +{ + my_bool error; + error = init_available_charsets(MYF(0)); /* If it isn't initialized */ + if (error) + return compiled_charset_number(charset_name); + else + return find_type((char*)charset_name, &available_charsets, 1); +} + +const char *get_charset_name(uint charset_number) +{ + my_bool error; + error = init_available_charsets(MYF(0)); /* If it isn't initialized */ + if (error) + return compiled_charset_name(charset_number); + else + return get_type(&available_charsets, charset_number - 1); +} + + +static CHARSET_INFO *find_charset(CHARSET_INFO **table, uint cs_number, + size_t tablesz) +{ + uint i; + for (i = 0; i < tablesz; ++i) + if (table[i]->number == cs_number) + return table[i]; + return NULL; +} + +static CHARSET_INFO *find_charset_by_name(CHARSET_INFO **table, const char *name, + size_t tablesz) +{ + uint i; + for (i = 0; i < tablesz; ++i) + if (!strcmp(table[i]->name,name)) + return table[i]; + return NULL; +} + +static CHARSET_INFO *add_charset(uint cs_number, const char *cs_name) +{ + CHARSET_INFO tmp_cs,*cs; + uchar tmp_ctype[CTYPE_TABLE_SIZE]; + uchar tmp_to_lower[TO_LOWER_TABLE_SIZE]; + uchar tmp_to_upper[TO_UPPER_TABLE_SIZE]; + uchar tmp_sort_order[SORT_ORDER_TABLE_SIZE]; + + /* Don't allocate memory if we are not sure we can find the char set */ + cs= &tmp_cs; + bzero((char*) cs, sizeof(*cs)); + cs->ctype=tmp_ctype; + cs->to_lower=tmp_to_lower; + cs->to_upper=tmp_to_upper; + cs->sort_order=tmp_sort_order; + if (read_charset_file(cs_number, cs, MYF(MY_WME))) + return NULL; + + cs = (CHARSET_INFO*) my_once_alloc(sizeof(CHARSET_INFO), + MYF(MY_WME)); + *cs=tmp_cs; + cs->name = (char *) my_once_alloc(strlen(cs_name) + 1, MYF(MY_WME)); + cs->ctype = (uchar*) my_once_alloc(CTYPE_TABLE_SIZE, MYF(MY_WME)); + cs->to_lower = (uchar*) my_once_alloc(TO_LOWER_TABLE_SIZE, MYF(MY_WME)); + cs->to_upper = (uchar*) my_once_alloc(TO_UPPER_TABLE_SIZE, MYF(MY_WME)); + cs->sort_order=(uchar*) my_once_alloc(SORT_ORDER_TABLE_SIZE, MYF(MY_WME)); + cs->number = cs_number; + memcpy((char*) cs->name, (char*) cs_name, strlen(cs_name) + 1); + memcpy((char*) cs->ctype, (char*) tmp_ctype, sizeof(tmp_ctype)); + memcpy((char*) cs->to_lower, (char*) tmp_to_lower, sizeof(tmp_to_lower)); + memcpy((char*) cs->to_upper, (char*) tmp_to_upper, sizeof(tmp_to_upper)); + memcpy((char*) cs->sort_order, (char*) tmp_sort_order, + sizeof(tmp_sort_order)); + insert_dynamic(&cs_info_table, (gptr) &cs); + return cs; +} + +static CHARSET_INFO *get_internal_charset(uint cs_number) +{ + CHARSET_INFO *cs; + /* + To make things thread safe we are not allowing other threads to interfere + while we may changing the cs_info_table + */ + pthread_mutex_lock(&THR_LOCK_charset); + if (!(cs = find_charset((CHARSET_INFO**) cs_info_table.buffer, cs_number, + cs_info_table.elements))) + if (!(cs = find_compiled_charset(cs_number))) + cs=add_charset(cs_number, get_charset_name(cs_number)); + pthread_mutex_unlock(&THR_LOCK_charset); + return cs; +} + + +static CHARSET_INFO *get_internal_charset_by_name(const char *name) +{ + CHARSET_INFO *cs; + /* + To make things thread safe we are not allowing other threads to interfere + while we may changing the cs_info_table + */ + pthread_mutex_lock(&THR_LOCK_charset); + if (!(cs = find_charset_by_name((CHARSET_INFO**) cs_info_table.buffer, name, + cs_info_table.elements))) + if (!(cs = find_compiled_charset_by_name(name))) + cs=add_charset(get_charset_number(name), name); + pthread_mutex_unlock(&THR_LOCK_charset); + return cs; +} + + +CHARSET_INFO *get_charset(uint cs_number, myf flags) +{ + CHARSET_INFO *cs; + (void) init_available_charsets(MYF(0)); /* If it isn't initialized */ + cs=get_internal_charset(cs_number); + + if (!cs && flags & MY_WME) + { + char index_file[FN_REFLEN], cs_string[23]; + strmov(get_charsets_dir(index_file), "Index"); + cs_string[0]='#'; + int10_to_str(cs_number, cs_string+1, 10); + my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_string, index_file); + } + return cs; +} + +my_bool set_default_charset(uint cs, myf flags) +{ + CHARSET_INFO *new; + DBUG_ENTER("set_default_charset"); + DBUG_PRINT("enter",("character set: %d",(int) cs)); + new = get_charset(cs, flags); + if (!new) + { + DBUG_PRINT("error",("Couldn't set default character set")); + DBUG_RETURN(TRUE); /* error */ + } + default_charset_info = new; + DBUG_RETURN(FALSE); +} + +CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags) +{ + CHARSET_INFO *cs; + (void) init_available_charsets(MYF(0)); /* If it isn't initialized */ + cs=get_internal_charset_by_name(cs_name); + + if (!cs && (flags & MY_WME)) + { + char index_file[FN_REFLEN]; + strmov(get_charsets_dir(index_file), "Index"); + my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_name, index_file); + } + + return cs; +} + +my_bool set_default_charset_by_name(const char *cs_name, myf flags) +{ + CHARSET_INFO *new; + DBUG_ENTER("set_default_charset_by_name"); + DBUG_PRINT("enter",("character set: %s", cs_name)); + new = get_charset_by_name(cs_name, flags); + if (!new) + { + DBUG_PRINT("error",("Couldn't set default character set")); + DBUG_RETURN(TRUE); /* error */ + } + + default_charset_info = new; + DBUG_RETURN(FALSE); +} + +/* Only append name if it doesn't exist from before */ + +static my_bool charset_in_string(const char *name, DYNAMIC_STRING *s) +{ + uint length=strlen(name); + const char *pos; + for (pos=s->str ; (pos=strstr(pos,name)) ; pos++) + { + if (! pos[length] || pos[length] == ' ') + return TRUE; /* Already existed */ + } + + return FALSE; +} + +static void charset_append(DYNAMIC_STRING *s, const char *name) +{ + if (!charset_in_string(name, s)) { + dynstr_append(s, name); + dynstr_append(s, " "); + } +} + + +/* Returns a dynamically-allocated string listing the character sets + requested. The caller is responsible for freeing the memory. */ + +char * list_charsets(myf want_flags) +{ + DYNAMIC_STRING s; + char *p; + + init_dynamic_string(&s, NullS, 256, 1024); + + if (want_flags & MY_COMPILED_SETS) + { + CHARSET_INFO *cs; + for (cs = compiled_charsets; cs->number > 0; cs++) + { + dynstr_append(&s, cs->name); + dynstr_append(&s, " "); + } + } + + if (want_flags & MY_CONFIG_SETS) + { + uint i; + const char *cs_name; + char buf[FN_REFLEN]; + MY_STAT stat; + + for (i = 0; i < available_charsets.count; i++) + { + cs_name = get_type(&available_charsets, i); + if (charset_in_string(cs_name, &s)) + continue; + get_charset_conf_name(i + 1, buf); + if (!my_stat(buf, &stat, MYF(0))) + continue; /* conf file doesn't exist */ + dynstr_append(&s, cs_name); + dynstr_append(&s, " "); + } + } + + if (want_flags & MY_INDEX_SETS) + { + uint i; + for (i = 0; i < available_charsets.count; i++) + charset_append(&s, get_type(&available_charsets, i)); + } + + if (want_flags & MY_LOADED_SETS) + { + uint i; + for (i = 0; i < cs_info_table.elements; i++) + charset_append(&s, + dynamic_element(&cs_info_table, i, CHARSET_INFO *)->name); + } + s.str[s.length - 1] = '\0'; /* chop trailing space */ + p = my_strdup(s.str, MYF(MY_WME)); + dynstr_free(&s); + + return p; +} + +/**************************************************************************** +* Code for debugging. +****************************************************************************/ + + +static void _print_array(uint8 *data, uint size) +{ + uint i; + for (i = 0; i < size; ++i) + { + if (i == 0 || i % 16 == size % 16) printf(" "); + printf(" %02x", data[i]); + if ((i+1) % 16 == size % 16) printf("\n"); + } +} + +/* _print_csinfo is called from test_charset.c */ +void _print_csinfo(CHARSET_INFO *cs) +{ + printf("%s #%d\n", cs->name, cs->number); + printf("ctype:\n"); _print_array(cs->ctype, 257); + printf("to_lower:\n"); _print_array(cs->to_lower, 256); + printf("to_upper:\n"); _print_array(cs->to_upper, 256); + printf("sort_order:\n"); _print_array(cs->sort_order, 256); + printf("collate: %3s (%d, %p, %p, %p, %p, %p)\n", + cs->strxfrm_multiply ? "yes" : "no", + cs->strxfrm_multiply, + cs->strcoll, + cs->strxfrm, + cs->strnncoll, + cs->strnxfrm, + cs->like_range); + printf("multi-byte: %3s (%d, %p, %p, %p)\n", + cs->mbmaxlen ? "yes" : "no", + cs->mbmaxlen, + cs->ismbchar, + cs->ismbhead, + cs->mbcharlen); +} diff --git a/mysys/checksum.c b/mysys/checksum.c new file mode 100644 index 00000000000..00861853945 --- /dev/null +++ b/mysys/checksum.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Calculate a long checksum for a memoryblock. Used to verify pack_isam */ + +#include <global.h> +#include "my_sys.h" + +ulong checksum(const byte *mem, uint count) +{ + ulong crc; + for (crc=0; count-- ; mem++) + crc=((crc << 1) + *((uchar*) mem)) + + test(crc & ((ulong) 1L << (8*sizeof(ulong)-1))); + return crc; +} diff --git a/mysys/default.c b/mysys/default.c new file mode 100644 index 00000000000..ae4ba5044be --- /dev/null +++ b/mysys/default.c @@ -0,0 +1,362 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/**************************************************************************** +** Add all options from files named "group".cnf from the default_directories +** before the command line arguments. +** On Windows defaults will also search in the Windows directory for a file +** called 'group'.ini +** As long as the program uses the last argument for conflicting +** options one only have to add a call to "load_defaults" to enable +** use of default values. +** pre- and end 'blank space' are removed from options and values. The +** following escape sequences are recognized in values: \b \t \n \r \\ +** +** The following arguments are handled automaticly; If used, they must be +** first argument on the command line! +** --no-defaults ; no options are read. +** --print-defaults ; Print the modified command line and exit +** --defaults-file=full-path-to-default-file ; Only this file will be read. +****************************************************************************/ + +#undef SAFEMALLOC /* safe_malloc is not yet initailized */ + +#include "mysys_priv.h" +#include "m_string.h" +#include "m_ctype.h" + +/* Which directories are searched for options (and in which order) */ + +const char *default_directories[]= { +#ifdef __WIN__ +"C:/", +#else +"/etc/", +#endif +#ifdef DATADIR +DATADIR, +#endif +#ifndef __WIN__ +"~/", +#endif +NullS, +}; + +#define default_ext ".cnf" /* extension for config file */ +#ifdef __WIN__ +#include <winbase.h> +#define windows_ext ".ini" +#endif + +static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc, + const char *dir, const char *config_file, + const char *ext, TYPELIB *group); + + +void load_defaults(const char *conf_file, const char **groups, + int *argc, char ***argv) +{ + DYNAMIC_ARRAY args; + const char **dirs, *extra_default_file; + TYPELIB group; + my_bool found_print_defaults=0; + MEM_ROOT alloc; + char *ptr,**res; + DBUG_ENTER("load_defaults"); + + init_alloc_root(&alloc,128); + if (*argc >= 2 && !strcmp(argv[0][1],"--no-defaults")) + { + /* remove the --no-defaults argument and return only the other arguments */ + uint i; + if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+ + (*argc + 1)*sizeof(char*)))) + goto err; + res= (char**) (ptr+sizeof(alloc)); + res[0]= **argv; /* Copy program name */ + for (i=2 ; i < (uint) *argc ; i++) + res[i-1]=argv[0][i]; + (*argc)--; + *argv=res; + *(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */ + DBUG_VOID_RETURN; + } + + /* Check if we want to force the use a specific default file */ + extra_default_file=0; + if (*argc >= 2 && is_prefix(argv[0][1],"--defaults-file=")) + extra_default_file=strchr(argv[0][1],'=')+1; + + group.count=0; + group.name= "defaults"; + group.type_names= groups; + for (; *groups ; groups++) + group.count++; + + if (init_dynamic_array(&args, sizeof(char*),*argc, 32)) + goto err; + if (extra_default_file) + { + if (search_default_file(&args, &alloc, "", extra_default_file, "", + &group)) + goto err; + } + else if (dirname_length(conf_file)) + { + if (search_default_file(&args, &alloc, NullS, conf_file, default_ext, + &group)) + goto err; + } + else + { +#ifdef __WIN__ + char system_dir[FN_REFLEN]; + GetWindowsDirectory(system_dir,sizeof(system_dir)); + if (search_default_file(&args, &alloc, system_dir, conf_file, windows_ext, + &group)) + goto err; +#endif + for (dirs=default_directories ; *dirs; dirs++) + { + if (search_default_file(&args, &alloc, *dirs, conf_file, default_ext, + &group)) + goto err; + } + } + if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+ + (args.elements + *argc +1) *sizeof(char*)))) + goto err; + res= (char**) (ptr+sizeof(alloc)); + + /* copy name + found arguments + command line arguments to new array */ + res[0]=argv[0][0]; + memcpy((gptr) (res+1), args.buffer, args.elements*sizeof(char*)); + if (extra_default_file) + { + --*argc; /* Skipp --defaults-file */ + ++*argv; + } + + /* Check if we wan't to see the new argument list */ + if (*argc >= 2 && !strcmp(argv[0][1],"--print-defaults")) + { + found_print_defaults=1; + --*argc; ++*argv; /* skipp argument */ + } + + memcpy((gptr) (res+1+args.elements), (char*) ((*argv)+1), + (*argc-1)*sizeof(char*)); + res[args.elements+ *argc]=0; /* last null */ + + (*argc)+=args.elements; + *argv= (char**) res; + *(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */ + delete_dynamic(&args); + if (found_print_defaults) + { + int i; + printf("%s would have been started with the following arguments:\n", + **argv); + for (i=1 ; i < *argc ; i++) + printf("%s ", (*argv)[i]); + puts(""); + exit(1); + } + DBUG_VOID_RETURN; + + err: + fprintf(stderr,"Program aborted\n"); + exit(1); +} + + +void free_defaults(char **argv) +{ + MEM_ROOT ptr; + memcpy_fixed((char*) &ptr,(char *) argv - sizeof(ptr), sizeof(ptr)); + free_root(&ptr); +} + + +static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc, + const char *dir, const char *config_file, + const char *ext, TYPELIB *group) +{ + char name[FN_REFLEN+10],buff[257],*ptr,*end,*value,*tmp; + FILE *fp; + uint line=0; + my_bool read_values=0,found_group=0; + + if ((dir ? strlen(dir) : 0 )+strlen(config_file) >= FN_REFLEN-3) + return 0; /* Ignore wrong paths */ + if (dir) + { + strmov(name,dir); + convert_dirname(name); + if (dir[0] == FN_HOMELIB) /* Add . to filenames in home */ + strcat(name,"."); + strxmov(strend(name),config_file,ext,NullS); + } + else + { + strmov(name,config_file); + } + if (!(fp = my_fopen(fn_format(name,name,"","",4),O_RDONLY,MYF(0)))) + return 0; /* Ignore wrong files */ + + while (fgets(buff,sizeof(buff)-1,fp)) + { + line++; + /* Ignore comment and empty lines */ + for (ptr=buff ; isspace(*ptr) ; ptr++ ) ; + if (*ptr == '#' || *ptr == ';' || !*ptr) + continue; + if (*ptr == '[') /* Group name */ + { + found_group=1; + if (!(end=(char *) strchr(++ptr,']'))) + { + fprintf(stderr, + "error: Wrong group definition in config file: %s at line %d\n", + name,line); + goto err; + } + for ( ; isspace(end[-1]) ; end--) ; /* Remove end space */ + end[0]=0; + read_values=find_type(ptr,group,3) > 0; + continue; + } + if (!found_group) + { + fprintf(stderr, + "error: Found option without preceding group in config file: %s at line: %d\n", + name,line); + goto err; + } + if (!read_values) + continue; + if (!(end=value=strchr(ptr,'='))) + end=strend(ptr); /* Option without argument */ + for ( ; isspace(end[-1]) ; end--) ; + if (!value) + { + if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3))) + goto err; + strmake(strmov(tmp,"--"),ptr,(uint) (end-ptr)); + if (insert_dynamic(args,(gptr) &tmp)) + goto err; + } + else + { + /* Remove pre- and end space */ + char *value_end; + for (value++ ; isspace(*value); value++) ; + value_end=strend(value); + for ( ; isspace(value_end[-1]) ; value_end--) ; + if (value_end < value) /* Empty string */ + value_end=value; + if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3 + + (uint) (value_end-value)+1))) + goto err; + if (insert_dynamic(args,(gptr) &tmp)) + goto err; + ptr=strnmov(strmov(tmp,"--"),ptr,(uint) (end-ptr)); + *ptr++= '='; + for ( ; value != value_end; value++) + { + if (*value == '\\' && value != value_end-1) + { + switch(*++value) { + case 'n': + *ptr++='\n'; + break; + case 't': + *ptr++= '\t'; + break; + case 'r': + *ptr++ = '\r'; + break; + case 'b': + *ptr++ = '\b'; + break; + case 's': + *ptr++= ' '; /* space */ + break; + case '\\': + *ptr++= '\\'; + break; + default: /* Unknown; Keep '\' */ + *ptr++= '\\'; + *ptr++= *value; + break; + } + } + else + *ptr++= *value; + } + *ptr=0; + } + } + my_fclose(fp,MYF(0)); + return(0); + + err: + my_fclose(fp,MYF(0)); + return 1; +} + + +void print_defaults(const char *conf_file, const char **groups) +{ +#ifdef __WIN__ + bool have_ext=fn_ext(conf_file)[0] != 0; +#endif + char name[FN_REFLEN]; + const char **dirs; + puts("\nDefault options are read from the following files in the given order:"); + + if (dirname_length(conf_file)) + fputs(conf_file,stdout); + else + { +#ifdef __WIN__ + GetWindowsDirectory(name,sizeof(name)); + printf("%s\\%s%s ",name,conf_file,have_ext ? "" : windows_ext); +#endif + for (dirs=default_directories ; *dirs; dirs++) + { + strmov(name,*dirs); + convert_dirname(name); + if (name[0] == FN_HOMELIB) /* Add . to filenames in home */ + strcat(name,"."); + strxmov(strend(name),conf_file,default_ext," ",NullS); + fputs(name,stdout); + } + puts(""); + } + fputs("The following groups are read:",stdout); + for ( ; *groups ; groups++) + { + fputc(' ',stdout); + fputs(*groups,stdout); + } + puts("\nThe following options may be given as the first argument:\n\ +--print-defaults Print the program argument list and exit\n\ +--no-defaults Don't read default options from any options file\n\ +--defaults-file=# Only read default options from the given file #"); +} + diff --git a/mysys/errors.c b/mysys/errors.c new file mode 100644 index 00000000000..03b0b9d7f46 --- /dev/null +++ b/mysys/errors.c @@ -0,0 +1,84 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include "mysys_err.h" + +#ifndef SHARED_LIBRARY + +const char * NEAR globerrs[GLOBERRS]= +{ + "File '%s' not found (Errcode: %d)", + "Can't create/write to file '%s' (Errcode: %d)", + "Error reading file '%s' (Errcode: %d)", + "Error writing file '%s' (Errcode: %d)", + "Error on close of '%s' (Errcode: %d)", + "Out of memory (Needed %u bytes)", + "Error on delete of '%s' (Errcode: %d)", + "Error on rename of '%s' to '%s' (Errcode: %d)", + "", + "Unexpected eof found when reading file '%s' (Errcode: %d)", + "Can't lock file (Errcode: %d)", + "Can't unlock file (Errcode: %d)", + "Can't read dir of '%s' (Errcode: %d)", + "Can't get stat of '%s' (Errcode: %d)", + "Can't change size of file (Errcode: %d)", + "Can't open stream from handle (Errcode: %d)", + "Can't get working dirctory (Errcode: %d)", + "Can't change dir to '%s' (Errcode: %d)", + "Warning: '%s' had %d links", + "%d files and %d streams is left open\n", + "Disk is full writing '%s'. Waiting for someone to free space...", + "Can't create directory '%s' (Errcode: %d)", + "Character set '%s' is not a compiled character set and is not specified in the '%s' file" +}; + +void init_glob_errs(void) +{ + errmsg[GLOB] = & globerrs[0]; +} /* init_glob_errs */ + +#else + +void init_glob_errs() +{ + errmsg[GLOB] = & globerrs[0]; + + EE(EE_FILENOTFOUND) = "File '%s' not found (Errcode: %d)"; + EE(EE_CANTCREATEFILE) = "Can't create/write to file '%s' (Errcode: %d)"; + EE(EE_READ) = "Error reading file '%s' (Errcode: %d)"; + EE(EE_WRITE) = "Error writing file '%s' (Errcode: %d)"; + EE(EE_BADCLOSE) = "Error on close of '%'s (Errcode: %d)"; + EE(EE_OUTOFMEMORY) = "Out of memory (Needed %u bytes)"; + EE(EE_DELETE) = "Error on delete of '%s' (Errcode: %d)"; + EE(EE_LINK) = "Error on rename of '%s' to '%s' (Errcode: %d)"; + EE(EE_EOFERR) = "Unexpected eof found when reading file '%s' (Errcode: %d)"; + EE(EE_CANTLOCK) = "Can't lock file (Errcode: %d)"; + EE(EE_CANTUNLOCK) = "Can't unlock file (Errcode: %d)"; + EE(EE_DIR) = "Can't read dir of '%s' (Errcode: %d)"; + EE(EE_STAT) = "Can't get stat of '%s' (Errcode: %d)"; + EE(EE_CANT_CHSIZE) = "Can't change size of file (Errcode: %d)"; + EE(EE_CANT_OPEN_STREAM)= "Can't open stream from handle (Errcode: %d)"; + EE(EE_GETWD) = "Can't get working dirctory (Errcode: %d)"; + EE(EE_SETWD) = "Can't change dir to '%s' (Errcode: %d)"; + EE(EE_LINK_WARNING) = "Warning: '%s' had %d links"; + EE(EE_OPEN_WARNING) = "%d files and %d streams is left open\n"; + EE(EE_DISK_FULL) = "Disk is full writing '%s'. Waiting for someone to free space..."; + EE(EE_CANT_MKDIR) ="Can't create directory '%s' (Errcode: %d)"; + EE(EE_UNKNOWN_CHARSET)= "Character set is not a compiled character set and is not specified in the %s file"; +} +#endif diff --git a/mysys/getopt.c b/mysys/getopt.c new file mode 100644 index 00000000000..88fdbff7811 --- /dev/null +++ b/mysys/getopt.c @@ -0,0 +1,744 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94 + Free Software Foundation, Inc. + +Changes by monty: +- Added include of string.h when nessessary. +- Removed two warnings from gcc. + +This file is part of the GNU C Library. Its master source is NOT part of +the C library, however. The master source lives in /gd/gnu/lib. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. + Ditto for AIX 3.2 and <stdlib.h>. */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#if (!defined (__STDC__) || !__STDC__) && !defined(MSDOS) +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include <global.h> /* Changes for mysys */ +#include <m_string.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include <stdlib.h> +#endif /* GNU C library. */ + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = NULL; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* XXX 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return EOF with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include <string.h> +#define my_index strchr +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +char *getenv (const char *); + +static char * +my_index (const char *str, int chr) +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +#if !defined (__STDC__) || !__STDC__ +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen (const char *); +#endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange (char **argv) +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +static const char * +_getopt_initialize (const char *optstring) +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind = 1; + + nextchar = NULL; + + posixly_correct = getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns `EOF'. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (int argc, char *const *argv, const char *optstring, const struct option *longopts, int *longind, int long_only) +{ + optarg = NULL; + + if (optind == 0) + optstring = _getopt_initialize (optstring); + + if (nextchar == NULL || *nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc + && (argv[optind][0] != '-' || argv[optind][1] == '\0')) + optind++; + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return EOF; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if ((argv[optind][0] != '-' || argv[optind][1] == '\0')) + { + if (ordering == REQUIRE_ORDER) + return EOF; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound=0; /* Keep gcc happy */ + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((size_t) (nameend - nextchar) == (size_t) strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, "%s: option `%s' is ambiguous\n", + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + "%s: option `--%s' doesn't allow an argument\n", + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[optind - 1][0], pfound->name); + } + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, "%s: option `%s' requires an argument\n", + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, "%s: unrecognized option `--%s'\n", + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, "%s: unrecognized option `%c%s'\n", + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { + if (posixly_correct) + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); + else + fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c); + } + optopt = c; + return '?'; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: option requires an argument -- %c\n", + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (int argc, char *const *argv, const char *optstring) +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == EOF) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/mysys/getopt1.c b/mysys/getopt1.c new file mode 100644 index 00000000000..6068a036e7b --- /dev/null +++ b/mysys/getopt1.c @@ -0,0 +1,170 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987, 88, 89, 90, 91, 92, 1993, 1994 + Free Software Foundation, Inc. + +This file is part of the GNU C Library. Its master source is NOT part of +the C library, however. The master source lives in /gd/gnu/lib. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <global.h> +#include "getopt.h" + +#if (!defined (__STDC__) || !__STDC__) && !defined(MSDOS) +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + +#ifndef __WIN__ +#include <stdlib.h> +#endif /* __WIN__ */ + +#ifndef NULL +#define NULL 0 +#endif + +int +getopt_long (int argc, char *const *argv, const char *options, const struct option *long_options, int *opt_index) +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only (int argc, char *const *argv, const char *options, const struct option *long_options, int *opt_index) +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +#include <stdio.h> + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = + { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == EOF) + break; + + switch (c) + { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case 'd': + printf ("option d with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/mysys/getvar.c b/mysys/getvar.c new file mode 100644 index 00000000000..1d452002490 --- /dev/null +++ b/mysys/getvar.c @@ -0,0 +1,105 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Allow use of the -O variable= option to set long variables */ + +#include "mysys_priv.h" +#include <m_string.h> +#include <m_ctype.h> + + /* set all changeable variables */ + +void set_all_changeable_vars(CHANGEABLE_VAR *vars) +{ + for ( ; vars->name ; vars++) + *vars->varptr= vars->def_value; +} + + +my_bool set_changeable_varval(const char* var, ulong val, + CHANGEABLE_VAR *vars) +{ + char buffer[256]; + sprintf( buffer, "%s=%lu", var, (unsigned long) val ); + return set_changeable_var( buffer, vars ); +} + + +my_bool set_changeable_var(my_string str,CHANGEABLE_VAR *vars) +{ + char endchar; + my_string end; + DBUG_ENTER("set_changeable_var"); + DBUG_PRINT("enter",("%s",str)); + + if (str) + { + if (!(end=strchr(str,'='))) + fprintf(stderr,"Can't find '=' in expression '%s' to option -O\n",str); + else + { + uint length=(uint) (end-str),found_count=0; + CHANGEABLE_VAR *var,*found; + const char *name; + long num; + + for (var=vars,found=0 ; (name=var->name) ; var++) + { + if (!my_casecmp(name,str,length)) + { + found=var; found_count++; + if (!name[length]) + { + found_count=1; + break; + } + } + } + if (found_count == 0) + { + fprintf(stderr,"No variable match for: -O '%s'\n",str); + DBUG_RETURN(1); + } + if (found_count > 1) + { + fprintf(stderr,"Variable prefix '%*s' is not unique\n",length,str); + DBUG_RETURN(1); + } + + num=(long) atol(end+1); endchar=strend(end+1)[-1]; + if (endchar == 'k' || endchar == 'K') + num*=1024; + else if (endchar == 'm' || endchar == 'M') + num*=1024L*1024L; + else if (!isdigit(endchar)) + { + fprintf(stderr,"Unknown prefix used for variable value '%s'\n",str); + DBUG_RETURN(1); + } + if (num < (long) found->min_value) + num=(long) found->min_value; + else if ((unsigned long) num > + (unsigned long) found->max_value) + num=(long) found->max_value; + *found->varptr=(long) ((ulong) (num-found->sub_size) / + (ulong) found->block_size); + (*found->varptr)*= (ulong) found->block_size; + DBUG_RETURN(0); + } + } + DBUG_RETURN(1); +} diff --git a/mysys/hash.c b/mysys/hash.c new file mode 100644 index 00000000000..a6181443a42 --- /dev/null +++ b/mysys/hash.c @@ -0,0 +1,586 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* The hash functions used for saveing keys */ +/* One of key_length or key_length_offset must be given */ +/* Key length of 0 isn't allowed */ + +#include "mysys_priv.h" +#include <m_string.h> +#include <m_ctype.h> +#include "hash.h" + +#define NO_RECORD ((uint) -1) +#define LOWFIND 1 +#define LOWUSED 2 +#define HIGHFIND 4 +#define HIGHUSED 8 + +static uint hash_mask(uint hashnr,uint buffmax,uint maxlength); +static void movelink(HASH_LINK *array,uint pos,uint next_link,uint newlink); +static uint calc_hashnr(const byte *key,uint length); +static uint calc_hashnr_caseup(const byte *key,uint length); +static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length); + + +my_bool hash_init(HASH *hash,uint size,uint key_offset,uint key_length, + hash_get_key get_key, + void (*free_element)(void*),uint flags) +{ + DBUG_ENTER("hash_init"); + DBUG_PRINT("enter",("hash: %lx size: %d",hash,size)); + + hash->records=0; + if (init_dynamic_array(&hash->array,sizeof(HASH_LINK),size,0)) + { + hash->free=0; /* Allow call to hash_free */ + DBUG_RETURN(TRUE); + } + hash->key_offset=key_offset; + hash->key_length=key_length; + hash->blength=1; + hash->current_record= NO_RECORD; /* For the future */ + hash->get_key=get_key; + hash->free=free_element; + hash->flags=flags; + if (flags & HASH_CASE_INSENSITIVE) + hash->calc_hashnr=calc_hashnr_caseup; + else + hash->calc_hashnr=calc_hashnr; + DBUG_RETURN(0); +} + + +void hash_free(HASH *hash) +{ + DBUG_ENTER("hash_free"); + if (hash->free) + { + uint i,records; + HASH_LINK *data=dynamic_element(&hash->array,0,HASH_LINK*); + for (i=0,records=hash->records ; i < records ; i++) + (*hash->free)(data[i].data); + hash->free=0; + } + delete_dynamic(&hash->array); + hash->records=0; + DBUG_VOID_RETURN; +} + + /* some helper functions */ + +static inline byte* +hash_key(HASH *hash,const byte *record,uint *length,my_bool first) +{ + if (hash->get_key) + return (*hash->get_key)(record,length,first); + *length=hash->key_length; + return (byte*) record+hash->key_offset; +} + + /* Calculate pos according to keys */ + +static uint hash_mask(uint hashnr,uint buffmax,uint maxlength) +{ + if ((hashnr & (buffmax-1)) < maxlength) return (hashnr & (buffmax-1)); + return (hashnr & ((buffmax >> 1) -1)); +} + +static uint hash_rec_mask(HASH *hash,HASH_LINK *pos,uint buffmax, + uint maxlength) +{ + uint length; + byte *key=hash_key(hash,pos->data,&length,0); + return hash_mask((*hash->calc_hashnr)(key,length),buffmax,maxlength); +} + + /* Calc hashvalue for a key */ + +static uint calc_hashnr(const byte *key,uint length) +{ + register uint nr=1, nr2=4; + while (length--) + { + nr^= (((nr & 63)+nr2)*((uint) (uchar) *key++))+ (nr << 8); + nr2+=3; + } + return((uint) nr); +} + + /* Calc hashvalue for a key, case indepenently */ + +static uint calc_hashnr_caseup(const byte *key,uint length) +{ + register uint nr=1, nr2=4; + while (length--) + { + nr^= (((nr & 63)+nr2)*((uint) (uchar) toupper(*key++)))+ (nr << 8); + nr2+=3; + } + return((uint) nr); +} + + +static inline uint rec_hashnr(HASH *hash,const byte *record) +{ + uint length; + byte *key=hash_key(hash,record,&length,0); + return (*hash->calc_hashnr)(key,length); +} + + + /* Search after a record based on a key */ + /* Sets info->current_ptr to found record */ + +gptr hash_search(HASH *hash,const byte *key,uint length) +{ + HASH_LINK *pos; + uint flag,idx; + DBUG_ENTER("hash_search"); + + flag=1; + if (hash->records) + { + idx=hash_mask((*hash->calc_hashnr)(key,length ? length : + hash->key_length), + hash->blength,hash->records); + do + { + pos= dynamic_element(&hash->array,idx,HASH_LINK*); + if (!hashcmp(hash,pos,key,length)) + { + DBUG_PRINT("exit",("found key at %d",idx)); + hash->current_record= idx; + DBUG_RETURN (pos->data); + } + if (flag) + { + flag=0; /* Reset flag */ + if (hash_rec_mask(hash,pos,hash->blength,hash->records) != idx) + break; /* Wrong link */ + } + } + while ((idx=pos->next) != NO_RECORD); + } + hash->current_record= NO_RECORD; + DBUG_RETURN(0); +} + + /* Get next record with identical key */ + /* Can only be called if previous calls was hash_search */ + +gptr hash_next(HASH *hash,const byte *key,uint length) +{ + HASH_LINK *pos; + uint idx; + + if (hash->current_record != NO_RECORD) + { + HASH_LINK *data=dynamic_element(&hash->array,0,HASH_LINK*); + for (idx=data[hash->current_record].next; idx != NO_RECORD ; idx=pos->next) + { + pos=data+idx; + if (!hashcmp(hash,pos,key,length)) + { + hash->current_record= idx; + return pos->data; + } + } + hash->current_record=NO_RECORD; + } + return 0; +} + + + /* Change link from pos to new_link */ + +static void movelink(HASH_LINK *array,uint find,uint next_link,uint newlink) +{ + HASH_LINK *old_link; + do + { + old_link=array+next_link; + } + while ((next_link=old_link->next) != find); + old_link->next= newlink; + return; +} + + /* Compare a key in a record to a whole key. Return 0 if identical */ + +static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length) +{ + uint rec_keylength; + byte *rec_key=hash_key(hash,pos->data,&rec_keylength,1); + return (length && length != rec_keylength) || + (hash->flags & HASH_CASE_INSENSITIVE ? + my_casecmp(rec_key,key,rec_keylength) : + memcmp(rec_key,key,rec_keylength)); +} + + + /* Write a hash-key to the hash-index */ + +my_bool hash_insert(HASH *info,const byte *record) +{ + int flag; + uint halfbuff,hash_nr,first_index,idx; + byte *ptr_to_rec,*ptr_to_rec2; + HASH_LINK *data,*empty,*gpos,*gpos2,*pos; + + LINT_INIT(gpos); LINT_INIT(gpos2); + LINT_INIT(ptr_to_rec); LINT_INIT(ptr_to_rec2); + + flag=0; + if (!(empty=(HASH_LINK*) alloc_dynamic(&info->array))) + return(TRUE); /* No more memory */ + + info->current_record= NO_RECORD; + data=dynamic_element(&info->array,0,HASH_LINK*); + halfbuff= info->blength >> 1; + + idx=first_index=info->records-halfbuff; + if (idx != info->records) /* If some records */ + { + do + { + pos=data+idx; + hash_nr=rec_hashnr(info,pos->data); + if (flag == 0) /* First loop; Check if ok */ + if (hash_mask(hash_nr,info->blength,info->records) != first_index) + break; + if (!(hash_nr & halfbuff)) + { /* Key will not move */ + if (!(flag & LOWFIND)) + { + if (flag & HIGHFIND) + { + flag=LOWFIND | HIGHFIND; + /* key shall be moved to the current empty position */ + gpos=empty; + ptr_to_rec=pos->data; + empty=pos; /* This place is now free */ + } + else + { + flag=LOWFIND | LOWUSED; /* key isn't changed */ + gpos=pos; + ptr_to_rec=pos->data; + } + } + else + { + if (!(flag & LOWUSED)) + { + /* Change link of previous LOW-key */ + gpos->data=ptr_to_rec; + gpos->next=(uint) (pos-data); + flag= (flag & HIGHFIND) | (LOWFIND | LOWUSED); + } + gpos=pos; + ptr_to_rec=pos->data; + } + } + else + { /* key will be moved */ + if (!(flag & HIGHFIND)) + { + flag= (flag & LOWFIND) | HIGHFIND; + /* key shall be moved to the last (empty) position */ + gpos2 = empty; empty=pos; + ptr_to_rec2=pos->data; + } + else + { + if (!(flag & HIGHUSED)) + { + /* Change link of previous hash-key and save */ + gpos2->data=ptr_to_rec2; + gpos2->next=(uint) (pos-data); + flag= (flag & LOWFIND) | (HIGHFIND | HIGHUSED); + } + gpos2=pos; + ptr_to_rec2=pos->data; + } + } + } + while ((idx=pos->next) != NO_RECORD); + + if ((flag & (LOWFIND | LOWUSED)) == LOWFIND) + { + gpos->data=ptr_to_rec; + gpos->next=NO_RECORD; + } + if ((flag & (HIGHFIND | HIGHUSED)) == HIGHFIND) + { + gpos2->data=ptr_to_rec2; + gpos2->next=NO_RECORD; + } + } + /* Check if we are at the empty position */ + + idx=hash_mask(rec_hashnr(info,record),info->blength,info->records+1); + pos=data+idx; + if (pos == empty) + { + pos->data=(byte*) record; + pos->next=NO_RECORD; + } + else + { + /* Check if more records in same hash-nr family */ + empty[0]=pos[0]; + gpos=data+hash_rec_mask(info,pos,info->blength,info->records+1); + if (pos == gpos) + { + pos->data=(byte*) record; + pos->next=(uint) (empty - data); + } + else + { + pos->data=(byte*) record; + pos->next=NO_RECORD; + movelink(data,(uint) (pos-data),(uint) (gpos-data),(uint) (empty-data)); + } + } + if (++info->records == info->blength) + info->blength+= info->blength; + return(0); +} + + +/****************************************************************************** +** Remove one record from hash-table. The record with the same record +** ptr is removed. +** if there is a free-function it's called for record if found +******************************************************************************/ + +my_bool hash_delete(HASH *hash,byte *record) +{ + uint blength,pos2,pos_hashnr,lastpos_hashnr,idx,empty_index; + HASH_LINK *data,*lastpos,*gpos,*pos,*pos3,*empty; + DBUG_ENTER("hash_delete"); + + blength=hash->blength; + data=dynamic_element(&hash->array,0,HASH_LINK*); + + /* Search after record with key */ + pos=data+ hash_mask(rec_hashnr(hash,record),blength,hash->records); + gpos = 0; + + while (pos->data != record) + { + gpos=pos; + if (pos->next == NO_RECORD) + DBUG_RETURN(1); /* Key not found */ + pos=data+pos->next; + } + + if ( --(hash->records) < hash->blength >> 1) hash->blength>>=1; + hash->current_record= NO_RECORD; + lastpos=data+hash->records; + + /* Remove link to record */ + empty=pos; empty_index=(uint) (empty-data); + if (gpos) + gpos->next=pos->next; /* unlink current ptr */ + else if (pos->next != NO_RECORD) + { + empty=data+(empty_index=pos->next); + pos->data=empty->data; + pos->next=empty->next; + } + + if (empty == lastpos) /* last key at wrong pos or no next link */ + goto exit; + + /* Move the last key (lastpos) */ + lastpos_hashnr=rec_hashnr(hash,lastpos->data); + /* pos is where lastpos should be */ + pos=data+hash_mask(lastpos_hashnr,hash->blength,hash->records); + if (pos == empty) /* Move to empty position. */ + { + empty[0]=lastpos[0]; + goto exit; + } + pos_hashnr=rec_hashnr(hash,pos->data); + /* pos3 is where the pos should be */ + pos3= data+hash_mask(pos_hashnr,hash->blength,hash->records); + if (pos != pos3) + { /* pos is on wrong posit */ + empty[0]=pos[0]; /* Save it here */ + pos[0]=lastpos[0]; /* This should be here */ + movelink(data,(uint) (pos-data),(uint) (pos3-data),empty_index); + goto exit; + } + pos2= hash_mask(lastpos_hashnr,blength,hash->records+1); + if (pos2 == hash_mask(pos_hashnr,blength,hash->records+1)) + { /* Identical key-positions */ + if (pos2 != hash->records) + { + empty[0]=lastpos[0]; + movelink(data,(uint) (lastpos-data),(uint) (pos-data),empty_index); + goto exit; + } + idx= (uint) (pos-data); /* Link pos->next after lastpos */ + } + else idx= NO_RECORD; /* Different positions merge */ + + empty[0]=lastpos[0]; + movelink(data,idx,empty_index,pos->next); + pos->next=empty_index; + +exit: + VOID(pop_dynamic(&hash->array)); + if (hash->free) + (*hash->free)((byte*) record); + DBUG_RETURN(0); +} + + /* + Update keys when record has changed. + This is much more efficent than using a delete & insert. + */ + +my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length) +{ + uint idx,new_index,new_pos_index,blength,records,empty; + HASH_LINK org_link,*data,*previous,*pos; + DBUG_ENTER("hash_update"); + + data=dynamic_element(&hash->array,0,HASH_LINK*); + blength=hash->blength; records=hash->records; + + /* Search after record with key */ + + idx=hash_mask((*hash->calc_hashnr)(old_key,(old_key_length ? + old_key_length : + hash->key_length)), + blength,records); + new_index=hash_mask(rec_hashnr(hash,record),blength,records); + if (idx == new_index) + DBUG_RETURN(0); /* Nothing to do (No record check) */ + previous=0; + for (;;) + { + + if ((pos= data+idx)->data == record) + break; + previous=pos; + if ((idx=pos->next) == NO_RECORD) + DBUG_RETURN(1); /* Not found in links */ + } + hash->current_record= NO_RECORD; + org_link= *pos; + empty=idx; + + /* Relink record from current chain */ + + if (!previous) + { + if (pos->next != NO_RECORD) + { + empty=pos->next; + *pos= data[pos->next]; + } + } + else + previous->next=pos->next; /* unlink pos */ + + /* Move data to correct position */ + pos=data+new_index; + new_pos_index=hash_rec_mask(hash,pos,blength,records); + if (new_index != new_pos_index) + { /* Other record in wrong position */ + data[empty] = *pos; + movelink(data,new_index,new_pos_index,empty); + org_link.next=NO_RECORD; + data[new_index]= org_link; + } + else + { /* Link in chain at right position */ + org_link.next=data[new_index].next; + data[empty]=org_link; + data[new_index].next=empty; + } + DBUG_RETURN(0); +} + + +byte *hash_element(HASH *hash,uint idx) +{ + if (idx < hash->records) + return dynamic_element(&hash->array,idx,HASH_LINK*)->data; + return 0; +} + + +#ifndef DBUG_OFF + +my_bool hash_check(HASH *hash) +{ + int error; + uint i,rec_link,found,max_links,seek,links,idx; + uint records,blength; + HASH_LINK *data,*hash_info; + + records=hash->records; blength=hash->blength; + data=dynamic_element(&hash->array,0,HASH_LINK*); + error=0; + + for (i=found=max_links=seek=0 ; i < records ; i++) + { + if (hash_rec_mask(hash,data+i,blength,records) == i) + { + found++; seek++; links=1; + for (idx=data[i].next ; + idx != NO_RECORD && found < records + 1; + idx=hash_info->next) + { + if (idx >= records) + { + DBUG_PRINT("error", + ("Found pointer outside array to %d from link starting at %d", + idx,i)); + error=1; + } + hash_info=data+idx; + seek+= ++links; + if ((rec_link=hash_rec_mask(hash,hash_info,blength,records)) != i) + { + DBUG_PRINT("error", + ("Record in wrong link at %d: Start %d Record: %lx Record-link %d", idx,i,hash_info->data,rec_link)); + error=1; + } + else + found++; + } + if (links > max_links) max_links=links; + } + } + if (found != records) + { + DBUG_PRINT("error",("Found %ld of %ld records")); + error=1; + } + if (records) + DBUG_PRINT("info", + ("records: %ld seeks: %d max links: %d hitrate: %.2f", + records,seek,max_links,(float) seek / (float) records)); + return error; +} +#endif diff --git a/mysys/list.c b/mysys/list.c new file mode 100644 index 00000000000..0a6d900d6b9 --- /dev/null +++ b/mysys/list.c @@ -0,0 +1,116 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* + Code for handling dubble-linked lists in C +*/ + +#include "mysys_priv.h" +#include <my_list.h> + + + + /* Add a element to start of list */ + +LIST *list_add(LIST *root, LIST *element) +{ + DBUG_ENTER("list_add"); + DBUG_PRINT("enter",("root: %lx element: %lx", root, element)); + if (root) + { + if (root->prev) /* If add in mid of list */ + root->prev->next= element; + element->prev=root->prev; + root->prev=element; + } + else + element->prev=0; + element->next=root; + DBUG_RETURN(element); /* New root */ +} + + +LIST *list_delete(LIST *root, LIST *element) +{ + if (element->prev) + element->prev->next=element->next; + else + root=element->next; + if (element->next) + element->next->prev=element->prev; + return root; +} + + +void list_free(LIST *root, pbool free_data) +{ + LIST *next; + while (root) + { + next=root->next; + if (free_data) + my_free((gptr) root->data,MYF(0)); + my_free((gptr) root,MYF(0)); + root=next; + } +} + + +LIST *list_cons(void *data, LIST *list) +{ + LIST *new=(LIST*) my_malloc(sizeof(LIST),MYF(MY_FAE)); + if (!new) + return 0; + new->data=data; + return list_add(list,new); +} + + +LIST *list_reverse(LIST *root) +{ + LIST *last; + + last=root; + while (root) + { + last=root; + root=root->next; + last->next=last->prev; + last->prev=root; + } + return last; +} + +uint list_length(LIST *list) +{ + uint count; + for (count=0 ; list ; list=list->next, count++) ; + return count; +} + + +int list_walk(LIST *list, list_walk_action action, gptr argument) +{ + int error=0; + while (list) + { + if ((error = (*action)(list->data,argument))) + return error; + list=rest(list); + } + return 0; +} diff --git a/mysys/make-ccc b/mysys/make-ccc new file mode 100755 index 00000000000..9c54185682a --- /dev/null +++ b/mysys/make-ccc @@ -0,0 +1,4 @@ +rm -f .deps/* raid.o mf_iocache.o libmysys.a +ccc -DDEFAULT_BASEDIR="\"/usr/local/mysql\"" -DDATADIR="\"/usr/local/mysql/var\"" -DHAVE_CONFIG_H -I./../include -I../include -I.. -DDBUG_OFF -fast -O3 -fomit-frame-pointer -c array.c checksum.c default.c errors.c getopt.c getopt1.c getvar.c hash.c list.c mf_brkhant.c mf_cache.c mf_casecnv.c mf_dirname.c mf_fn_ext.c mf_format.c mf_getdate.c mf_keycache.c mf_loadpath.c mf_pack.c mf_pack2.c mf_path.c mf_qsort.c mf_qsort2.c mf_radix.c mf_reccache.c mf_same.c mf_sort.c mf_soundex.c mf_stripp.c mf_unixpath.c mf_wcomp.c mf_wfile.c mulalloc.c my_alarm.c my_alloc.c my_append.c my_chsize.c my_clock.c my_compress.c my_copy.c my_create.c my_delete.c my_div.c my_error.c my_fopen.c my_fstream.c my_getwd.c my_init.c my_lib.c my_lockmem.c my_lread.c my_lwrite.c my_malloc.c my_messnc.c my_mkdir.c my_net.c my_once.c my_open.c my_pread.c my_pthread.c my_quick.c my_read.c my_realloc.c my_redel.c my_rename.c my_seek.c my_static.c my_tempnam.c my_thr_init.c my_write.c ptr_cmp.c queues.c safemalloc.c string.c thr_alarm.c thr_lock.c thr_mutex.c thr_rwlock.c tree.c typelib.c +make raid.o mf_iocache.o my_lock.o +ar -cr libmysys.a array.o raid.o mf_iocache.o my_lock.o diff --git a/mysys/make-conf.c b/mysys/make-conf.c new file mode 100644 index 00000000000..9db766574e2 --- /dev/null +++ b/mysys/make-conf.c @@ -0,0 +1,73 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* make-conf.c + * make a charset .conf file out of a ctype-charset.c file. + */ + +#ifndef CHARSET +#error You must define the charset, e.g.: -DCHARSET=latin1 +#endif + +/* some pre-processor tricks to get us going */ +#define _STRINGIZE_HELPER(x) #x +#define STRINGIZE(x) _STRINGIZE_HELPER(x) + +#define _JOIN_WORDS_HELPER(a, b) a ## b +#define JOIN_WORDS(a, b) _JOIN_WORDS_HELPER(a, b) + +#define CH_SRC ctype- ## CHARSET ## .c +#define CH_INCLUDE STRINGIZE(CH_SRC) + +/* aaaah, that's better */ +#include <my_global.h> +#include CH_INCLUDE + +#include <stdio.h> +#include <stdlib.h> + +#define ROW_LEN 16 + +void print_array(const char *name, const uchar *array, uint size); + +int main(void) +{ + printf("# Configuration file for the " + STRINGIZE(CHARSET) + " character set.\n"); + + print_array("ctype", JOIN_WORDS(ctype_, CHARSET), 257); + print_array("to_lower", JOIN_WORDS(to_lower_, CHARSET), 256); + print_array("to_upper", JOIN_WORDS(to_upper_, CHARSET), 256); + print_array("sort_order", JOIN_WORDS(sort_order_, CHARSET), 256); + + exit(EXIT_SUCCESS); +} + +void print_array(const char *name, const uchar *array, uint size) +{ + uint i; + + printf("\n# The %s array must have %d elements.\n", name, size); + + for (i = 0; i < size; ++i) { + printf(" %02X", array[i]); + + if ((i+1) % ROW_LEN == size % ROW_LEN) + printf("\n"); + } +} diff --git a/mysys/mf_brkhant.c b/mysys/mf_brkhant.c new file mode 100644 index 00000000000..4e4bc2410f9 --- /dev/null +++ b/mysys/mf_brkhant.c @@ -0,0 +1,76 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Dont let the user break when you are doing something important */ +/* Remembers if it got 'SIGINT' and executes it on allow_break */ +/* A static buffer is used; don't call dont_break() twice in a row */ + +#include "mysys_priv.h" +#include "my_static.h" + + /* Set variable that we can't break */ + +void dont_break(void) +{ +#if !defined(THREAD) + my_dont_interrupt=1; +#endif + return; +} /* dont_break */ + +void allow_break(void) +{ +#if !defined(THREAD) + { + reg1 int index; + + my_dont_interrupt=0; + if (_my_signals) + { + if (_my_signals > MAX_SIGNALS) + _my_signals=MAX_SIGNALS; + for (index=0 ; index < _my_signals ; index++) + { + if (_my_sig_remember[index].func) /* Safequard */ + { + (*_my_sig_remember[index].func)(_my_sig_remember[index].number); + _my_sig_remember[index].func=0; + } + } + _my_signals=0; + } + } +#endif +} /* dont_break */ + + /* Set old status */ + +#if !defined(THREAD) +void my_remember_signal(int signal_number, sig_handler (*func) (int)) +{ +#ifndef __WIN__ + reg1 int index; + + index=_my_signals++; /* Nobody can break a ++ ? */ + if (index < MAX_SIGNALS) + { + _my_sig_remember[index].number=signal_number; + _my_sig_remember[index].func=func; + } +#endif /* __WIN__ */ +} /* my_remember_signal */ +#endif /* THREAD */ diff --git a/mysys/mf_cache.c b/mysys/mf_cache.c new file mode 100644 index 00000000000..c40cfa386d3 --- /dev/null +++ b/mysys/mf_cache.c @@ -0,0 +1,83 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Open a temporary file and cache it with io_cache. Delete it on close */ + +#include "mysys_priv.h" + + /* + ** Open a cached tempfile by IO_CACHE + ** Should be used when no seeks are done (only reinit_io_buff) + ** Return 0 if cache is inited ok + ** The actual file is created when the IO_CACHE buffer gets filled + */ + +my_bool open_cached_file(IO_CACHE *cache, const char* dir, const char *prefix, + uint cache_size, myf cache_myflags) +{ + DBUG_ENTER("open_cached_file"); + + cache->buffer=0; /* Mark that not open */ + if (!(cache->file_name=my_tempnam(dir,prefix,MYF(MY_WME)))) + DBUG_RETURN(1); + if (!init_io_cache(cache,-1,cache_size,WRITE_CACHE,0L,0, + MYF(cache_myflags | MY_NABP))) + { + DBUG_RETURN(0); + } + (*free)(cache->file_name); /* my_tempnam uses malloc() */ + cache->file_name=0; + DBUG_RETURN(0); +} + + +my_bool real_open_cached_file(IO_CACHE *cache) +{ + DBUG_ENTER("real_open_cached_file"); + if ((cache->file=my_create(cache->file_name,0, + (int) (O_RDWR | O_BINARY | O_TRUNC | O_TEMPORARY | + O_SHORT_LIVED), + MYF(MY_WME))) >= 0) + { +#if O_TEMPORARY == 0 && !defined(CANT_DELETE_OPEN_FILES) + VOID(my_delete(cache->file_name,MYF(MY_WME | ME_NOINPUT))); +#endif + DBUG_RETURN(0); + } + DBUG_RETURN(1); +} + + +void close_cached_file(IO_CACHE *cache) +{ + DBUG_ENTER("close_cached_file"); + + if (my_b_inited(cache)) + { + VOID(end_io_cache(cache)); + if (cache->file >= 0) + { + VOID(my_close(cache->file,MYF(MY_WME))); +#ifdef CANT_DELETE_OPEN_FILES + VOID(my_delete(cache->file_name,MYF(MY_WME | ME_NOINPUT))); +#endif + } + if (cache->file_name) + (*free)(cache->file_name); /* my_tempnam uses malloc() */ + } + DBUG_VOID_RETURN; +} diff --git a/mysys/mf_casecnv.c b/mysys/mf_casecnv.c new file mode 100644 index 00000000000..705e1361937 --- /dev/null +++ b/mysys/mf_casecnv.c @@ -0,0 +1,252 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* + Functions to convert to lover_case and to upper_case in scandinavia. + + case_sort converts a character string to a representaion that can + be compared by strcmp to find with is alfabetical bigger. + (lower- and uppercase letters is compared as the same) +*/ + +#include "mysys_priv.h" +#include <m_ctype.h> + + /* string to uppercase */ + +void caseup_str(my_string str) +{ +#ifdef USE_MB + register uint32 l; + register char *end=str+strlen(str); + if (use_mb(default_charset_info)) + while (*str) + { + if ((l=my_ismbchar(default_charset_info, str,end))) str+=l; + else *str=toupper(*str),++str; + } + else +#endif + while ((*str = toupper(*str)) != 0) + str++; +} /* caseup_str */ + + /* string to lowercase */ + +void casedn_str(my_string str) +{ +#ifdef USE_MB + register uint32 l; + register char *end=str+strlen(str); + if (use_mb(default_charset_info)) + while (*str) + { + if ((l=my_ismbchar(default_charset_info, str,end))) str+=l; + else *str=tolower(*str),++str; + } + else +#endif + while ((*str= tolower(*str)) != 0) + str++; +} /* casedn_str */ + + + /* to uppercase */ + +void caseup(my_string str, uint length) +{ +#ifdef USE_MB + register uint32 l; + register char *end=str+length; + if (use_mb(default_charset_info)) + while (str<end) + { + if ((l=my_ismbchar(default_charset_info, str,end))) str+=l; + else *str=toupper(*str),++str; + } + else +#endif + for ( ; length>0 ; length--, str++) + *str= toupper(*str); +} /* caseup */ + + /* to lowercase */ + +void casedn(my_string str, uint length) +{ +#ifdef USE_MB + register uint32 l; + register char *end=str+length; + if (use_mb(default_charset_info)) + while (str<end) + { + if ((l=my_ismbchar(default_charset_info, str,end))) str+=l; + else *str=tolower(*str),++str; + } + else +#endif + for ( ; length>0 ; length--, str++) + *str= tolower(*str); +} /* casedn */ + + /* to sort-string that can be compared to get text in order */ + +void case_sort(my_string str, uint length) +{ + for ( ; length>0 ; length--, str++) + *str= (char) my_sort_order[(uchar) *str]; +} /* case_sort */ + + /* find string in another with no case_sensivity */ + +/* ToDo: This function should be modified to support multibyte charset. + However it is not used untill 3.23.5. + Wei He (hewei@mail.ied.ac.cn) +*/ + +my_string my_strcasestr(const char *str, const char *search) +{ + uchar *i,*j,*pos; + + pos=(uchar*) str; +skipp: + while (*pos != '\0') + { + if (toupper((uchar) *pos++) == toupper((uchar) *search)) + { + i=(uchar*) pos; j=(uchar*) search+1; + while (*j) + if (toupper(*i++) != toupper(*j++)) goto skipp; + return ((char*) pos-1); + } + } + return ((my_string) 0); +} /* strcstr */ + + + /* compare strings without regarding to case */ + +int my_strcasecmp(const char *s, const char *t) +{ +#ifdef USE_MB + register uint32 l; + register const char *end=s+strlen(s); + if (use_mb(default_charset_info)) + { + while (s<end) + { + if ((l=my_ismbchar(default_charset_info, s,end))) + { + while (l--) + if (*s++ != *t++) return 1; + } + else if (my_ismbhead(default_charset_info, *t)) return 1; + else if (toupper((uchar) *s++) != toupper((uchar) *t++)) return 1; + } + return *t; + } + else +#endif + { + while (toupper((uchar) *s) == toupper((uchar) *t++)) + if (!*s++) return 0; + return ((int) toupper((uchar) s[0]) - (int) toupper((uchar) t[-1])); + } +} + + +int my_casecmp(const char *s, const char *t, uint len) +{ +#ifdef USE_MB + register uint32 l; + register const char *end=s+len; + if (use_mb(default_charset_info)) + { + while (s<end) + { + if ((l=my_ismbchar(default_charset_info, s,end))) + { + while (l--) + if (*s++ != *t++) return 1; + } + else if (my_ismbhead(default_charset_info, *t)) return 1; + else if (toupper((uchar) *s++) != toupper((uchar) *t++)) return 1; + } + return 0; + } + else +#endif + { + while (len-- != 0 && toupper(*s++) == toupper(*t++)) ; + return (int) len+1; + } +} + + +int my_strsortcmp(const char *s, const char *t) +{ +#ifdef USE_STRCOLL + if (use_strcoll(default_charset_info)) + return my_strcoll(default_charset_info, (uchar *)s, (uchar *)t); + else +#endif + { + while (my_sort_order[(uchar) *s] == my_sort_order[(uchar) *t++]) + if (!*s++) return 0; + return ((int) my_sort_order[(uchar) s[0]] - + (int) my_sort_order[(uchar) t[-1]]); + } +} + +int my_sortcmp(const char *s, const char *t, uint len) +{ +#ifdef USE_STRCOLL + if (use_strcoll(default_charset_info)) + return my_strnncoll(default_charset_info, + (uchar *)s, len, (uchar *)t, len); + else +#endif + { + while (len--) + { + if (my_sort_order[(uchar) *s++] != my_sort_order[(uchar) *t++]) + return ((int) my_sort_order[(uchar) s[-1]] - + (int) my_sort_order[(uchar) t[-1]]); + } + return 0; + } +} + +int my_sortncmp(const char *s, uint s_len, const char *t, uint t_len) +{ +#ifdef USE_STRCOLL + if (use_strcoll(default_charset_info)) + return my_strnncoll(default_charset_info, + (uchar *)s, s_len, (uchar *)t, t_len); + else +#endif + { + uint len= min(s_len,t_len); + while (len--) + { + if (my_sort_order[(uchar) *s++] != my_sort_order[(uchar) *t++]) + return ((int) my_sort_order[(uchar) s[-1]] - + (int) my_sort_order[(uchar) t[-1]]); + } + return (int) (s_len - t_len); + } +} diff --git a/mysys/mf_dirname.c b/mysys/mf_dirname.c new file mode 100644 index 00000000000..1bd6d256cfe --- /dev/null +++ b/mysys/mf_dirname.c @@ -0,0 +1,106 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include <m_string.h> + + /* Functions definied in this file */ + +uint dirname_length(const char *name) +{ + register my_string pos,gpos; +#ifdef FN_DEVCHAR + if ((pos=strrchr(name,FN_DEVCHAR)) == 0) +#endif + pos=(char*) name-1; + + gpos= pos++; + for ( ; *pos ; pos++) /* Find last FN_LIBCHAR */ + if (*pos == FN_LIBCHAR || *pos == '/' +#ifdef FN_C_AFTER_DIR + || *pos == FN_C_AFTER_DIR || *pos == FN_C_AFTER_DIR_2 +#endif + ) + gpos=pos; + return ((uint) (uint) (gpos+1-(char*) name)); +} + + + /* Gives directory part of filename. Directory ends with '/' */ + /* Returns length of directory part */ + +uint dirname_part(my_string to, const char *name) +{ + uint length; + DBUG_ENTER("dirname_part"); + DBUG_PRINT("enter",("'%s'",name)); + + length=dirname_length(name); + (void) strmake(to,(char*) name,min(length,FN_REFLEN-2)); + convert_dirname(to); /* Convert chars */ + DBUG_RETURN(length); +} /* dirname */ + + + /* convert dirname to use under this system */ + /* If MSDOS converts '/' to '\' */ + /* If VMS converts '<' to '[' and '>' to ']' */ + /* Adds a '/' to end if there isn't one and the last isn't a dev_char */ + /* ARGSUSED */ + +#ifndef FN_DEVCHAR +#define FN_DEVCHAR '\0' /* For easier code */ +#endif + +void convert_dirname(my_string to) +{ +#ifdef FN_UPPER_CASE + caseup_str(to); +#endif +#ifdef FN_LOWER_CASE + casedn_str(to); +#endif +#if FN_LIBCHAR != '/' + { + reg1 my_string pos; + pos=to-1; /* Change from '/' */ + while ((pos=strchr(pos+1,'/')) != 0) + *pos=FN_LIBCHAR; + } +#endif +#ifdef FN_C_BEFORE_DIR_2 + { + reg1 my_string pos; + for (pos=to ; *pos ; pos++) + { + if (*pos == FN_C_BEFORE_DIR_2) + *pos=FN_C_BEFORE_DIR; + if (*pos == FN_C_AFTER_DIR_2) + *pos=FN_C_AFTER_DIR; + } + } +#else + { /* Append FN_LIBCHAR if not there */ + char *end=strend(to); + if (end != to && (end[-1] != FN_LIBCHAR && end[-1] != FN_DEVCHAR)) + { + end[0]=FN_LIBCHAR; + end[1]=0; + } + } +#endif +} /* convert_dirname */ diff --git a/mysys/mf_fn_ext.c b/mysys/mf_fn_ext.c new file mode 100644 index 00000000000..6a9b9d18341 --- /dev/null +++ b/mysys/mf_fn_ext.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Returnerar en pekare till filnamnets extension. */ + +#include "mysys_priv.h" +#include <m_string.h> + + /* Return a pointerto the extension of the filename + The pointer points at the extension character (normally '.')) + If there isn't any extension, the pointer points at the end + NULL of the filename + */ + +my_string fn_ext(const char *name) +{ + register my_string pos,gpos; + DBUG_ENTER("fn_ext"); + DBUG_PRINT("mfunkt",("name: '%s'",name)); + +#if defined(FN_DEVCHAR) || defined(FN_C_AFTER_DIR) + { + char buff[FN_REFLEN]; + gpos=(my_string) name+dirname_part(buff,(char*) name); + } +#else + if (!(gpos=strrchr(name,FNLIBCHAR))) + gpos=name; +#endif + pos=strrchr(gpos,FN_EXTCHAR); + DBUG_RETURN (pos ? pos : strend(gpos)); +} /* fn_ext */ diff --git a/mysys/mf_format.c b/mysys/mf_format.c new file mode 100644 index 00000000000..623f1dbd19e --- /dev/null +++ b/mysys/mf_format.c @@ -0,0 +1,146 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include <m_string.h> +#ifdef HAVE_REALPATH +#include <sys/param.h> +#include <sys/stat.h> +#endif + + /* format a filename with replace of library and extension */ + /* params to and name may be identicall */ + /* function doesn't change name if name != to */ + /* Flag may be: 1 replace filenames library with 'dsk' */ + /* 2 replace extension with 'form' */ + /* 4 Unpack filename (replace ~ with home) */ + /* 8 Pack filename as short as possibly */ + /* 16 Resolve symbolic links for filename */ + /* 32 Resolve filename to full path */ + +#ifdef MAXPATHLEN +#define BUFF_LEN MAXPATHLEN +#else +#define BUFF_LEN FN_LEN +#endif + +my_string fn_format(my_string to, const char *name, const char *dsk, + const char *form, int flag) +{ + reg1 uint length; + char dev[FN_REFLEN], buff[BUFF_LEN], *pos, *startpos; + const char *ext; + DBUG_ENTER("fn_format"); + DBUG_PRINT("enter",("name: %s dsk: %s form: %s flag: %d", + name,dsk,form,flag)); + + /* Kopiera & skippa enheten */ + name+=(length=dirname_part(dev,(startpos=(my_string) name))); + if (length == 0 || flag & 1) + { + (void) strmov(dev,dsk); /* Use given directory */ + convert_dirname(dev); /* Fix to this OS */ + } + if (flag & 8) + pack_dirname(dev,dev); /* Put in ./.. and ~/.. */ + if (flag & 4) + (void) unpack_dirname(dev,dev); /* Replace ~/.. with dir */ + if ((pos=strchr(name,FN_EXTCHAR)) != NullS) + { + if ((flag & 2) == 0) /* Skall vi byta extension ? */ + { + length=strlength(name); /* Old extension */ + ext = ""; + } + else + { + length=(uint) (pos-(char*) name); /* Change extension */ + ext= form; + } + } + else + { + length=strlength(name); /* Har ingen ext- tag nya */ + ext=form; + } + + if (strlen(dev)+length+strlen(ext) >= FN_REFLEN || length >= FN_LEN ) + { /* To long path, return original */ + uint tmp_length=strlength(startpos); + DBUG_PRINT("error",("dev: '%s' ext: '%s' length: %d",dev,ext,length)); + (void) strmake(to,startpos,min(tmp_length,FN_REFLEN-1)); + } + else + { + if (to == startpos) + { + bmove(buff,(char*) name,length); /* Save name for last copy */ + name=buff; + } + (void) strmov(strnmov(strmov(to,dev),name,length),ext); +#ifdef FN_UPPER_CASE + caseup_str(to); +#endif +#ifdef FN_LOWER_CASE + casedn_str(to); +#endif + } + /* Purify gives a lot of UMR errors when using realpath */ +#if defined(HAVE_REALPATH) && !defined(HAVE_purify) + if (flag & 16) + { + struct stat stat_buff; + if (flag & 32 || (!lstat(to,&stat_buff) && S_ISLNK(stat_buff.st_mode))) + { + if (realpath(to,buff)) + strmov(to,buff); + } + } +#endif + DBUG_RETURN (to); +} /* fn_format */ + + + /* + strlength(const string str) + Return length of string with end-space:s not counted. + */ + +size_s strlength(const char *str) +{ + reg1 my_string pos; + reg2 my_string found; + DBUG_ENTER("strlength"); + + pos=found=(char*) str; + + while (*pos) + { + if (*pos != ' ') + { + while (*++pos && *pos != ' ') {}; + if (!*pos) + { + found=pos; /* String ends here */ + break; + } + } + found=pos; + while (*++pos == ' ') {}; + } + DBUG_RETURN((size_s) (found-(char*) str)); +} /* strlength */ diff --git a/mysys/mf_getdate.c b/mysys/mf_getdate.c new file mode 100644 index 00000000000..627789dc802 --- /dev/null +++ b/mysys/mf_getdate.c @@ -0,0 +1,59 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Get date in a printable form: yyyy-mm-dd hh:mm:ss */ + +#include "mysys_priv.h" +#include <m_string.h> + + /* + If flag & 1 Return date and time + If flag & 2 Return short date format YYMMDD + */ + + +void get_date(register my_string to, int flag, time_t date) +{ + reg2 struct tm *start_time; + time_t skr; +#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT) + struct tm tm_tmp; +#endif + + skr=date ? (time_t) date : time((time_t*) 0); +#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT) + localtime_r(&skr,&tm_tmp); + start_time= &tm_tmp; +#else + start_time=localtime(&skr); +#endif + if (flag & 2) + sprintf(to,"%02d%02d%02d", + start_time->tm_year % 100, + start_time->tm_mon+1, + start_time->tm_mday); + else + sprintf(to,"%d-%02d-%02d", + start_time->tm_year+1900, + start_time->tm_mon+1, + start_time->tm_mday); + if (flag & 1) + sprintf(strend(to)," %2d:%02d:%02d", + start_time->tm_hour, + start_time->tm_min, + start_time->tm_sec); +} /* get_date */ diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c new file mode 100644 index 00000000000..86cf5fc65e2 --- /dev/null +++ b/mysys/mf_iocache.c @@ -0,0 +1,603 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* + Cashing of files with only does (sequential) read or writes of fixed- + length records. A read isn't allowed to go over file-length. A read is ok + if it ends at file-length and next read can try to read after file-length + (and get a EOF-error). + Possibly use of asyncronic io. + macros for read and writes for faster io. + Used instead of FILE when reading or writing hole files. + This shall make mf_rec_cache obsolite. + One can change info->pos_in_file to a higer value to skipp bytes in file if + also info->rc_pos is set to info->rc_end. +*/ + +#define MAP_TO_USE_RAID +#include "mysys_priv.h" +#include <m_string.h> +#ifdef HAVE_AIOWAIT +#include "mysys_err.h" +#include <errno.h> +static void my_aiowait(my_aio_result *result); +#endif + + + /* + ** if cachesize == 0 then use default cachesize (from s-file) + ** if file == -1 then real_open_cached_file() will be called to + ** returns 0 if ok + */ + +int init_io_cache(IO_CACHE *info, File file, uint cachesize, + enum cache_type type, my_off_t seek_offset, + pbool use_async_io, myf cache_myflags) +{ + uint min_cache; + DBUG_ENTER("init_io_cache"); + DBUG_PRINT("enter",("type: %d pos: %ld",(int) type, (ulong) seek_offset)); + + info->file=file; + if (!cachesize) + if (! (cachesize= my_default_record_cache_size)) + DBUG_RETURN(1); /* No cache requested */ + min_cache=use_async_io ? IO_SIZE*4 : IO_SIZE*2; + if (type == READ_CACHE) + { /* Assume file isn't growing */ + my_off_t file_pos,end_of_file; + if ((file_pos=my_tell(file,MYF(0)) == MY_FILEPOS_ERROR)) + DBUG_RETURN(1); + end_of_file=my_seek(file,0L,MY_SEEK_END,MYF(0)); + if (end_of_file < seek_offset) + end_of_file=seek_offset; + VOID(my_seek(file,file_pos,MY_SEEK_SET,MYF(0))); + if ((my_off_t) cachesize > end_of_file-seek_offset+IO_SIZE*2-1) + { + cachesize=(uint) (end_of_file-seek_offset)+IO_SIZE*2-1; + use_async_io=0; /* No nead to use async */ + } + } + + for (;;) + { + cachesize=(uint) ((ulong) (cachesize + min_cache-1) & + (ulong) ~(min_cache-1)); + if (cachesize < min_cache) + cachesize = min_cache; + if ((info->buffer= + (byte*) my_malloc(cachesize, + MYF((cache_myflags & ~ MY_WME) | + (cachesize == min_cache ? MY_WME : 0)))) != 0) + break; /* Enough memory found */ + if (cachesize == min_cache) + DBUG_RETURN(2); /* Can't alloc cache */ + cachesize= (uint) ((long) cachesize*3/4); /* Try with less memory */ + } + info->pos_in_file=seek_offset; + info->read_length=info->buffer_length=cachesize; + info->seek_not_done= test(file >= 0); /* Seek not done */ + info->myflags=cache_myflags & ~(MY_NABP | MY_FNABP); + info->rc_request_pos=info->rc_pos=info->buffer; + + if (type == READ_CACHE) + { + info->rc_end=info->buffer; /* Nothing in cache */ + } + else /* type == WRITE_CACHE */ + { + info->rc_end=info->buffer+info->buffer_length- (seek_offset & (IO_SIZE-1)); + } + info->end_of_file=MY_FILEPOS_ERROR; /* May be changed by user */ + info->type=type; + info->error=0; + info->read_function=_my_b_read; +#ifdef HAVE_AIOWAIT + if (use_async_io && ! my_disable_async_io) + { + DBUG_PRINT("info",("Using async io")); + info->read_length/=2; + info->read_function=_my_b_async_read; + } + info->inited=info->aio_result.pending=0; +#endif + DBUG_RETURN(0); +} /* init_io_cache */ + + + /* Wait until current request is ready */ + +#ifdef HAVE_AIOWAIT +static void my_aiowait(my_aio_result *result) +{ + if (result->pending) + { + struct aio_result_t *tmp; + for (;;) + { + if ((int) (tmp=aiowait((struct timeval *) 0)) == -1) + { + if (errno == EINTR) + continue; + DBUG_PRINT("error",("No aio request, error: %d",errno)); + result->pending=0; /* Assume everythings is ok */ + break; + } + ((my_aio_result*) tmp)->pending=0; + if ((my_aio_result*) tmp == result) + break; + } + } + return; +} +#endif + + /* Use this to reset cache to start or other type */ + /* Some simple optimizing is done when reinit in current buffer */ + +my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, + my_off_t seek_offset, + pbool use_async_io __attribute__((unused)), + pbool clear_cache) +{ + DBUG_ENTER("reinit_io_cache"); + + info->seek_not_done= test(info->file >= 0); /* Seek not done */ + if (! clear_cache && + seek_offset >= info->pos_in_file && + seek_offset <= info->pos_in_file + + (uint) (info->rc_end - info->rc_request_pos)) + { /* use current buffer */ + if (info->type == WRITE_CACHE && type == READ_CACHE) + { + info->rc_end=info->rc_pos; + info->end_of_file=my_b_tell(info); + } + else if (info->type == READ_CACHE && type == WRITE_CACHE) + info->rc_end=info->buffer+info->buffer_length; + info->rc_pos=info->rc_request_pos+(seek_offset-info->pos_in_file); +#ifdef HAVE_AIOWAIT + my_aiowait(&info->aio_result); /* Wait for outstanding req */ +#endif + } + else + { + if (info->type == WRITE_CACHE && type == READ_CACHE) + info->end_of_file=my_b_tell(info); + if (flush_io_cache(info)) + DBUG_RETURN(1); + info->pos_in_file=seek_offset; + info->rc_request_pos=info->rc_pos=info->buffer; + if (type == READ_CACHE) + { + info->rc_end=info->buffer; /* Nothing in cache */ + } + else + { + info->rc_end=info->buffer+info->buffer_length- + (seek_offset & (IO_SIZE-1)); + info->end_of_file=MY_FILEPOS_ERROR; /* May be changed by user */ + } + } + info->type=type; + info->error=0; + info->read_function=_my_b_read; +#ifdef HAVE_AIOWAIT + if (use_async_io && ! my_disable_async_io && + ((ulong) info->buffer_length < + (ulong) (info->end_of_file - seek_offset))) + { + info->read_length=info->buffer_length/2; + info->read_function=_my_b_async_read; + } + info->inited=0; +#endif + DBUG_RETURN(0); +} /* init_io_cache */ + + + + /* Read buffered. Returns 1 if can't read requested characters */ + /* Returns 0 if record read */ + +int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count) +{ + uint length,diff_length,left_length; + my_off_t max_length, pos_in_file; + + memcpy(Buffer,info->rc_pos, + (size_t) (left_length=(uint) (info->rc_end-info->rc_pos))); + Buffer+=left_length; + Count-=left_length; + pos_in_file=info->pos_in_file+(uint) (info->rc_end - info->buffer); + if (info->seek_not_done) + { /* File touched, do seek */ + VOID(my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0))); + info->seek_not_done=0; + } + diff_length=(uint) (pos_in_file & (IO_SIZE-1)); + if (Count >= (uint) (IO_SIZE+(IO_SIZE-diff_length))) + { /* Fill first intern buffer */ + uint read_length; + if (info->end_of_file == pos_in_file) + { /* End of file */ + info->error=(int) left_length; + return 1; + } + length=(Count & (uint) ~(IO_SIZE-1))-diff_length; + if ((read_length=my_read(info->file,Buffer,(uint) length,info->myflags)) + != (uint) length) + { + info->error= read_length == (uint) -1 ? -1 : + (int) (read_length+left_length); + return 1; + } + Count-=length; + Buffer+=length; + pos_in_file+=length; + left_length+=length; + diff_length=0; + } + max_length=info->end_of_file - pos_in_file; + if (max_length > info->read_length-diff_length) + max_length=info->read_length-diff_length; + + if (!max_length) + { + if (Count) + { + info->error= left_length; /* We only got this many char */ + return 1; + } + length=0; /* Didn't read any chars */ + } + else if ((length=my_read(info->file,info->buffer,(uint) max_length, + info->myflags)) < Count || + length == (uint) -1) + { + if (length != (uint) -1) + memcpy(Buffer,info->buffer,(size_t) length); + info->error= length == (uint) -1 ? -1 : (int) (length+left_length); + return 1; + } + info->rc_pos=info->buffer+Count; + info->rc_end=info->buffer+length; + info->pos_in_file=pos_in_file; + memcpy(Buffer,info->buffer,(size_t) Count); + return 0; +} + + +#ifdef HAVE_AIOWAIT + +int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) +{ + uint length,read_length,diff_length,left_length,use_length,org_Count; + my_off_t max_length; + my_off_t next_pos_in_file; + byte *read_buffer; + + memcpy(Buffer,info->rc_pos, + (size_t) (left_length=(uint) (info->rc_end-info->rc_pos))); + Buffer+=left_length; + org_Count=Count; + Count-=left_length; + + if (info->inited) + { /* wait for read block */ + info->inited=0; /* No more block to read */ + my_aiowait(&info->aio_result); /* Wait for outstanding req */ + if (info->aio_result.result.aio_errno) + { + if (info->myflags & MY_WME) + my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), + my_filename(info->file), + info->aio_result.result.aio_errno); + my_errno=info->aio_result.result.aio_errno; + info->error= -1; + return(1); + } + if (! (read_length = (uint) info->aio_result.result.aio_return) || + read_length == (uint) -1) + { + my_errno=0; /* For testing */ + info->error= (read_length == (uint) -1 ? -1 : + (int) (read_length+left_length)); + return(1); + } + info->pos_in_file+=(uint) (info->rc_end - info->rc_request_pos); + + if (info->rc_request_pos != info->buffer) + info->rc_request_pos=info->buffer; + else + info->rc_request_pos=info->buffer+info->read_length; + info->rc_pos=info->rc_request_pos; + next_pos_in_file=info->aio_read_pos+read_length; + + /* Check if pos_in_file is changed + (_ni_read_cache may have skipped some bytes) */ + + if (info->aio_read_pos < info->pos_in_file) + { /* Fix if skipped bytes */ + if (info->aio_read_pos + read_length < info->pos_in_file) + { + read_length=0; /* Skipp block */ + next_pos_in_file=info->pos_in_file; + } + else + { + my_off_t offset= (info->pos_in_file - info->aio_read_pos); + info->pos_in_file=info->aio_read_pos; /* Whe are here */ + info->rc_pos=info->rc_request_pos+offset; + read_length-=offset; /* Bytes left from rc_pos */ + } + } +#ifndef DBUG_OFF + if (info->aio_read_pos > info->pos_in_file) + { + my_errno=EINVAL; + return(info->read_length= -1); + } +#endif + /* Copy found bytes to buffer */ + length=min(Count,read_length); + memcpy(Buffer,info->rc_pos,(size_t) length); + Buffer+=length; + Count-=length; + left_length+=length; + info->rc_end=info->rc_pos+read_length; + info->rc_pos+=length; + } + else + next_pos_in_file=(info->pos_in_file+ (uint) + (info->rc_end - info->rc_request_pos)); + + /* If reading large blocks, or first read or read with skipp */ + if (Count) + { + if (next_pos_in_file == info->end_of_file) + { + info->error=(int) (read_length+left_length); + return 1; + } + VOID(my_seek(info->file,next_pos_in_file,MY_SEEK_SET,MYF(0))); + read_length=IO_SIZE*2- (uint) (next_pos_in_file & (IO_SIZE-1)); + if (Count < read_length) + { /* Small block, read to cache */ + if ((read_length=my_read(info->file,info->rc_request_pos, + read_length, info->myflags)) == (uint) -1) + return info->error= -1; + use_length=min(Count,read_length); + memcpy(Buffer,info->rc_request_pos,(size_t) use_length); + info->rc_pos=info->rc_request_pos+Count; + info->rc_end=info->rc_request_pos+read_length; + info->pos_in_file=next_pos_in_file; /* Start of block in cache */ + next_pos_in_file+=read_length; + + if (Count != use_length) + { /* Didn't find hole block */ + if (info->myflags & (MY_WME | MY_FAE | MY_FNABP) && Count != org_Count) + my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), + my_filename(info->file),my_errno); + info->error=(int) (read_length+left_length); + return 1; + } + } + else + { /* Big block, don't cache it */ + if ((read_length=my_read(info->file,Buffer,(uint) Count,info->myflags)) + != Count) + { + info->error= read_length == (uint) -1 ? -1 : read_length+left_length; + return 1; + } + info->rc_pos=info->rc_end=info->rc_request_pos; + info->pos_in_file=(next_pos_in_file+=Count); + } + } + + /* Read next block with asyncronic io */ + max_length=info->end_of_file - next_pos_in_file; + diff_length=(next_pos_in_file & (IO_SIZE-1)); + + if (max_length > (my_off_t) info->read_length - diff_length) + max_length= (my_off_t) info->read_length - diff_length; + if (info->rc_request_pos != info->buffer) + read_buffer=info->buffer; + else + read_buffer=info->buffer+info->read_length; + info->aio_read_pos=next_pos_in_file; + if (max_length) + { + info->aio_result.result.aio_errno=AIO_INPROGRESS; /* Marker for test */ + DBUG_PRINT("aioread",("filepos: %ld length: %ld", + (ulong) next_pos_in_file,(ulong) max_length)); + if (aioread(info->file,read_buffer,(int) max_length, + (my_off_t) next_pos_in_file,MY_SEEK_SET, + &info->aio_result.result)) + { /* Skipp async io */ + my_errno=errno; + DBUG_PRINT("error",("got error: %d, aio_result: %d from aioread, async skipped", + errno, info->aio_result.result.aio_errno)); + if (info->rc_request_pos != info->buffer) + { + bmove(info->buffer,info->rc_request_pos, + (uint) (info->rc_end - info->rc_pos)); + info->rc_request_pos=info->buffer; + info->rc_pos-=info->read_length; + info->rc_end-=info->read_length; + } + info->read_length=info->buffer_length; /* Use hole buffer */ + info->read_function=_my_b_read; /* Use normal IO_READ next */ + } + else + info->inited=info->aio_result.pending=1; + } + return 0; /* Block read, async in use */ +} /* _my_b_async_read */ +#endif + + +/* Read one byte when buffer is empty */ + +int _my_b_get(IO_CACHE *info) +{ + byte buff; + if ((*(info)->read_function)(info,&buff,1)) + return my_b_EOF; + return (int) (uchar) buff; +} + + /* Returns != 0 if error on write */ + +int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count) +{ + uint rest_length,length; + + rest_length=(uint) (info->rc_end - info->rc_pos); + memcpy(info->rc_pos,Buffer,(size_t) rest_length); + Buffer+=rest_length; + Count-=rest_length; + info->rc_pos+=rest_length; + if (flush_io_cache(info)) + return 1; + if (Count >= IO_SIZE) + { /* Fill first intern buffer */ + length=Count & (uint) ~(IO_SIZE-1); + if (info->seek_not_done) + { /* File touched, do seek */ + VOID(my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0))); + info->seek_not_done=0; + } + if (my_write(info->file,Buffer,(uint) length,info->myflags | MY_NABP)) + return info->error= -1; + Count-=length; + Buffer+=length; + info->pos_in_file+=length; + } + memcpy(info->rc_pos,Buffer,(size_t) Count); + info->rc_pos+=Count; + return 0; +} + + +/* + Write a block to disk where part of the data may be inside the record + buffer. As all write calls to the data goes through the cache, + we will never get a seek over the end of the buffer +*/ + +int my_block_write(register IO_CACHE *info, const byte *Buffer, uint Count, + my_off_t pos) +{ + uint length; + int error=0; + + if (pos < info->pos_in_file) + { + /* Of no overlap, write everything without buffering */ + if (pos + Count <= info->pos_in_file) + return my_pwrite(info->file, Buffer, Count, pos, + info->myflags | MY_NABP); + /* Write the part of the block that is before buffer */ + length= (uint) (info->pos_in_file - pos); + if (my_pwrite(info->file, Buffer, length, pos, info->myflags | MY_NABP)) + info->error=error=-1; + Buffer+=length; + pos+= length; + Count-= length; + } + + /* Check if we want to write inside the used part of the buffer.*/ + length= (uint) (info->rc_end - info->buffer); + if (pos < info->pos_in_file + length) + { + uint offset= (uint) (pos - info->pos_in_file); + length-=offset; + if (length > Count) + length=Count; + memcpy(info->buffer+offset, Buffer, length); + Buffer+=length; + Count-= length; + /* Fix length of buffer if the new data was larger */ + if (info->buffer+length > info->rc_pos) + info->rc_pos=info->buffer+length; + if (!Count) + return (error); + } + /* Write at the end of the current buffer; This is the normal case */ + if (_my_b_write(info, Buffer, Count)) + error= -1; + return error; +} + + + /* Flush write cache */ + +int flush_io_cache(IO_CACHE *info) +{ + uint length; + DBUG_ENTER("flush_io_cache"); + + if (info->type == WRITE_CACHE) + { + if (info->file == -1) + { + if (real_open_cached_file(info)) + DBUG_RETURN((info->error= -1)); + } + if (info->rc_pos != info->buffer) + { + length=(uint) (info->rc_pos - info->buffer); + if (info->seek_not_done) + { /* File touched, do seek */ + VOID(my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0))); + info->seek_not_done=0; + } + info->rc_pos=info->buffer; + info->pos_in_file+=length; + info->rc_end=(info->buffer+info->buffer_length- + (info->pos_in_file & (IO_SIZE-1))); + if (my_write(info->file,info->buffer,length,info->myflags | MY_NABP)) + DBUG_RETURN((info->error= -1)); + DBUG_RETURN(0); + } + } +#ifdef HAVE_AIOWAIT + else + { + my_aiowait(&info->aio_result); /* Wait for outstanding req */ + info->inited=0; + } +#endif + DBUG_RETURN(0); +} + + +int end_io_cache(IO_CACHE *info) +{ + int error=0; + DBUG_ENTER("end_io_cache"); + if (info->buffer) + { + if (info->file != -1) /* File doesn't exist */ + error=flush_io_cache(info); + my_free((gptr) info->buffer,MYF(MY_WME)); + info->buffer=info->rc_pos=(byte*) 0; + } + DBUG_RETURN(error); +} /* end_io_cache */ diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c new file mode 100644 index 00000000000..eca22039444 --- /dev/null +++ b/mysys/mf_keycache.c @@ -0,0 +1,753 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* + This functions is handle keyblock cacheing for NISAM, MISAM and PISAM + databases. + One cache can handle many files. Every different blocksize has it owns + set of buffers that are allocated from block_mem. + init_key_cache() should be used to init cache handler. + */ + +#include "mysys_priv.h" +#include "my_static.h" +#include <m_string.h> +#include <errno.h> + +#if defined(MSDOS) && !defined(M_IC80386) + /* We nead much memory */ +#undef my_malloc_lock +#undef my_free_lock +#define my_malloc_lock(A,B) halloc((long) (A/IO_SIZE),IO_SIZE) +#define my_free_lock(A,B) hfree(A) +#endif + +/* size of map to be used to find changed files */ + +#define CHANGED_BLOCKS_HASH 128 /* Must be power of 2 */ +#define CHANGED_BLOCKS_MASK (CHANGED_BLOCKS_HASH-1) +#define FLUSH_CACHE 2000 /* Sort this many blocks at once */ + +static uint find_next_bigger_power(uint value); +static SEC_LINK *find_key_block(int file,my_off_t filepos,int *error); + + /* static variables in this file */ +static SEC_LINK *_my_block_root,**_my_hash_root, + *_my_used_first,*_my_used_last; +static int _my_disk_blocks; +static uint _my_disk_blocks_used, _my_hash_blocks; +ulong _my_blocks_used,_my_blocks_changed; +ulong _my_cache_w_requests,_my_cache_write,_my_cache_r_requests, + _my_cache_read; +static byte HUGE_PTR *_my_block_mem; +static SEC_LINK *changed_blocks[CHANGED_BLOCKS_HASH]; +static SEC_LINK *file_blocks[CHANGED_BLOCKS_HASH]; +#ifndef DBUG_OFF +static my_bool _my_printed; +#endif + + + /* Init of disk_buffert */ + /* Returns blocks in use */ + /* ARGSUSED */ + +int init_key_cache(ulong use_mem, + ulong leave_this_much_mem __attribute__((unused))) +{ + uint blocks,length; + byte *extra_mem=0; + DBUG_ENTER("init_key_cache"); + + if (key_cache_inited && _my_disk_blocks > 0) + { + DBUG_PRINT("warning",("key cache allready in use")); /* purecov: inspected */ + DBUG_RETURN(0); /* purecov: inspected */ + } + if (! key_cache_inited) + { + key_cache_inited=TRUE; + _my_disk_blocks= -1; +#ifndef DBUG_OFF + _my_printed=0; +#endif + } + + blocks= (uint) (use_mem/(sizeof(SEC_LINK)+sizeof(SEC_LINK*)*5/4+KEYCACHE_BLOCK_SIZE)); + /* No use to have very few blocks */ + if (blocks >= 8 && _my_disk_blocks < 0) + { +#if !defined(HAVE_ALLOCA) && !defined(THREAD) + if ((extra_mem=my_malloc((uint) leave_this_much_mem,MYF(0))) == 0) + goto err; +#endif + for (;;) + { + if ((_my_hash_blocks=find_next_bigger_power((uint) blocks)) < blocks*5/4) + _my_hash_blocks<<=1; + while ((length=(uint) blocks*sizeof(SEC_LINK)+ + sizeof(SEC_LINK*)*_my_hash_blocks)+(ulong) blocks*KEYCACHE_BLOCK_SIZE > + use_mem) + blocks--; + if ((_my_block_mem=my_malloc_lock((ulong) blocks * KEYCACHE_BLOCK_SIZE,MYF(0)))) + { + if ((_my_block_root=(SEC_LINK*) my_malloc((uint) length,MYF(0))) != 0) + break; + my_free_lock(_my_block_mem,MYF(0)); + } + if (blocks < 8) + goto err; + blocks=blocks/4*3; + } + _my_disk_blocks=(int) blocks; + _my_hash_root= (SEC_LINK**) (_my_block_root+blocks); + bzero((byte*) _my_hash_root,_my_hash_blocks*sizeof(SEC_LINK*)); + _my_used_first=_my_used_last=0; + _my_blocks_used=_my_disk_blocks_used=_my_blocks_changed=0; + _my_cache_w_requests=_my_cache_r_requests=_my_cache_read=_my_cache_write=0; + DBUG_PRINT("exit",("disk_blocks: %d block_root: %lx _my_hash_blocks: %d hash_root: %lx", + _my_disk_blocks,_my_block_root,_my_hash_blocks, + _my_hash_root)); +#if !defined(HAVE_ALLOCA) && !defined(THREAD) + my_free(extra_mem,MYF(0)); +#endif + } + bzero((gptr) changed_blocks,sizeof(changed_blocks[0])*CHANGED_BLOCKS_HASH); + bzero((gptr) file_blocks,sizeof(file_blocks[0])*CHANGED_BLOCKS_HASH); + DBUG_RETURN((int) blocks); +err: + if (extra_mem) /* purecov: inspected */ + my_free(extra_mem,MYF(0)); + my_errno=ENOMEM; + DBUG_RETURN(0); +} /* init_key_cache */ + + + /* Remove key_cache from memory */ + +void end_key_cache(void) +{ + DBUG_ENTER("end_key_cache"); + if (! _my_blocks_changed) + { + if (_my_disk_blocks > 0) + { + my_free_lock((gptr) _my_block_mem,MYF(0)); + my_free((gptr) _my_block_root,MYF(0)); + _my_disk_blocks= -1; + } + } + DBUG_PRINT("status", + ("used: %d changed: %d w_requests: %ld writes: %ld r_requests: %ld reads: %ld", + _my_blocks_used,_my_blocks_changed,_my_cache_w_requests, + _my_cache_write,_my_cache_r_requests,_my_cache_read)); + DBUG_VOID_RETURN; +} /* end_key_cache */ + + +static uint find_next_bigger_power(uint value) +{ + uint old_value=1; + while (value) + { + old_value=value; + value&= value-1; + } + return (old_value << 1); +} + +static inline void link_into_file_blocks(SEC_LINK *next, int file) +{ + reg1 SEC_LINK **ptr= &file_blocks[(uint) file & CHANGED_BLOCKS_MASK]; + next->prev_changed= ptr; + if ((next->next_changed= *ptr)) + (*ptr)->prev_changed= &next->next_changed; + *ptr=next; +} + + +static inline void relink_into_file_blocks(SEC_LINK *next, int file) +{ + reg1 SEC_LINK **ptr= &file_blocks[(uint) file & CHANGED_BLOCKS_MASK]; + if (next->next_changed) + next->next_changed->prev_changed=next->prev_changed; + *next->prev_changed=next->next_changed; + next->prev_changed= ptr; + if ((next->next_changed= *ptr)) + (*ptr)->prev_changed= &next->next_changed; + *ptr=next; +} + +static inline void link_changed_to_file(SEC_LINK *next,int file) +{ + reg1 SEC_LINK **ptr= &file_blocks[(uint) file & CHANGED_BLOCKS_MASK]; + if (next->next_changed) + next->next_changed->prev_changed=next->prev_changed; + *next->prev_changed=next->next_changed; + next->prev_changed= ptr; + if ((next->next_changed= *ptr)) + (*ptr)->prev_changed= &next->next_changed; + *ptr=next; + next->changed=0; + _my_blocks_changed--; +} + +static inline void link_file_to_changed(SEC_LINK *next) +{ + reg1 SEC_LINK **ptr= &changed_blocks[(uint) next->file & CHANGED_BLOCKS_MASK]; + if (next->next_changed) + next->next_changed->prev_changed=next->prev_changed; + *next->prev_changed=next->next_changed; + next->prev_changed= ptr; + if ((next->next_changed= *ptr)) + (*ptr)->prev_changed= &next->next_changed; + *ptr=next; + next->changed=1; + _my_blocks_changed++; +} + + +#ifndef DBUG_OFF +#define DBUG_OFF /* This should work */ +#endif + +#ifndef DBUG_OFF +static void test_key_cache(char *where, my_bool lock); +#endif + + + /* + ** read a key_buffer + ** filepos must point at a even KEYCACHE_BLOCK_SIZE block + ** if return_buffer is set then the intern buffer is returned if + ** it can be used + ** Returns adress to where data is read + */ + +byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length, + uint block_length __attribute__((unused)), + int return_buffer __attribute__((unused))) +{ + reg1 SEC_LINK *next; + int error=0; + +#ifndef THREAD + if (block_length > KEYCACHE_BLOCK_SIZE) + return_buffer=0; +#endif + if (_my_disk_blocks > 0) + { /* We have key_cacheing */ + byte *start=buff; + uint read_length; + pthread_mutex_lock(&THR_LOCK_keycache); + do + { + _my_cache_r_requests++; + read_length= length > KEYCACHE_BLOCK_SIZE ? KEYCACHE_BLOCK_SIZE : length; + if (!(next=find_key_block(file,filepos,&error))) + { + pthread_mutex_unlock(&THR_LOCK_keycache); + return (byte*) 0; /* Got a fatal error */ + } + if (error) + { /* Didn't find it in cache */ + if (my_pread(file,next->buffer,read_length,filepos,MYF(MY_NABP))) + { + pthread_mutex_unlock(&THR_LOCK_keycache); + return((byte*) 0); + } + _my_cache_read++; + } +#ifndef THREAD /* buffer may be used a long time */ + if (return_buffer) + { + pthread_mutex_unlock(&THR_LOCK_keycache); + return (next->buffer); + } +#endif + if (! (read_length & 511)) + bmove512(buff,next->buffer,read_length); + else + memcpy(buff,next->buffer,(size_t) read_length); + buff+=read_length; + filepos+=read_length; + } while ((length-= read_length)); + pthread_mutex_unlock(&THR_LOCK_keycache); + return(start); + pthread_mutex_unlock(&THR_LOCK_keycache); + } + _my_cache_r_requests++; + _my_cache_read++; + if (my_pread(file,(byte*) buff,length,filepos,MYF(MY_NABP))) + error=1; + return (error ? (byte*) 0 : buff); +} /* key_cache_read */ + + + /* write a key_buffer */ + /* We don't have to use pwrite because of write locking */ + /* buff must point at a even KEYCACHE_BLOCK_SIZE block */ + +int key_cache_write(File file, my_off_t filepos, byte *buff, uint length, + uint block_length __attribute__((unused)), + int dont_write) +{ + reg1 SEC_LINK *next; + int error=0; + + if (!dont_write) + { /* Forced write of buffer */ + _my_cache_write++; + if (my_pwrite(file,buff,length,filepos,MYF(MY_NABP | MY_WAIT_IF_FULL))) + return(1); + } + +#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) + DBUG_EXECUTE("exec",test_key_cache("start of key_cache_write",1);); +#endif + if (_my_disk_blocks > 0) + { /* We have key_cacheing */ + uint read_length; + pthread_mutex_lock(&THR_LOCK_keycache); + _my_cache_w_requests++; + do + { + read_length= length > KEYCACHE_BLOCK_SIZE ? KEYCACHE_BLOCK_SIZE : length; + if (!(next=find_key_block(file,filepos,&error))) + goto end; /* Fatal error */ + if (!dont_write) /* If we wrote buff at start */ + { + if (next->changed) /* Unlink from changed list */ + link_changed_to_file(next,next->file); + } + else if (!next->changed) + link_file_to_changed(next); /* Add to changed list */ + + if (!(read_length & 511)) + bmove512(next->buffer,buff,read_length); + else + memcpy(next->buffer,buff,(size_t) read_length); + buff+=read_length; + filepos+=read_length; + } while ((length-= read_length)); + error=0; + pthread_mutex_unlock(&THR_LOCK_keycache); + } + else if (dont_write) + { /* We must write, no cache */ + _my_cache_w_requests++; + _my_cache_write++; + if (my_pwrite(file,(byte*) buff,length,filepos, + MYF(MY_NABP | MY_WAIT_IF_FULL))) + error=1; + } +end: +#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) + DBUG_EXECUTE("exec",test_key_cache("end of key_cache_write",1);); +#endif + return(error); +} /* key_cache_write */ + + + /* Find block in cache */ + /* IF found sector and error is set then next->changed is cleared */ + +static SEC_LINK *find_key_block(int file, my_off_t filepos, int *error) +{ + reg1 SEC_LINK *next,**start; + +#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) + DBUG_EXECUTE("exec",test_key_cache("start of find_key_block",0);); +#endif + + *error=0; + next= *(start= &_my_hash_root[((ulong) (filepos/KEYCACHE_BLOCK_SIZE)+(ulong) file) & + (_my_hash_blocks-1)]); + while (next && (next->diskpos != filepos || next->file != file)) + next= next->next_hash; + + if (next) + { /* Found block */ + if (next != _my_used_last) + { /* Relink used-chain */ + if (next == _my_used_first) + _my_used_first=next->next_used; + else + { + next->prev_used->next_used = next->next_used; + next->next_used->prev_used = next->prev_used; + } + next->prev_used=_my_used_last; + _my_used_last->next_used=next; + } + } + else + { /* New block */ + if (_my_disk_blocks_used+1 <= (uint) _my_disk_blocks) + { /* There are unused blocks */ + next= &_my_block_root[_my_blocks_used++]; /* Link in hash-chain */ + next->buffer=ADD_TO_PTR(_my_block_mem, + (ulong) _my_disk_blocks_used*KEYCACHE_BLOCK_SIZE,byte*); + /* link first in file_blocks */ + next->changed=0; + link_into_file_blocks(next,file); + _my_disk_blocks_used++; + if (!_my_used_first) + _my_used_first=next; + if (_my_used_last) + _my_used_last->next_used=next; /* Last in used-chain */ + } + else + { /* Reuse old block */ + next= _my_used_first; + if (next->changed) + { + if (my_pwrite(next->file,next->buffer,KEYCACHE_BLOCK_SIZE,next->diskpos, + MYF(MY_NABP | MY_WAIT_IF_FULL))) + { + *error=1; + return((SEC_LINK*) 0); + } + _my_cache_write++; + link_changed_to_file(next,file); + } + else + { + if (next->file == -1) + link_into_file_blocks(next,file); + else + relink_into_file_blocks(next,file); + } + if (next->prev_hash) /* If in hash-link */ + if ((*next->prev_hash=next->next_hash) != 0) /* Remove from link */ + next->next_hash->prev_hash= next->prev_hash; + + _my_used_last->next_used=next; + _my_used_first=next->next_used; + } + if (*start) /* Link in first in h.-chain */ + (*start)->prev_hash= &next->next_hash; + next->next_hash= *start; next->prev_hash=start; *start=next; + next->prev_used=_my_used_last; + next->file=file; + next->diskpos=filepos; + *error=1; /* Block wasn't in memory */ + } + _my_used_last=next; +#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) + DBUG_EXECUTE("exec",test_key_cache("end of find_key_block",0);); +#endif + return next; +} /* find_key_block */ + + +static void free_block(SEC_LINK *used) +{ + used->file= -1; + if (used != _my_used_first) /* Relink used-chain */ + { + if (used == _my_used_last) + _my_used_last=used->prev_used; + else + { + used->prev_used->next_used = used->next_used; + used->next_used->prev_used = used->prev_used; + } + used->next_used=_my_used_first; + used->next_used->prev_used=used; + _my_used_first=used; + } + if ((*used->prev_hash=used->next_hash)) /* Relink hash-chain */ + used->next_hash->prev_hash= used->prev_hash; + if (used->next_changed) /* Relink changed/file list */ + used->next_changed->prev_changed=used->prev_changed; + *used->prev_changed=used->next_changed; + used->prev_hash=0; used->next_hash=0; /* Safety */ +} + + + /* Flush all changed blocks to disk. Free used blocks if requested */ + +static int cmp_sec_link(SEC_LINK **a, SEC_LINK **b) +{ + return (((*a)->diskpos < (*b)->diskpos) ? -1 : + ((*a)->diskpos > (*b)->diskpos) ? 1 : 0); +} + +static int flush_cached_blocks(File file, SEC_LINK **cache, uint count) +{ + uint last_errno=0; + qsort((byte*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link); + for ( ; count-- ; cache++) + { + if (my_pwrite(file,(*cache)->buffer,KEYCACHE_BLOCK_SIZE,(*cache)->diskpos, + MYF(MY_NABP | MY_WAIT_IF_FULL))) + { + if (!last_errno) + last_errno=errno ? errno : -1; + } + } + return last_errno; +} + + +int flush_key_blocks(File file, enum flush_type type) +{ + int error=0,last_errno=0; + uint count=0; + SEC_LINK *cache_buff[FLUSH_CACHE],**cache,**pos,**end; + SEC_LINK *used,*next; + DBUG_ENTER("flush_key_blocks"); + DBUG_PRINT("enter",("file: %d blocks_used: %d blocks_changed: %d", + file,_my_blocks_used,_my_blocks_changed)); + + pthread_mutex_lock(&THR_LOCK_keycache); + +#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) + DBUG_EXECUTE("exec",test_key_cache("start of flush_key_blocks",0);); +#endif + cache=cache_buff; /* If no key cache */ + if (_my_disk_blocks > 0 && + (!my_disable_flush_key_blocks || type != FLUSH_KEEP)) + { + if (type != FLUSH_IGNORE_CHANGED) + { + /* Count how many key blocks we have to cache to be able to + write everything with so few seeks as possible */ + + for (used=changed_blocks[(uint) file & CHANGED_BLOCKS_MASK]; + used ; + used=used->next_changed) + { + if (used->file == file) + count++; + } + /* Only allocate a new buffer if its bigger than the one we have */ + if (count <= FLUSH_CACHE || + !(cache=(SEC_LINK**) my_malloc(sizeof(SEC_LINK*)*count,MYF(0)))) + { + cache=cache_buff; /* Fall back to safe buffer */ + count=FLUSH_CACHE; + } + end=cache+count; + } + + /* Go through the keys and write them to buffer to be flushed */ + end=(pos=cache)+count; + for (used=changed_blocks[(uint) file & CHANGED_BLOCKS_MASK]; + used ; + used=next) + { + next=used->next_changed; + if (used->file == file) + { + if (type != FLUSH_IGNORE_CHANGED) + { + if (pos == end) + { + if ((error=flush_cached_blocks(file, cache, count))) + last_errno=error; + pos=cache; + } + *pos++=used; + _my_cache_write++; + } + if (type != FLUSH_KEEP && type != FLUSH_FORCE_WRITE) + { + /* This will not destroy position or data */ + used->changed=0; + _my_blocks_changed--; + free_block(used); + } + else + link_changed_to_file(used,file); + } + } + if (pos != cache) + { + if ((error=flush_cached_blocks(file, cache, (uint) (pos-cache)))) + last_errno=error; + } + /* The following happens very seldom */ + if (type != FLUSH_KEEP && type != FLUSH_FORCE_WRITE) + { + for (used=file_blocks[(uint) file & CHANGED_BLOCKS_MASK]; + used ; + used=next) + { + next=used->next_changed; + if (used->file == file && (!used->changed || + type == FLUSH_IGNORE_CHANGED)) + free_block(used); + } + } + } +#ifndef DBUG_OFF + DBUG_EXECUTE("exec",test_key_cache("end of flush_key_blocks",0);); +#endif + pthread_mutex_unlock(&THR_LOCK_keycache); + if (cache != cache_buff) + my_free((gptr) cache,MYF(0)); + if (last_errno) + errno=last_errno; /* Return first error */ + DBUG_RETURN(last_errno != 0); +} /* flush_key_blocks */ + + +#ifndef DBUG_OFF + + /* Test if disk-cachee is ok */ + +static void test_key_cache(char *where, my_bool lock) +{ + reg1 uint i,found,error,changed; + SEC_LINK *pos,**prev; + + if (lock) + pthread_mutex_lock(&THR_LOCK_keycache); + found=error=0; + for (i= 0 ; i < _my_hash_blocks ; i++) + { + + for (pos= *(prev= &_my_hash_root[i]) ; + pos && found < _my_blocks_used+2 ; + found++, pos= *(prev= &pos->next_hash)) + { + if (prev != pos->prev_hash) + { + error=1; + DBUG_PRINT("error", + ("hash: %d pos: %lx : prev: %lx != pos->prev: %lx", + i,pos,prev,pos->prev_hash)); + } + + if (((pos->diskpos/KEYCACHE_BLOCK_SIZE)+pos->file) % _my_hash_blocks != i) + { + DBUG_PRINT("error",("hash: %d pos: %lx : Wrong disk_buffer %ld", + i,pos,pos->diskpos)); + error=1; + } + } + } + if (found > _my_blocks_used) + { + DBUG_PRINT("error",("Found too many hash_pointers")); + error=1; + } + if (error && !_my_printed) + { /* Write all hash-pointers */ + _my_printed=1; + for (i=0 ; i < _my_hash_blocks ; i++) + { + DBUG_PRINT("loop",("hash: %d _my_hash_root: %lx",i,&_my_hash_root[i])); + pos= _my_hash_root[i]; found=0; + while (pos && found < 10) + { + DBUG_PRINT("loop",("pos: %lx prev: %lx next: %lx file: %d disk_buffer: %ld", pos,pos->prev_hash,pos->next_hash,pos->file,pos->diskpos)); + found++; pos= pos->next_hash; + } + } + } + + found=changed=0; + + if ((pos=_my_used_first)) + { + while (pos != _my_used_last && found < _my_blocks_used+2) + { + found++; + if (pos->changed) + changed++; + if (pos->next_used->prev_used != pos) + { + DBUG_PRINT("error",("pos: %lx next_used: %lx next_used->prev: %lx", + pos,pos->next_used,pos->next_used->prev_hash)); + error=1; + } + pos=pos->next_used; + } + found++; + if (pos->changed) + changed++; + } + if (found != _my_blocks_used) + { + DBUG_PRINT("error",("Found %d of %d keyblocks",found,_my_blocks_used)); + error=1; + } + + for (i= 0 ; i < CHANGED_BLOCKS_HASH ; i++) + { + found=0; + prev= &changed_blocks[i]; + for (pos= *prev ; pos && found < _my_blocks_used+2; pos=pos->next_changed) + { + found++; + if (pos->prev_changed != prev) + { + DBUG_PRINT("error",("changed_block list %d doesn't point backwards properly",i)); + error=1; + } + prev= &pos->next_changed; + if (((uint) pos->file & CHANGED_BLOCKS_MASK) != i) + { + DBUG_PRINT("error",("Wrong file %d in changed blocks: %d",pos->file,i)); + error=1; + } + changed--; + } + if (pos) + { + DBUG_PRINT("error",("changed_blocks %d has recursive link",i)); + error=1; + } + + found=0; + prev= &file_blocks[i]; + for (pos= *prev ; pos && found < _my_blocks_used+2; pos=pos->next_changed) + { + found++; + if (pos->prev_changed != prev) + { + DBUG_PRINT("error",("file_block list %d doesn't point backwards properly",i)); + error=1; + } + prev= &pos->next_changed; + if (((uint) pos->file & CHANGED_BLOCKS_MASK) != i) + { + DBUG_PRINT("error",("Wrong file %d in file_blocks: %d",pos->file,i)); + error=1; + } + } + if (pos) + { + DBUG_PRINT("error",("File_blocks %d has recursive link",i)); + error=1; + } + } + if (changed != 0) + { + DBUG_PRINT("error",("Found %d blocks that wasn't in changed blocks", + changed)); + error=1; + } + if (error) + DBUG_PRINT("error",("Found error at %s",where)); + if (lock) + pthread_mutex_unlock(&THR_LOCK_keycache); + return; +} /* test_key_cache */ +#endif diff --git a/mysys/mf_loadpath.c b/mysys/mf_loadpath.c new file mode 100644 index 00000000000..641528b8b5d --- /dev/null +++ b/mysys/mf_loadpath.c @@ -0,0 +1,54 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include <m_string.h> + + /* Returns full load-path for a file. to may be = path */ + /* if path is a hard-path return path */ + /* if path starts with home-dir return path */ + /* if path starts with current dir or parent-dir unpack path */ + /* if there is no path, prepend with own_path_prefix if given */ + /* else unpack path according to current dir */ + +my_string my_load_path(my_string to, const char *path, + const char *own_path_prefix) +{ + char buff[FN_REFLEN]; + DBUG_ENTER("my_load_path"); + DBUG_PRINT("enter",("path: %s prefix: %s",path, + own_path_prefix ? own_path_prefix : "")); + + if ((path[0] == FN_HOMELIB && path[1] == FN_LIBCHAR) || + test_if_hard_path(path)) + VOID(strmov(buff,path)); + else if ((path[0] == FN_CURLIB && path[1] == FN_LIBCHAR) || + (is_prefix((gptr) path,FN_PARENTDIR) && + path[strlen(FN_PARENTDIR)] == FN_LIBCHAR) || + ! own_path_prefix) + { + if (! my_getwd(buff,(uint) (FN_REFLEN-strlen(path)),MYF(0))) + VOID(strcat(buff,path)); + else + VOID(strmov(buff,path)); + } + else + VOID(strxmov(buff,own_path_prefix,path,NullS)); + strmov(to,buff); + DBUG_PRINT("exit",("to: %s",to)); + DBUG_RETURN(to); +} /* my_load_path */ diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c new file mode 100644 index 00000000000..8aff6a3484a --- /dev/null +++ b/mysys/mf_pack.c @@ -0,0 +1,528 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include <m_string.h> +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif +#ifdef VMS +#include <rms.h> +#include <iodef.h> +#include <descrip.h> +#endif /* VMS */ + +static my_string NEAR_F expand_tilde(my_string *path); + + /* Pack a dirname ; Changes HOME to ~/ and current dev to ./ */ + /* from is a dirname (from dirname() ?) ending with FN_LIBCHAR */ + +void pack_dirname(my_string to, const char *from) + + /* to may be == from */ +{ + int cwd_err; + uint d_length,length,buff_length; + my_string start; + char buff[FN_REFLEN]; + DBUG_ENTER("pack_dirname"); + + (void) intern_filename(to,from); /* Change to intern name */ + +#ifdef FN_DEVCHAR + if ((start=strrchr(to,FN_DEVCHAR)) != 0) /* Skipp device part */ + start++; + else +#endif + start=to; + + LINT_INIT(buff_length); + if (!(cwd_err= my_getwd(buff,FN_REFLEN,MYF(0)))) + { + buff_length=strlen(buff); + d_length=(uint) (start-to); + if ((start == to || + (buff_length == d_length && !bcmp(buff,start,d_length))) && + *start != FN_LIBCHAR && *start) + { /* Put current dir before */ + bchange(to,d_length,buff,buff_length,strlen(to)+1); + } + } + + if ((d_length= cleanup_dirname(to,to)) != 0) + { + length=0; + if (home_dir) + { + length=strlen(home_dir); + if (home_dir[length-1] == FN_LIBCHAR) + length--; /* Don't test last '/' */ + } + if (length > 1 && length < d_length) + { /* test if /xx/yy -> ~/yy */ + if (bcmp(to,home_dir,length) == 0 && to[length] == FN_LIBCHAR) + { + to[0]=FN_HOMELIB; /* Filename begins with ~ */ + (void) strmov_overlapp(to+1,to+length); + } + } + if (! cwd_err) + { /* Test if cwd is ~/... */ + if (length > 1 && length < buff_length) + { + if (bcmp(buff,home_dir,length) == 0 && buff[length] == FN_LIBCHAR) + { + buff[0]=FN_HOMELIB; + (void) strmov_overlapp(buff+1,buff+length); + } + } + if (is_prefix(to,buff)) + { + length=strlen(buff); + if (to[length]) + (void) strmov_overlapp(to,to+length); /* Remove everything before */ + else + { + to[0]= FN_CURLIB; /* Put ./ instead of cwd */ + to[1]= FN_LIBCHAR; + to[2]= '\0'; + } + } + } + } + DBUG_PRINT("exit",("to: '%s'",to)); + DBUG_VOID_RETURN; +} /* pack_dirname */ + + + /* remove unwanted chars from dirname */ + /* if "/../" removes prev dir; "/~/" removes all before ~ */ + /* "//" is same as "/", except on Win32 at start of a file */ + /* "/./" is removed */ + /* Unpacks home_dir if "~/.." used */ + /* Unpacks current dir if if "./.." used */ + +uint cleanup_dirname(register my_string to, const char *from) + /* to may be == from */ + +{ + reg5 uint length; + reg2 my_string pos; + reg3 my_string from_ptr; + reg4 my_string start; + char parent[5], /* for "FN_PARENTDIR" */ + buff[FN_REFLEN+1],*end_parentdir; + DBUG_ENTER("cleanup_dirname"); + DBUG_PRINT("enter",("from: '%s'",from)); + + start=buff; + from_ptr=(my_string) from; +#ifdef FN_DEVCHAR + if ((pos=strrchr(from_ptr,FN_DEVCHAR)) != 0) + { /* Skipp device part */ + length=(uint) (pos-from_ptr)+1; + start=strnmov(buff,from_ptr,length); from_ptr+=length; + } +#endif + + parent[0]=FN_LIBCHAR; + length=(uint) (strmov(parent+1,FN_PARENTDIR)-parent); + for (pos=start ; (*pos= *from_ptr++) != 0 ; pos++) + { + if (*pos == '/') + *pos = FN_LIBCHAR; + if (*pos == FN_LIBCHAR) + { + if ((uint) (pos-start) > length && bcmp(pos-length,parent,length) == 0) + { /* If .../../; skipp prev */ + pos-=length; + if (pos != start) + { /* not /../ */ + pos--; + if (*pos == FN_HOMELIB && (pos == start || pos[-1] == FN_LIBCHAR)) + { + if (!home_dir) + { + pos+=length+1; /* Don't unpack ~/.. */ + continue; + } + pos=strmov(buff,home_dir)-1; /* Unpacks ~/.. */ + if (*pos == FN_LIBCHAR) + pos--; /* home ended with '/' */ + } + if (*pos == FN_CURLIB && (pos == start || pos[-1] == FN_LIBCHAR)) + { + if (my_getwd(curr_dir,FN_REFLEN,MYF(0))) + { + pos+=length+1; /* Don't unpack ./.. */ + continue; + } + pos=strmov(buff,curr_dir)-1; /* Unpacks ./.. */ + if (*pos == FN_LIBCHAR) + pos--; /* home ended with '/' */ + } + end_parentdir=pos; + while (pos >= start && *pos != FN_LIBCHAR) /* remove prev dir */ + pos--; + if (pos[1] == FN_HOMELIB || bcmp(pos,parent,length) == 0) + { /* Don't remove ~user/ */ + pos=strmov(end_parentdir+1,parent); + *pos=FN_LIBCHAR; + continue; + } + } + } + else if ((uint) (pos-start) == length-1 && + !bcmp(start,parent+1,length-1)) + start=pos; /* Starts with "../" */ + else if (pos-start > 0 && pos[-1] == FN_LIBCHAR) + { +#ifdef FN_NETWORK_DRIVES + if (pos-start != 1) +#endif + pos--; /* Remove dupplicate '/' */ + } + else if (pos-start > 1 && pos[-1] == FN_CURLIB && pos[-2] == FN_LIBCHAR) + pos-=2; /* Skipp /./ */ + else if (pos > buff+1 && pos[-1] == FN_HOMELIB && pos[-2] == FN_LIBCHAR) + { /* Found ..../~/ */ + buff[0]=FN_HOMELIB; + buff[1]=FN_LIBCHAR; + start=buff; pos=buff+1; + } + } + } + (void) strmov(to,buff); + DBUG_PRINT("exit",("to: '%s'",to)); + DBUG_RETURN((uint) (pos-buff)); +} /* cleanup_dirname */ + + + /* + On system where you don't have symbolic links, the following + code will allow you to create a file: + directory-name.lnk that should contain the real path + to the directory. This will be used if the directory name + doesn't exists + */ + + +my_bool my_use_symdir=0; /* Set this if you want to use symdirs */ + +#ifdef USE_SYMDIR +void symdirget(char *dir) +{ + char buff[FN_REFLEN]; + char *pos=strend(dir); + if (dir[0] && pos[-1] != FN_DEVCHAR && access(dir, F_OK)) + { + FILE *fp; + char temp= *(--pos); /* May be "/" or "\" */ + strmov(pos,".sym"); + fp = my_fopen(dir, O_RDONLY,MYF(0)); + *pos++=temp; *pos=0; /* Restore old filename */ + if (fp) + { + if (fgets(buff, sizeof(buff), fp)) + { + for (pos=strend(buff); + pos > buff && (iscntrl(pos[-1]) || isspace(pos[-1])) ; + pos --); + strmake(dir,buff, (uint) (pos-buff)); + } + my_fclose(fp,MYF(0)); + } + } +} +#endif /* USE_SYMDIR */ + + /* Unpacks dirname to name that can be used by open... */ + /* Make that last char of to is '/' if from not empty and + from doesn't end in FN_DEVCHAR */ + /* Uses cleanup_dirname and changes ~/.. to home_dir/.. */ + /* Returns length of new directory */ + +uint unpack_dirname(my_string to, const char *from) + + /* to may be == from */ +{ + uint length,h_length; + char buff[FN_REFLEN+1+4],*suffix,*tilde_expansion; + DBUG_ENTER("unpack_dirname"); + + (void) intern_filename(buff,from); /* Change to intern name */ + length=strlen(buff); /* Fix that '/' is last */ + if (length && +#ifdef FN_DEVCHAR + buff[length-1] != FN_DEVCHAR && +#endif + buff[length-1] != FN_LIBCHAR && buff[length-1] != '/') + { + buff[length]=FN_LIBCHAR; + buff[length+1]= '\0'; + } + + length=cleanup_dirname(buff,buff); + if (buff[0] == FN_HOMELIB) + { + suffix=buff+1; tilde_expansion=expand_tilde(&suffix); + if (tilde_expansion) + { + length-=(uint) (suffix-buff)-1; + if (length+(h_length=strlen(tilde_expansion)) <= FN_REFLEN) + { + if (tilde_expansion[h_length-1] == FN_LIBCHAR) + h_length--; + if (buff+h_length < suffix) + bmove(buff+h_length,suffix,length); + else + bmove_upp(buff+h_length+length,suffix+length,length); + bmove(buff,tilde_expansion,h_length); + } + } + } +#ifdef USE_SYMDIR + if (my_use_symdir) + symdirget(buff); +#endif + DBUG_RETURN(system_filename(to,buff)); /* Fix for open */ +} /* unpack_dirname */ + + + /* Expand tilde to home or user-directory */ + /* Path is reset to point at FN_LIBCHAR after ~xxx */ + +static my_string NEAR_F expand_tilde(my_string *path) +{ + if (path[0][0] == FN_LIBCHAR) + return home_dir; /* ~/ expanded to home */ +#ifdef HAVE_GETPWNAM + { + char *str,save; + struct passwd *user_entry; + + if (!(str=strchr(*path,FN_LIBCHAR))) + str=strend(*path); + save= *str; *str= '\0'; + user_entry=getpwnam(*path); + *str=save; + endpwent(); + if (user_entry) + { + *path=str; + return user_entry->pw_dir; + } + } +#endif + return (my_string) 0; +} + + /* fix filename so it can be used by open, create .. */ + /* to may be == from */ + /* Returns to */ + +my_string unpack_filename(my_string to, const char *from) +{ + uint length,n_length; + char buff[FN_REFLEN]; + DBUG_ENTER("unpack_filename"); + + length=dirname_part(buff,from); /* copy & convert dirname */ + n_length=unpack_dirname(buff,buff); + if (n_length+strlen(from+length) < FN_REFLEN) + { + (void) strmov(buff+n_length,from+length); + (void) system_filename(to,buff); /* Fix to usably filename */ + } + else + (void) system_filename(to,from); /* Fix to usably filename */ + DBUG_RETURN(to); +} /* unpack_filename */ + + + /* Convert filename (unix standard) to system standard */ + /* Used before system command's like open(), create() .. */ + /* Returns to */ + +uint system_filename(my_string to, const char *from) +{ +#ifndef FN_C_BEFORE_DIR + return (uint) (strmake(to,from,FN_REFLEN-1)-to); +#else /* VMS */ + + /* change 'dev:lib/xxx' to 'dev:[lib]xxx' */ + /* change 'dev:xxx' to 'dev:xxx' */ + /* change './xxx' to 'xxx' */ + /* change './lib/' or lib/ to '[.lib]' */ + /* change '/x/y/z to '[x.y]x' */ + /* change 'dev:/x' to 'dev:[000000]x' */ + + int libchar_found,length; + my_string to_pos,from_pos,pos; + char buff[FN_REFLEN]; + DBUG_ENTER("system_filename"); + + libchar_found=0; + (void) strmov(buff,from); /* If to == from */ + from_pos= buff; + if ((pos=strrchr(from_pos,FN_DEVCHAR))) /* Skipp device part */ + { + pos++; + to_pos=strnmov(to,from_pos,(size_s) (pos-from_pos)); + from_pos=pos; + } + else + to_pos=to; + + if (from_pos[0] == FN_CURLIB && from_pos[1] == FN_LIBCHAR) + from_pos+=2; /* Skipp './' */ + if (strchr(from_pos,FN_LIBCHAR)) + { + *(to_pos++) = FN_C_BEFORE_DIR; + if (strinstr(from_pos,FN_ROOTDIR) == 1) + { + from_pos+=strlen(FN_ROOTDIR); /* Actually +1 but... */ + if (! strchr(from_pos,FN_LIBCHAR)) + { /* No dir, use [000000] */ + to_pos=strmov(to_pos,FN_C_ROOT_DIR); + libchar_found++; + } + } + else + *(to_pos++)=FN_C_DIR_SEP; /* '.' gives current dir */ + + while ((pos=strchr(from_pos,FN_LIBCHAR))) + { + if (libchar_found++) + *(to_pos++)=FN_C_DIR_SEP; /* Add '.' between dirs */ + if (strinstr(from_pos,FN_PARENTDIR) == 1 && + from_pos+strlen(FN_PARENTDIR) == pos) + to_pos=strmov(to_pos,FN_C_PARENT_DIR); /* Found '../' */ + else + to_pos=strnmov(to_pos,from_pos,(size_s) (pos-from_pos)); + from_pos=pos+1; + } + *(to_pos++)=FN_C_AFTER_DIR; + } + length=(int) (strmov(to_pos,from_pos)-to); + DBUG_PRINT("exit",("name: '%s'",to)); + DBUG_RETURN((uint) length); +#endif +} /* system_filename */ + + + /* Fix a filename to intern (UNIX format) */ + +my_string intern_filename(my_string to, const char *from) +{ +#ifndef VMS + { + uint length; + char buff[FN_REFLEN]; + if (from == to) + { /* Dirname may destroy from */ + strmov(buff,from); + from=buff; + } + length=dirname_part(to,from); /* Copy dirname & fix chars */ + (void) strcat(to,from+length); + return (to); + } +#else /* VMS */ + + /* change 'dev:[lib]xxx' to 'dev:lib/xxx' */ + /* change 'dev:xxx' to 'dev:xxx' */ + /* change 'dev:x/y/[.lib]' to 'dev:x/y/lib/ */ + /* change '[.lib]' to './lib/' */ + /* change '[x.y]' or '[x.][y]' or '[x][.y]' to '/x/y/' */ + /* change '[000000.x] or [x.000000]' to '/x/' */ + + int par_length,root_length; + my_string pos,from_pos,to_pos,end_pos; + char buff[FN_REFLEN]; + + (void) strmov(buff,from); + convert_dirname(buff); /* change '<>' to '[]' */ + from_pos=buff; + if ((pos=strrchr(from_pos,FN_DEVCHAR))) /* Skipp device part */ + { + pos++; + to_pos=strnmov(to,from_pos,(size_s) (pos-from_pos)); + from_pos=pos; + } + else + to_pos=to; + + root_length=strlen(FN_C_ROOT_DIR); + if ((pos = strchr(from_pos,FN_C_BEFORE_DIR)) && + (end_pos = strrchr(pos+1,FN_C_AFTER_DIR))) + { + to_pos=strnmov(to_pos,from_pos,(size_s) (pos-from_pos)); + /* Copy all between ':' and '[' */ + from_pos=pos+1; + if (strinstr(from_pos,FN_C_ROOT_DIR) == 1 && + (from_pos[root_length] == FN_C_DIR_SEP || + from_pos[root_length] == FN_C_AFTER_DIR)) + { + from_pos+=root_length+1; + } + else if (*from_pos == FN_C_DIR_SEP) + *(to_pos++) = FN_CURLIB; /* Set ./ first */ + *(to_pos++) = FN_LIBCHAR; + + par_length=strlen(FN_C_PARENT_DIR); + pos=to_pos; + for (; from_pos <= end_pos ; from_pos++) + { + switch (*from_pos) { + case FN_C_DIR_SEP: + case FN_C_AFTER_DIR: + if (pos != to_pos) + { + if ((int) (to_pos-pos) == root_length && + is_suffix(pos,FN_C_ROOT_DIR)) + to_pos=pos; /* remove root-pos */ + else + { + *(to_pos++)=FN_LIBCHAR; /* Find lib */ + pos=to_pos; + } + } + break; + case FN_C_BEFORE_DIR: + break; + case '-': /* *(FN_C_PARENT_DIR): */ + if (to_pos[-1] == FN_LIBCHAR && + strncmp(from_pos,FN_C_PARENT_DIR,par_length) == 0) + { /* Change '-' to '..' */ + to_pos=strmov(to_pos,FN_PARENTDIR); + *(to_pos++)=FN_LIBCHAR; + pos=to_pos; + from_pos+=par_length-1; + break; + } + /* Fall through */ + default: + *(to_pos++)= *from_pos; + break; + } + } + } + (void) strmov(to_pos,from_pos); + return (to); +#endif /* VMS */ +} /* intern_filename */ diff --git a/mysys/mf_pack2.c b/mysys/mf_pack2.c new file mode 100644 index 00000000000..1cda7797457 --- /dev/null +++ b/mysys/mf_pack2.c @@ -0,0 +1,53 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include <m_string.h> + + /* Pack a filename for output on screen */ + /* Changes long paths to .../ */ + /* Removes pathname and extension */ + /* If not possibly to pack returns '?' in to and returns 1*/ + +int pack_filename(my_string to, const char *name, size_s max_length) + /* to may be name */ + +{ + int i; + char buff[FN_REFLEN]; + + if (strlen(fn_format(to,name,"","",0)) <= max_length) + return 0; + if (strlen(fn_format(to,name,"","",8)) <= max_length) + return 0; + if (strlen(fn_format(buff,name,".../","",1)) <= max_length) + { + VOID(strmov(to,buff)); + return 0; + } + for (i= 0 ; i < 3 ; i++) + { + if (strlen(fn_format(buff,to,"","", i == 0 ? 2 : i == 1 ? 1 : 3 )) + <= max_length) + { + VOID(strmov(to,buff)); + return 0; + } + } + to[0]='?'; to[1]=0; /* Can't pack filename */ + return 1; +} /* pack_filename */ diff --git a/mysys/mf_path.c b/mysys/mf_path.c new file mode 100644 index 00000000000..0a0a760cea1 --- /dev/null +++ b/mysys/mf_path.c @@ -0,0 +1,120 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include <m_string.h> + +static char *find_file_in_path(char *to,const char *name); + + /* Finds where program can find it's files. + pre_pathname is found by first locking at progname (argv[0]). + if progname contains path the path is returned. + else if progname is found in path, return it + else if progname is given and POSIX environment variable "_" is set + then path is taken from "_". + If filename doesn't contain a path append MY_BASEDIR_VERSION or + MY_BASEDIR if defined, else append "/my/running". + own_path_name_part is concatinated to result. + my_path puts result in to and returns to */ + +my_string my_path(my_string to, const char *progname, + const char *own_pathname_part) +{ + my_string start,end,prog; + DBUG_ENTER("my_path"); + + start=to; /* Return this */ + if (progname && (dirname_part(to, progname) || + find_file_in_path(to,progname) || + ((prog=getenv("_")) != 0 && dirname_part(to,prog)))) + { + VOID(intern_filename(to,to)); + if (!test_if_hard_path(to)) + { + if (!my_getwd(curr_dir,FN_REFLEN,MYF(0))) + bchange(to,0,curr_dir,strlen(curr_dir),strlen(to)+1); + } + } + else + { + if ((end = getenv("MY_BASEDIR_VERSION")) == 0 && + (end = getenv("MY_BASEDIR")) == 0) + { +#ifdef DEFAULT_BASEDIR + end= (char*) DEFAULT_BASEDIR; +#else + end= (char*) "/my/"; +#endif + } + VOID(intern_filename(to,end)); + to=strend(to); + if (to != start && to[-1] != FN_LIBCHAR) + *to++ = FN_LIBCHAR; + VOID(strmov(to,own_pathname_part)); + } + DBUG_PRINT("exit",("to: '%s'",start)); + DBUG_RETURN(start); +} /* my_path */ + + + /* test if file without filename is found in path */ + /* Returns to if found and to has dirpart if found, else NullS */ + +#if defined(MSDOS) || defined(__WIN__) +#define F_OK 0 +#define PATH_SEP ';' +#define PROGRAM_EXTENSION ".exe" +#else +#define PATH_SEP ':' +#endif + +static char *find_file_in_path(char *to, const char *name) +{ + char *path,*pos,dir[2]; + const char *ext=""; + + if (!(path=getenv("PATH"))) + return NullS; + dir[0]=FN_LIBCHAR; dir[1]=0; +#ifdef PROGRAM_EXTENSION + if (!fn_ext(name)[0]) + ext=PROGRAM_EXTENSION; +#endif + + for (pos=path ; (pos=strchr(pos,PATH_SEP)) ; path= ++pos) + { + if (path != pos) + { + strxmov(strnmov(to,path,(uint) (pos-path)),dir,name,ext,NullS); + if (!access(to,F_OK)) + { + to[(uint) (pos-path)+1]=0; /* Return path only */ + return to; + } + } + } +#ifdef __WIN__ + to[0]=FN_CURLIB; + strxmov(to+1,dir,name,ext,NullS); + if (!access(to,F_OK)) /* Test in current dir */ + { + to[2]=0; /* Leave ".\" */ + return to; + } +#endif + return NullS; /* File not found */ +} diff --git a/mysys/mf_qsort.c b/mysys/mf_qsort.c new file mode 100644 index 00000000000..15fa5638639 --- /dev/null +++ b/mysys/mf_qsort.c @@ -0,0 +1,258 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Plug-compatible replacement for UNIX qsort. + Copyright (C) 1989 Free Software Foundation, Inc. + Written by Douglas C. Schmidt (schmidt@ics.uci.edu) + Optimized and modyfied for mysys by monty. + +This file is part of GNU CC. + +GNU QSORT is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 1, or (at your option) +any later version. + +GNU QSORT is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU QSORT; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "mysys_priv.h" +#if !defined(HAVE_purify) || defined(QSORT_EXTRA_CMP_ARGUMENT) + +/* Envoke the comparison function, returns either 0, < 0, or > 0. */ +#ifdef QSORT_EXTRA_CMP_ARGUMENT +#define CMP(A,B) ((*cmp)(cmp_argument,(A),(B))) +#else +#define CMP(A,B) ((*cmp)((A),(B))) +#endif + +/* Byte-wise swap two items of size SIZE. */ +#define SWAP(A,B,SIZE) do {int sz=(int)(SIZE); char *a = (A); char *b = (B); \ + do { char _temp = *a;*a++ = *b;*b++ = _temp;} while (--sz);} while (0) + +/* Copy SIZE bytes from item B to item A. */ +#define COPY(A,B,SIZE) {int sz = (int) (SIZE); do { *(A)++ = *(B)++; } while (--sz); } + +/* This should be replaced by a standard ANSI macro. */ +#define BYTES_PER_WORD 8 + +/* The next 4 #defines implement a very fast in-line stack abstraction. */ +#define STACK_SIZE (BYTES_PER_WORD * sizeof (long)) +#define PUSH(LOW,HIGH) do {top->lo = LOW;top++->hi = HIGH;} while (0) +#define POP(LOW,HIGH) do {LOW = (--top)->lo;HIGH = top->hi;} while (0) +#define STACK_NOT_EMPTY (stack < top) + +/* Discontinue quicksort algorithm when partition gets below this size. + This particular magic number was chosen to work best on a Sparc SLC. */ +#define MAX_THRESH 12 + +/* Stack node declarations used to store unfulfilled partition obligations. */ +typedef struct +{ + char *lo; + char *hi; +} stack_node; + +/* Order size using quicksort. This implementation incorporates + four optimizations discussed in Sedgewick: + + 1. Non-recursive, using an explicit stack of pointer that store the + next array partition to sort. To save time, this maximum amount + of space required to store an array of MAX_INT is allocated on the + stack. Assuming a 32-bit integer, this needs only 32 * + sizeof (stack_node) == 136 bits. Pretty cheap, actually. + + 2. Chose the pivot element using a median-of-three decision tree. + This reduces the probability of selecting a bad pivot value and + eliminates certain extraneous comparisons. + + 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving + insertion sort to order the MAX_THRESH items within each partition. + This is a big win, since insertion sort is faster for small, mostly + sorted array segements. + + 4. The larger of the two sub-partitions is always pushed onto the + stack first, with the algorithm then concentrating on the + smaller partition. This *guarantees* no more than log (n) + stack size is needed (actually O(1) in this case)! */ + +#if defined(QSORT_TYPE_IS_VOID) +#define SORT_RETURN return +#else +#define SORT_RETURN return 0 +#endif + +#ifdef QSORT_EXTRA_CMP_ARGUMENT +qsort_t qsort2(void *base_ptr, size_t total_elems, size_t size, qsort2_cmp cmp, + void *cmp_argument) +#else +qsort_t qsort(void *base_ptr, size_t total_elems, size_t size, qsort_cmp cmp) +#endif +{ + /* Allocating SIZE bytes for a pivot buffer facilitates a better + algorithm below since we can do comparisons directly on the pivot. + */ + int max_thresh = (int) (MAX_THRESH * size); + if (total_elems <= 1) + SORT_RETURN; /* Crashes on MSDOS if continues */ + + if (total_elems > MAX_THRESH) + { + char *lo = base_ptr; + char *hi = lo + size * (total_elems - 1); + stack_node stack[STACK_SIZE]; /* Largest size needed for 32-bit int!!! */ + stack_node *top = stack + 1; + char *pivot_buffer = (char *) my_alloca ((int) size); + + while (STACK_NOT_EMPTY) + { + char *left_ptr; + char *right_ptr; + { + char *pivot = pivot_buffer; + { + /* Select median value from among LO, MID, and HI. Rearrange + LO and HI so the three values are sorted. This lowers the + probability of picking a pathological pivot value and + skips a comparison for both the LEFT_PTR and RIGHT_PTR. */ + + char *mid = lo + size * (((uint) (hi - lo) / (uint) size) >> 1); + + if (CMP(hi,lo) < 0) + SWAP (hi, lo, size); + if (CMP (mid, lo) < 0) + SWAP (mid, lo, size); + else if (CMP (hi, mid) < 0) + SWAP (mid, hi, size); + COPY (pivot, mid, size); + pivot = pivot_buffer; + } + left_ptr = lo + size; + right_ptr = hi - size; + + /* Here's the famous ``collapse the walls'' section of quicksort. + Gotta like those tight inner loops! They are the main reason + that this algorithm runs much faster than others. */ + do + { + while (CMP (left_ptr, pivot) < 0) + left_ptr += size; + + while (CMP (pivot, right_ptr) < 0) + right_ptr -= size; + + if (left_ptr < right_ptr) + { + SWAP (left_ptr, right_ptr, size); + left_ptr += size; + right_ptr -= size; + } + else if (left_ptr == right_ptr) + { + left_ptr += size; + right_ptr -= size; + break; + } + } + while (left_ptr <= right_ptr); + } + + /* Set up pointers for next iteration. First determine whether + left and right partitions are below the threshold size. If so, + ignore one or both. Otherwise, push the larger partition's + bounds on the stack and continue sorting the smaller one. */ + + if ((right_ptr - lo) <= max_thresh) + { + if ((hi - left_ptr) <= max_thresh) /* Ignore both small parts. */ + POP (lo, hi); + else /* Ignore small left part. */ + lo = left_ptr; + } + else if ((hi - left_ptr) <= max_thresh) /* Ignore small right part. */ + hi = right_ptr; + else if ((right_ptr - lo) > (hi - left_ptr)) /* Push larger left part */ + { + PUSH (lo, right_ptr); + lo = left_ptr; + } + else /* Push larger right part */ + { + PUSH (left_ptr, hi); + hi = right_ptr; + } + } + my_afree(pivot_buffer); + } + + /* Once the BASE_PTR array is partially sorted by quicksort the rest + is completely sorted using insertion sort, since this is efficient + for partitions below MAX_THRESH size. BASE_PTR points to the beginning + of the array to sort, and END_PTR points at the very last element in + the array (*not* one beyond it!). */ + + { + char *end_ptr = (char*) base_ptr + size * (total_elems - 1); + char *run_ptr; + char *tmp_ptr = (char*) base_ptr; + char *thresh = min (end_ptr, (char*) base_ptr + max_thresh); + + /* Find smallest element in first threshold and place it at the + array's beginning. This is the smallest array element, + and the operation speeds up insertion sort's inner loop. */ + + for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size) + if (CMP (run_ptr, tmp_ptr) < 0) + tmp_ptr = run_ptr; + + if (tmp_ptr != (char*) base_ptr) + SWAP (tmp_ptr, (char*) base_ptr, size); + + /* Insertion sort, running from left-hand-side up to `right-hand-side.' + Pretty much straight out of the original GNU qsort routine. */ + + for (run_ptr = (char*) base_ptr + size; + (tmp_ptr = run_ptr += size) <= end_ptr; ) + { + while (CMP (run_ptr, tmp_ptr -= size) < 0) ; + + if ((tmp_ptr += size) != run_ptr) + { + char *trav; + + for (trav = run_ptr + size; --trav >= run_ptr;) + { + char c = *trav; + char *hi, *lo; + + for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo) + *hi = *lo; + *hi = c; + } + } + + } + } + SORT_RETURN; +} +#endif /* HAVE_purify */ diff --git a/mysys/mf_qsort2.c b/mysys/mf_qsort2.c new file mode 100644 index 00000000000..7b1ca4e39ab --- /dev/null +++ b/mysys/mf_qsort2.c @@ -0,0 +1,21 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* qsort that sends one extra argument to the compare subrutine */ + +#define QSORT_EXTRA_CMP_ARGUMENT +#include "mf_qsort.c" diff --git a/mysys/mf_radix.c b/mysys/mf_radix.c new file mode 100644 index 00000000000..99aa4d0b073 --- /dev/null +++ b/mysys/mf_radix.c @@ -0,0 +1,56 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* + Radixsort for pointers to fixed length strings. + A very quick sort for not to long (< 20 char) strings. + Neads a extra buffers of number_of_elements pointers but is + 2-3 times faster than quicksort +*/ + +#include "mysys_priv.h" +#include <m_string.h> + + /* Radixsort */ + +void radixsort_for_str_ptr(uchar **base, uint number_of_elements, size_s size_of_element, uchar **buffer) +{ + uchar **end,**ptr,**buffer_ptr; + uint32 *count_ptr,*count_end,count[256]; + int pass; + + end=base+number_of_elements; count_end=count+256; + for (pass=(int) size_of_element-1 ; pass >= 0 ; pass--) + { + bzero((gptr) count,sizeof(uint32)*256); + for (ptr= base ; ptr < end ; ptr++) + count[ptr[0][pass]]++; + if (count[0] == number_of_elements) + goto next; + for (count_ptr=count+1 ; count_ptr < count_end ; count_ptr++) + { + if (*count_ptr == number_of_elements) + goto next; + (*count_ptr)+= *(count_ptr-1); + } + for (ptr= end ; ptr-- != base ;) + buffer[--count[ptr[0][pass]]]= *ptr; + for (ptr=base, buffer_ptr=buffer ; ptr < end ;) + (*ptr++) = *buffer_ptr++; + next:; + } +} diff --git a/mysys/mf_same.c b/mysys/mf_same.c new file mode 100644 index 00000000000..5b8c5ecf970 --- /dev/null +++ b/mysys/mf_same.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Kopierar biblioteksstrukturen och extensionen fr}n ett filnamn */ + +#include "mysys_priv.h" +#include <m_string.h> + + /* Formaterar ett filnamn i avsende p} ett annat namn */ + /* Klarar {ven to = name */ + /* Denna funktion r|r inte p} utg}ngsnamnet */ + +my_string fn_same(my_string toname, const char *name, int flag) +{ + char dev[FN_REFLEN]; + const char *ext; + DBUG_ENTER("fn_same"); + DBUG_PRINT("mfunkt",("to: %s name: %s flag: %d",toname,name,flag)); + + if ((ext=strrchr(name+dirname_part(dev,name),FN_EXTCHAR)) == 0) + ext=""; + + DBUG_RETURN(fn_format(toname,toname,dev,ext,flag)); +} /* fn_same */ diff --git a/mysys/mf_sleep.c b/mysys/mf_sleep.c new file mode 100644 index 00000000000..f33a904cf5a --- /dev/null +++ b/mysys/mf_sleep.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Wait a given time (On systems that dont have sleep !!; MSDOS) */ + +#include "mysys_priv.h" +#include <m_string.h> + +#ifdef _MSC_VER + +void sleep(sec) +int sec; +{ + ulong start; + DBUG_ENTER("sleep"); + + start=(ulong) time((time_t*) 0); + while ((ulong) time((time_t*) 0) < start+sec); + DBUG_VOID_RETURN; +} /* sleep */ + +#endif /* MSDOS */ diff --git a/mysys/mf_sort.c b/mysys/mf_sort.c new file mode 100644 index 00000000000..754a1deb1a7 --- /dev/null +++ b/mysys/mf_sort.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Sort of string pointers in string-order with radix or qsort */ + +#include "mysys_priv.h" +#include <m_string.h> + +void my_string_ptr_sort(void *base, uint items, size_s size) +{ +#if INT_MAX > 65536L + uchar **ptr=0; + + if (size <= 20 && items >= 1000 && + (ptr= (uchar**) my_malloc(items*sizeof(char*),MYF(0)))) + { + radixsort_for_str_ptr((uchar**) base,items,size,ptr); + my_free((gptr) ptr,MYF(0)); + } + else +#endif + { + if (size && items) + { + uint size_arg=size; + qsort2(base,items,sizeof(byte*),get_ptr_compare(size),(void*) &size_arg); + } + } +} diff --git a/mysys/mf_soundex.c b/mysys/mf_soundex.c new file mode 100644 index 00000000000..827385a1466 --- /dev/null +++ b/mysys/mf_soundex.c @@ -0,0 +1,102 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/**************************************************************** +* SOUNDEX ALGORITHM in C * +* * +* The basic Algorithm source is taken from EDN Nov. * +* 14, 1985 pg. 36. * +* * +* As a test Those in Illinois will find that the * +* first group of numbers in their drivers license * +* number is the soundex number for their last name. * +* * +* RHW PC-IBBS ID. #1230 * +* * +* As an extension if remove_garbage is set then all non- * +* alpha characters are skipped * +****************************************************************/ + +#include "mysys_priv.h" +#include <m_ctype.h> +#include "my_static.h" + +static char get_scode(char **ptr,pbool remove_garbage); + + /* outputed string is 4 byte long */ + /* out_pntr can be == in_pntr */ + +void soundex(register my_string out_pntr, my_string in_pntr, + pbool remove_garbage) +{ + char ch,last_ch; + reg3 my_string end; + + if (remove_garbage) + { + while (*in_pntr && isspace(*in_pntr)) /* Skipp pre-space */ + in_pntr++; + } + *out_pntr++ = toupper(*in_pntr); /* Copy first letter */ + last_ch = get_scode(&in_pntr,0); /* code of the first letter */ + /* for the first 'double-letter */ + /* check. */ + end=out_pntr+3; /* Loop on input letters until */ + /* end of input (null) or output */ + /* letter code count = 3 */ + + in_pntr++; + while (out_pntr < end && (ch = get_scode(&in_pntr,remove_garbage)) != 0) + { + in_pntr++; + if ((ch != '0') && (ch != last_ch)) /* if not skipped or double */ + { + *out_pntr++ = ch; /* letter, copy to output */ + } /* for next double-letter check */ + last_ch = ch; /* save code of last input letter */ + } + while (out_pntr < end) + *out_pntr++ = '0'; + *out_pntr=0; /* end string */ + return; +} /* soundex */ + + + /* + If alpha, map input letter to soundex code. + If not alpha and remove_garbage is set then skipp to next char + else return 0 + */ + +static char get_scode(char **ptr, pbool remove_garbage) +{ + uchar ch; + + if (remove_garbage) + { + while (**ptr && !isalpha(**ptr)) + (*ptr)++; + } + ch=toupper(**ptr); + if (ch < 'A' || ch > 'Z') + { + if (isalpha(ch)) /* If exetended alfa (country spec) */ + return '0'; /* threat as vokal */ + return 0; /* Can't map */ + } + return(soundex_map[ch-'A']); +} /* get_scode */ diff --git a/mysys/mf_stripp.c b/mysys/mf_stripp.c new file mode 100644 index 00000000000..6ebdce4cff6 --- /dev/null +++ b/mysys/mf_stripp.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* T|mmer en str{ng p{ slut_space */ + +#include "mysys_priv.h" + +/* + stripp_sp(my_string str) + Strips end-space from string and returns new length. +*/ + +size_s stripp_sp(register my_string str) +{ + reg2 my_string found; + reg3 my_string start; + + start=found=str; + + while (*str) + { + if (*str != ' ') + { + while (*++str && *str != ' ') {}; + if (!*str) + return (size_s) (str-start); /* Return stringlength */ + } + found=str; + while (*++str == ' ') {}; + } + *found= '\0'; /* Stripp at first space */ + return (size_s) (found-start); +} /* stripp_sp */ diff --git a/mysys/mf_unixpath.c b/mysys/mf_unixpath.c new file mode 100644 index 00000000000..6ae29f99136 --- /dev/null +++ b/mysys/mf_unixpath.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include <m_string.h> + + /* convert filename to unix style filename */ + /* If MSDOS converts '\' to '/' */ + +void to_unix_path(my_string to __attribute__((unused))) +{ +#if FN_LIBCHAR != '/' + { + to--; + while ((to=strchr(to+1,FN_LIBCHAR)) != 0) + *to='/'; + } +#endif +} diff --git a/mysys/mf_util.c b/mysys/mf_util.c new file mode 100644 index 00000000000..12af323680e --- /dev/null +++ b/mysys/mf_util.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Utilities with are missing on some systems */ + +#include "mysys_priv.h" +#ifdef __ZTC__ +#include <dos.h> +#endif + +#ifdef __ZTC__ + + /* On ZORTECH C we don't have a getpid() call */ + +int getpid(void) +{ + return (int) _psp; +} + +#ifndef M_IC80386 + + /* Define halloc and hfree in as in MSC */ + +void * __CDECL halloc(long count,size_t length) +{ + return (void*) MK_FP(dos_alloc((uint) ((count*length+15) >> 4)),0); +} + +void __CDECL hfree(void *ptr) +{ + dos_free(FP_SEG(ptr)); +} + +#endif /* M_IC80386 */ +#endif /* __ZTC__ */ diff --git a/mysys/mf_wcomp.c b/mysys/mf_wcomp.c new file mode 100644 index 00000000000..5f1ab9b813e --- /dev/null +++ b/mysys/mf_wcomp.c @@ -0,0 +1,68 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Funktions for comparing with wild-cards */ + +#include "mysys_priv.h" + + /* Test if a string is "comparable" to a wild-card string */ + /* returns 0 if the strings are "comparable" */ + +char wild_many='*'; +char wild_one='?'; +char wild_prefix=0; + +int wild_compare(register const char *str, register const char *wildstr) +{ + reg3 int flag; + DBUG_ENTER("wild_compare"); + + while (*wildstr) + { + while (*wildstr && *wildstr != wild_many && *wildstr != wild_one) + { + if (*wildstr == wild_prefix && wildstr[1]) + wildstr++; + if (*wildstr++ != *str++) DBUG_RETURN(1); + } + if (! *wildstr ) DBUG_RETURN (*str != 0); + if (*wildstr++ == wild_one) + { + if (! *str++) DBUG_RETURN (1); /* One char; skipp */ + } + else + { /* Found '*' */ + if (!*wildstr) DBUG_RETURN(0); /* '*' as last char: OK */ + flag=(*wildstr != wild_many && *wildstr != wild_one); + do + { + if (flag) + { + char cmp; + if ((cmp= *wildstr) == wild_prefix && wildstr[1]) + cmp=wildstr[1]; + while (*str && *str != cmp) + str++; + if (!*str) DBUG_RETURN (1); + } + if (wild_compare(str,wildstr) == 0) DBUG_RETURN (0); + } while (*str++ && wildstr[0] != wild_many); + DBUG_RETURN(1); + } + } + DBUG_RETURN (*str != '\0'); +} /* wild_compare */ diff --git a/mysys/mf_wfile.c b/mysys/mf_wfile.c new file mode 100644 index 00000000000..02e155d9936 --- /dev/null +++ b/mysys/mf_wfile.c @@ -0,0 +1,132 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Functions for finding files with wildcards */ + +/* + The following file-name-test is supported: + - "name [[,] name...] ; Matches any of used filenames. + Each name can have "*" and/or "?" + wild-cards. + - [wildspec [,]] !wildspec2 ; File that matches wildspec and not + wildspec2. +*/ + +#include "mysys_priv.h" +#include <m_string.h> + + /* Store wildcard-string in a easyer format */ + +WF_PACK *wf_comp(my_string str) +{ + uint ant; + int not_pos; + register my_string pos; + my_string buffer; + WF_PACK *ret; + DBUG_ENTER("wf_comp"); + + not_pos= -1; /* Skipp space and '!' in front */ + while (*str == ' ') + str++; + if (*str == '!') + { + not_pos=0; + while (*++str == ' ') {}; + } + if (*str == 0) /* Empty == everything */ + DBUG_RETURN((WF_PACK *) NULL); + + ant=1; /* Count filespecs */ + for (pos=str ; *pos ; pos++) + ant+= test(*pos == ' ' || *pos == ','); + +#ifdef FN_UPPER_CASE + caseup(str,(int) (pos-str)); +#endif +#ifdef FN_LOWER_CASE + casedn(str,(int) (pos-str)); +#endif + + if ((ret= (WF_PACK*) my_malloc((uint) ant*(sizeof(my_string*)+2)+ + sizeof(WF_PACK)+strlen(str)+1,MYF(MY_WME))) + == 0) + DBUG_RETURN((WF_PACK *) NULL); + ret->wild= (my_string*) (ret+1); + buffer= (my_string) (ret->wild+ant); + + ant=0; + for (pos=str ; *pos ; str= pos) + { + ret->wild[ant++]=buffer; + while (*pos != ' ' && *pos != ',' && *pos != '!' && *pos) + *buffer++ = *pos++; + + *buffer++ = '\0'; + while (*pos == ' ' || *pos == ',' || *pos == '!' ) + if (*pos++ == '!' && not_pos <0) + not_pos=(int) ant; + } + + ret->wilds=ant; + if (not_pos <0) + ret->not_pos=ant; + else + ret->not_pos=(uint) not_pos; + + DBUG_PRINT("exit",("antal: %d not_pos: %d",ret->wilds,ret->not_pos)); + DBUG_RETURN(ret); +} /* wf_comp */ + + + /* Test if a given filename is matched */ + +int wf_test(register WF_PACK *wf_pack, register const char *name) +{ + reg2 uint i; + reg3 uint not_pos; + DBUG_ENTER("wf_test"); + + if (! wf_pack || wf_pack->wilds == 0) + DBUG_RETURN(0); /* Everything goes */ + + not_pos=wf_pack->not_pos; + for (i=0 ; i < not_pos; i++) + if (wild_compare(name,wf_pack->wild[i]) == 0) + goto found; + if (i) + DBUG_RETURN(1); /* No-match */ + +found: +/* Test that it isn't in not-list */ + + for (i=not_pos ; i < wf_pack->wilds; i++) + if (wild_compare(name,wf_pack->wild[i]) == 0) + DBUG_RETURN(1); + DBUG_RETURN(0); +} /* wf_test */ + + + /* We need this because program don't know with malloc we used */ + +void wf_end(WF_PACK *buffer) +{ + DBUG_ENTER("wf_end"); + if (buffer) + my_free((gptr) buffer,MYF(0)); + DBUG_VOID_RETURN; +} /* wf_end */ diff --git a/mysys/mulalloc.c b/mysys/mulalloc.c new file mode 100644 index 00000000000..8a7ee312aa9 --- /dev/null +++ b/mysys/mulalloc.c @@ -0,0 +1,53 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + + /* Malloc many pointers at the same time */ + /* format myFlags,ptr,length,ptr,length ... until null ptr */ + +#include "mysys_priv.h" +#include <stdarg.h> + +gptr my_multi_malloc(myf myFlags, ...) +{ + va_list args; + char **ptr,*start,*res; + uint tot_length,length; + DBUG_ENTER("my_multi_malloc"); + + va_start(args,myFlags); + tot_length=0; + while ((ptr=va_arg(args, char **))) + { + length=va_arg(args,uint); + tot_length+=ALIGN_SIZE(length); + } + va_end(args); + + if (!(start=(char *) my_malloc(tot_length,myFlags))) + DBUG_RETURN(0); /* purecov: inspected */ + + va_start(args,myFlags); + res=start; + while ((ptr=va_arg(args, char **))) + { + *ptr=res; + length=va_arg(args,uint); + res+=ALIGN_SIZE(length); + } + va_end(args); + DBUG_RETURN((gptr) start); +} diff --git a/mysys/my_alarm.c b/mysys/my_alarm.c new file mode 100644 index 00000000000..aab01ad77f4 --- /dev/null +++ b/mysys/my_alarm.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Function to set a varible when we got a alarm */ +/* Used by my_lock samt functions in m_alarm.h */ + + +#include "mysys_priv.h" +#include "my_alarm.h" + +#ifdef HAVE_ALARM + + /* ARGSUSED */ +sig_handler my_set_alarm_variable(int signo __attribute__((unused))) +{ + my_have_got_alarm=1; /* Tell program that time expired */ + return; +} + +#endif /* HAVE_ALARM */ diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c new file mode 100644 index 00000000000..693ffbfab78 --- /dev/null +++ b/mysys/my_alloc.c @@ -0,0 +1,129 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Routines to handle mallocing of results which will be freed the same time */ + +#include <global.h> +#include <my_sys.h> +#include <m_string.h> + +void init_alloc_root(MEM_ROOT *mem_root,uint block_size) +{ + mem_root->free=mem_root->used=0; + mem_root->min_malloc=16; + mem_root->block_size=block_size-MALLOC_OVERHEAD-sizeof(USED_MEM)-8; + mem_root->error_handler=0; +} + +gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size) +{ +#if defined(HAVE_purify) && defined(EXTRA_DEBUG) + reg1 USED_MEM *next; + Size+=ALIGN_SIZE(sizeof(USED_MEM)); + + if (!(next = (USED_MEM*) my_malloc(Size,MYF(MY_WME)))) + { + if (mem_root->error_handler) + (*mem_root->error_handler)(); + return((gptr) 0); /* purecov: inspected */ + } + next->next=mem_root->used; + mem_root->used=next; + return (gptr) (((char*) next)+ALIGN_SIZE(sizeof(USED_MEM))); +#else + uint get_size,max_left; + gptr point; + reg1 USED_MEM *next; + reg2 USED_MEM **prev; + + Size= ALIGN_SIZE(Size); + prev= &mem_root->free; + max_left=0; + for (next= *prev ; next && next->left < Size ; next= next->next) + { + if (next->left > max_left) + max_left=next->left; + prev= &next->next; + } + if (! next) + { /* Time to alloc new block */ + get_size= Size+ALIGN_SIZE(sizeof(USED_MEM)); + if (max_left*4 < mem_root->block_size && get_size < mem_root->block_size) + get_size=mem_root->block_size; /* Normal alloc */ + + if (!(next = (USED_MEM*) my_malloc(get_size,MYF(MY_WME)))) + { + if (mem_root->error_handler) + (*mem_root->error_handler)(); + return((gptr) 0); /* purecov: inspected */ + } + next->next= *prev; + next->size= get_size; + next->left= get_size-ALIGN_SIZE(sizeof(USED_MEM)); + *prev=next; + } + point= (gptr) ((char*) next+ (next->size-next->left)); + if ((next->left-= Size) < mem_root->min_malloc) + { /* Full block */ + *prev=next->next; /* Remove block from list */ + next->next=mem_root->used; + mem_root->used=next; + } + return(point); +#endif +} + + /* deallocate everything used by alloc_root */ + +void free_root(MEM_ROOT *root) +{ + reg1 USED_MEM *next,*old; + DBUG_ENTER("free_root"); + + if (!root) + DBUG_VOID_RETURN; /* purecov: inspected */ + for (next= root->used ; next ; ) + { + old=next; next= next->next ; + my_free((gptr) old,MYF(0)); + } + for (next= root->free ; next ; ) + { + old=next; next= next->next ; + my_free((gptr) old,MYF(0)); + } + root->used=root->free=0; + DBUG_VOID_RETURN; +} + +char *strdup_root(MEM_ROOT *root,const char *str) +{ + uint len=strlen(str)+1; + char *pos; + if ((pos=alloc_root(root,len))) + memcpy(pos,str,len); + return pos; +} + + +char *memdup_root(MEM_ROOT *root,const char *str,uint len) +{ + char *pos; + if ((pos=alloc_root(root,len))) + memcpy(pos,str,len); + return pos; +} diff --git a/mysys/my_append.c b/mysys/my_append.c new file mode 100644 index 00000000000..0d3296fb278 --- /dev/null +++ b/mysys/my_append.c @@ -0,0 +1,66 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#define USES_TYPES /* sys/types is included */ +#include "mysys_priv.h" +#include <sys/stat.h> +#include <m_string.h> +#if defined(HAVE_SYS_UTIME_H) +#include <sys/utime.h> +#elif defined(HAVE_UTIME_H) +#include <utime.h> +#elif !defined(HPUX) +struct utimbuf { + time_t actime; + time_t modtime; +}; +#endif + + /* Append a file to another */ + +int my_append(const char *from, const char *to, myf MyFlags) + + + /* Dont set MY_FNABP or MY_NABP bits on + when calling this funktion */ +{ + uint Count; + File from_file,to_file; + char buff[IO_SIZE]; + DBUG_ENTER("my_append"); + DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags)); + + from_file=to_file= -1; + + if ((from_file=my_open(from,O_RDONLY,MyFlags)) >= 0) + { + if ((to_file=my_open(to,O_APPEND | O_WRONLY,MyFlags)) >= 0) + { + while ((Count=my_read(from_file,buff,IO_SIZE,MyFlags)) != 0) + if (Count == (uint) -1 || + my_write(to_file,buff,Count,MYF(MyFlags | MY_NABP))) + goto err; + if (my_close(from_file,MyFlags) | my_close(to_file,MyFlags)) + DBUG_RETURN(-1); /* Error on close */ + DBUG_RETURN(0); + } + } +err: + if (from_file >= 0) VOID(my_close(from_file,MyFlags)); + if (to_file >= 0) VOID(my_close(to_file,MyFlags)); + DBUG_RETURN(-1); +} diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c new file mode 100644 index 00000000000..1063e9381bf --- /dev/null +++ b/mysys/my_chsize.c @@ -0,0 +1,86 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include "mysys_err.h" +#include "m_string.h" + + /* Change size of file. Truncate file if shorter, */ + /* else expand with zero. */ + +int my_chsize(File fd, my_off_t newlength, myf MyFlags) +{ + DBUG_ENTER("my_chsize"); + DBUG_PRINT("my",("fd: %d length: %lu MyFlags: %d",fd,(ulong) newlength, + MyFlags)); + +#ifdef HAVE_CHSIZE + if (chsize(fd,(off_t) newlength)) + { + DBUG_PRINT("error",("errno: %d",errno)); + my_errno=errno; + if (MyFlags & MY_WME) + my_error(EE_CANT_CHSIZE,MYF(ME_BELL+ME_WAITTANG),errno); + DBUG_RETURN(1); + } + DBUG_RETURN(0); +#else + /* if file is shorter, expand with null, else fill unused part with null */ + { + my_off_t oldsize; + char buff[IO_SIZE]; + + bzero(buff,IO_SIZE); + oldsize = my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE)); + +#ifdef HAVE_FTRUNCATE + if (oldsize > newlength) + { + if (ftruncate(fd, (off_t) newlength)) + { + my_errno=errno; + DBUG_PRINT("error",("errno: %d",errno)); + if (MyFlags & MY_WME) + my_error(EE_CANT_CHSIZE, MYF(ME_BELL+ME_WAITTANG), errno); + DBUG_RETURN(1); + } + DBUG_RETURN(0); + } +#else + if (oldsize > newlength) + { /* Fill diff with null */ + VOID(my_seek(fd, newlength, MY_SEEK_SET, MYF(MY_WME+MY_FAE))); + swap(long, newlength, oldsize); + } +#endif + while (newlength-oldsize > IO_SIZE) + { + if (my_write(fd,(byte*) buff,IO_SIZE,MYF(MY_NABP))) + goto err; + oldsize+= IO_SIZE; + } + if (my_write(fd,(byte*) buff,(uint) (newlength-oldsize),MYF(MY_NABP))) + goto err; + DBUG_RETURN(0); + err: + if (MyFlags & MY_WME) + my_error(EE_CANT_CHSIZE,MYF(ME_BELL+ME_WAITTANG),my_errno); + DBUG_PRINT("error",("errno: %d",my_errno)); + DBUG_RETURN(1); + } +#endif +} /* my_chsize */ diff --git a/mysys/my_clock.c b/mysys/my_clock.c new file mode 100644 index 00000000000..d13d69a7b88 --- /dev/null +++ b/mysys/my_clock.c @@ -0,0 +1,35 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#define USES_TYPES +#include "global.h" + +#if !defined(_MSC_VER) && !defined(__BORLANDC__) +#include "mysys_priv.h" +#include <sys/times.h> +#endif + +long my_clock(void) +{ +#if !defined(MSDOS) && !defined(__WIN__) + struct tms tmsbuf; + VOID(times(&tmsbuf)); + return (tmsbuf.tms_utime + tmsbuf.tms_stime); +#else + return clock(); +#endif +} diff --git a/mysys/my_compress.c b/mysys/my_compress.c new file mode 100644 index 00000000000..d1e32234135 --- /dev/null +++ b/mysys/my_compress.c @@ -0,0 +1,87 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Written by Sinisa Milivojevic <sinisa@coresinc.com> */ + +#include <global.h> +#ifdef HAVE_COMPRESS +#include <my_sys.h> +#include <zlib.h> + +/* +** This replaces the packet with a compressed packet +** Returns 1 on error +** *complen is 0 if the packet wasn't compressed +*/ + +my_bool my_compress(byte *packet, ulong *len, ulong *complen) +{ + if (*len < MIN_COMPRESS_LENGTH) + *complen=0; + else + { + byte *compbuf=my_compress_alloc(packet,len,complen); + if (!compbuf) + return *complen ? 0 : 1; + memcpy(packet,compbuf,*len); + my_free(compbuf,MYF(MY_WME)); } + return 0; +} + + +byte *my_compress_alloc(const byte *packet, ulong *len, ulong *complen) +{ + byte *compbuf; + *complen = *len * 120 / 100 + 12; + if (!(compbuf = (byte *) my_malloc(*complen,MYF(MY_WME)))) + return 0; /* Not enough memory */ + if (compress((Bytef*) compbuf,(ulong *) complen, (Bytef*) packet, + (uLong) *len ) != Z_OK) + { + my_free(compbuf,MYF(MY_WME)); + return 0; + } + if (*complen >= *len) + { + *complen=0; + my_free(compbuf,MYF(MY_WME)); + return 0; + } + swap(ulong,*len,*complen); /* *len is now packet length */ + return compbuf; +} + + +my_bool my_uncompress (byte *packet, ulong *len, ulong *complen) +{ + if (*complen) /* If compressed */ + { + byte *compbuf = (byte *) my_malloc (*complen,MYF(MY_WME)); + if (!compbuf) + return 1; /* Not enough memory */ + if (uncompress((Bytef*) compbuf, complen, (Bytef*) packet, *len) != Z_OK) + { /* Probably wrong packet */ + my_free (compbuf,MYF(MY_WME)); + return 1; + } + *len = *complen; + memcpy(packet,compbuf,*len); + my_free(compbuf,MYF(MY_WME)); + } + return 0; +} +#endif /* HAVE_COMPRESS */ diff --git a/mysys/my_copy.c b/mysys/my_copy.c new file mode 100644 index 00000000000..bfd7e957585 --- /dev/null +++ b/mysys/my_copy.c @@ -0,0 +1,103 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#define USES_TYPES /* sys/types is included */ +#include "mysys_priv.h" +#include <sys/stat.h> +#include <m_string.h> +#if defined(HAVE_SYS_UTIME_H) +#include <sys/utime.h> +#elif defined(HAVE_UTIME_H) +#include <utime.h> +#elif !defined(HPUX) +#include <time.h> +struct utimbuf { + time_t actime; + time_t modtime; +}; +#endif + + + /* + Ordinary ownership and accesstimes are copied from 'from-file' + if MyFlags & MY_HOLD_ORIGINAL_MODES is set and to-file exists then + the modes of to-file isn't changed + Dont set MY_FNABP or MY_NABP bits on when calling this function ! + */ + +int my_copy(const char *from, const char *to, myf MyFlags) +{ + uint Count; + int new_file_stat; + File from_file,to_file; + char buff[IO_SIZE]; + struct stat stat_buff,new_stat_buff; + DBUG_ENTER("my_copy"); + DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags)); + + from_file=to_file= -1; + new_file_stat=0; + if (MyFlags & MY_HOLD_ORIGINAL_MODES) /* Copy stat if possible */ + new_file_stat=stat((char*) to, &new_stat_buff); + + if ((from_file=my_open(from,O_RDONLY,MyFlags)) >= 0) + { + if (stat(from,&stat_buff)) + { + my_errno=errno; + goto err; + } + if (MyFlags & MY_HOLD_ORIGINAL_MODES && !new_file_stat) + stat_buff=new_stat_buff; + if ((to_file= my_create(to,(int) stat_buff.st_mode, + O_WRONLY | O_TRUNC | O_BINARY, + MyFlags)) < 0) + goto err; + + while ((Count=my_read(from_file,buff,IO_SIZE,MyFlags)) != 0) + if (Count == (uint) -1 || + my_write(to_file,buff,Count,MYF(MyFlags | MY_NABP))) + goto err; + + if (my_close(from_file,MyFlags) | my_close(to_file,MyFlags)) + DBUG_RETURN(-1); /* Error on close */ + + /* Copy modes if possible */ + + if (MyFlags & MY_HOLD_ORIGINAL_MODES && new_file_stat) + DBUG_RETURN(0); /* File copyed but not stat */ + VOID(chmod(to, stat_buff.st_mode & 07777)); /* Copy modes */ +#if !defined(MSDOS) && !defined(__WIN__) && !defined(__EMX__) + VOID(chown(to, stat_buff.st_uid,stat_buff.st_gid)); /* Copy ownership */ +#endif +#if !defined(VMS) && !defined(__ZTC__) + if (MyFlags & MY_COPYTIME) + { + struct utimbuf timep; + timep.actime = stat_buff.st_atime; + timep.modtime = stat_buff.st_mtime; + VOID(utime((char*) to, &timep)); /* last accessed and modified times */ + } +#endif + DBUG_RETURN(0); + } + +err: + if (from_file >= 0) VOID(my_close(from_file,MyFlags)); + if (to_file >= 0) VOID(my_close(to_file,MyFlags)); + DBUG_RETURN(-1); +} /* my_copy */ diff --git a/mysys/my_create.c b/mysys/my_create.c new file mode 100644 index 00000000000..866c0dfd465 --- /dev/null +++ b/mysys/my_create.c @@ -0,0 +1,84 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#define USES_TYPES +#include "mysys_priv.h" +#include <my_dir.h> +#include "mysys_err.h" +#include <errno.h> +#if defined(MSDOS) || defined(__WIN__) +#include <share.h> +#endif + + /* + ** Create a new file + ** Arguments: + ** Path-name of file + ** Read | write on file (umask value) + ** Read & Write on open file + ** Special flags + */ + + +File my_create(const char *FileName, int CreateFlags, int access_flags, + myf MyFlags) +{ + int fd; + DBUG_ENTER("my_create"); + DBUG_PRINT("my",("Name: '%s' CreateFlags: %d AccessFlags: %d MyFlags: %d", + FileName, CreateFlags, access_flags, MyFlags)); + +#if !defined(NO_OPEN_3) + fd = open((my_string) FileName, access_flags | O_CREAT, + CreateFlags ? CreateFlags : my_umask); +#elif defined(VMS) + fd = open((my_string) FileName, access_flags | O_CREAT, 0, + "ctx=stm","ctx=bin"); +#elif defined(MSDOS) || defined(__WIN__) + if (access_flags & O_SHARE) + fd = sopen((my_string) FileName, access_flags | O_CREAT | O_BINARY, + SH_DENYNO, MY_S_IREAD | MY_S_IWRITE); + else + fd = open((my_string) FileName, access_flags | O_CREAT | O_BINARY, + MY_S_IREAD | MY_S_IWRITE); +#else + fd = open(FileName, access_flags); +#endif + + if (fd >= 0) + { + if ((int) fd >= MY_NFILE) + { + DBUG_PRINT("exit",("fd: %d",fd)); + DBUG_RETURN(fd); /* safeguard */ + } + if ((my_file_info[fd].name = (char*) my_strdup(FileName,MyFlags))) + { + my_file_opened++; + my_file_info[fd].type = FILE_BY_CREATE; + DBUG_PRINT("exit",("fd: %d",fd)); + DBUG_RETURN(fd); + } + VOID(my_close(fd,MyFlags)); + my_errno=ENOMEM; + } + else + my_errno=errno; + if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) + my_error(EE_CANTCREATEFILE, MYF(ME_BELL+ME_WAITTANG), FileName,my_errno); + DBUG_RETURN(-1); +} /* my_create */ diff --git a/mysys/my_delete.c b/mysys/my_delete.c new file mode 100644 index 00000000000..77d5f311418 --- /dev/null +++ b/mysys/my_delete.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" + +#include "mysys_err.h" + +int my_delete(const char *name, myf MyFlags) +{ + int err; + DBUG_ENTER("my_delete"); + DBUG_PRINT("my",("name %s MyFlags %d", name, MyFlags)); + + if ((err = unlink(name)) == -1) + { + my_errno=errno; + if (MyFlags & (MY_FAE+MY_WME)) + my_error(EE_DELETE,MYF(ME_BELL+ME_WAITTANG+(MyFlags & ME_NOINPUT)), + name,errno); + } + DBUG_RETURN(err); +} /* my_delete */ diff --git a/mysys/my_div.c b/mysys/my_div.c new file mode 100644 index 00000000000..24794679376 --- /dev/null +++ b/mysys/my_div.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" + +my_string my_filename(File fd) +{ + DBUG_ENTER("my_filename"); + if (fd >= MY_NFILE) + DBUG_RETURN((char*) "UNKNOWN"); + if (fd >= 0 && my_file_info[fd].type != UNOPEN) + { + DBUG_RETURN(my_file_info[fd].name); + } + else + DBUG_RETURN((char*) "UNOPENED"); /* Debug message */ +} diff --git a/mysys/my_error.c b/mysys/my_error.c new file mode 100644 index 00000000000..26510f08480 --- /dev/null +++ b/mysys/my_error.c @@ -0,0 +1,122 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include "mysys_err.h" +#include <m_string.h> +#include <stdarg.h> +#include <m_ctype.h> + +/* Define some external variables for error handling */ + +const char ** NEAR errmsg[MAXMAPS]={0,0,0,0}; +char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE]; + +/* Error message to user */ +/*VARARGS2*/ + +int my_error(int nr,myf MyFlags, ...) +{ + va_list ap; + uint olen, plen; + reg1 const char *tpos; + reg2 char *endpos; + char * par; + char ebuff[ERRMSGSIZE+20]; + DBUG_ENTER("my_error"); + + va_start(ap,MyFlags); + DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d", nr, MyFlags, errno)); + + if (nr / ERRMOD == GLOB && errmsg[GLOB] == 0) + init_glob_errs(); + + olen=(uint) strlen(tpos=errmsg[nr / ERRMOD][nr % ERRMOD]); + endpos=ebuff; + + while (*tpos) + { + if (tpos[0] != '%') + { + *endpos++= *tpos++; /* Copy ordinary char */ + olen++; + continue; + } + if (*++tpos == '%') /* test if %% */ + { + olen--; + } + else + { + /* Skipp if max size is used (to be compatible with printf) */ + while (isdigit(*tpos) || *tpos == '.' || *tpos == '-') + tpos++; + if (*tpos == 's') /* String parameter */ + { + par = va_arg(ap, char *); + plen = (uint) strlen(par); + if (olen + plen < ERRMSGSIZE+2) /* Replace if possible */ + { + endpos=strmov(endpos,par); + tpos++; + olen+=plen-2; + continue; + } + } + else if (*tpos == 'd' || *tpos == 'u') /* Integer parameter */ + { + register int iarg; + iarg = va_arg(ap, int); + if (*tpos == 'd') + plen= (uint) (int2str((long) iarg,endpos, -10) - endpos); + else + plen= (uint) (int2str((long) (uint) iarg,endpos,10)- endpos); + if (olen + plen < ERRMSGSIZE+2) /* Replace parameter if possible */ + { + endpos+=plen; + tpos++; + olen+=plen-2; + continue; + } + } + } + *endpos++='%'; /* % used as % or unknown code */ + } + *endpos='\0'; /* End of errmessage */ + va_end(ap); + DBUG_RETURN((*error_handler_hook)(nr, ebuff, MyFlags)); +} + + /* Error as printf */ + +int my_printf_error (uint error, const char *format, myf MyFlags, ...) +{ + va_list args; + char ebuff[ERRMSGSIZE+20]; + + va_start(args,MyFlags); + (void) vsprintf (ebuff,format,args); + va_end(args); + return (*error_handler_hook)(error, ebuff, MyFlags); +} + + /* Give message using error_handler_hook */ + +int my_message(uint error, const char *str, register myf MyFlags) +{ + return (*error_handler_hook)(error, str, MyFlags); +} diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c new file mode 100644 index 00000000000..b2e99518792 --- /dev/null +++ b/mysys/my_fopen.c @@ -0,0 +1,165 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include "my_static.h" +#include <errno.h> +#include "mysys_err.h" + +static void make_ftype(my_string to,int flag); + + /* Open a file as stream */ + +FILE *my_fopen(const char *FileName, int Flags, myf MyFlags) + /* Path-name of file */ + /* Read | write .. */ + /* Special flags */ +{ + FILE *fd; + char type[5]; + DBUG_ENTER("my_fopen"); + DBUG_PRINT("my",("Name: '%s' Flags: %d MyFlags: %d", + FileName, Flags, MyFlags)); + + make_ftype(type,Flags); + if ((fd = fopen(FileName, type)) != 0) + { + /* + The test works if MY_NFILE < 128. The problem is that fileno() is char + on some OS (SUNOS). Actually the filename save isn't that important + so we can ignore if this doesn't work. + */ + if ((uint) fileno(fd) >= MY_NFILE) + DBUG_RETURN(fd); /* safeguard */ + pthread_mutex_lock(&THR_LOCK_open); + if ((my_file_info[fileno(fd)].name = (char*) + my_strdup(FileName,MyFlags))) + { + my_stream_opened++; + my_file_info[fileno(fd)].type = STREAM_BY_FOPEN; + pthread_mutex_unlock(&THR_LOCK_open); + DBUG_PRINT("exit",("stream: %lx",fd)); + DBUG_RETURN(fd); + } + pthread_mutex_unlock(&THR_LOCK_open); + (void) my_fclose(fd,MyFlags); + my_errno=ENOMEM; + } + else + my_errno=errno; + DBUG_PRINT("error",("Got error %d on open",my_errno)); + if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) + my_error((Flags & O_RDONLY) || (Flags == O_RDONLY ) ? EE_FILENOTFOUND : + EE_CANTCREATEFILE, + MYF(ME_BELL+ME_WAITTANG), FileName,my_errno); + DBUG_RETURN((FILE*) 0); +} /* my_fopen */ + + + /* Close a stream */ + +int my_fclose(FILE *fd, myf MyFlags) +{ + int err,file; + DBUG_ENTER("my_fclose"); + DBUG_PRINT("my",("stream: %lx MyFlags: %d",fd, MyFlags)); + + pthread_mutex_lock(&THR_LOCK_open); + file=fileno(fd); + if ((err = fclose(fd)) < 0) + { + my_errno=errno; + if (MyFlags & (MY_FAE | MY_WME)) + my_error(EE_BADCLOSE, MYF(ME_BELL+ME_WAITTANG), + my_filename(file),errno); + } + if ((uint) file < MY_NFILE && my_file_info[file].type != UNOPEN) + { + my_file_info[file].type = UNOPEN; + my_free(my_file_info[file].name, MYF(0)); + my_stream_opened--; + } + pthread_mutex_unlock(&THR_LOCK_open); + DBUG_RETURN(err); +} /* my_fclose */ + + + /* Make a stream out of a file handle */ + +FILE *my_fdopen(File Filedes, int Flags, myf MyFlags) + + /* Read | write .. */ + /* Special flags */ +{ + FILE *fd; + char type[5]; + DBUG_ENTER("my_fdopen"); + DBUG_PRINT("my",("Fd: %d Flags: %d MyFlags: %d", + Filedes, Flags, MyFlags)); + + make_ftype(type,Flags); + if ((fd = fdopen(Filedes, type)) == 0) + { + my_errno=errno; + if (MyFlags & (MY_FAE | MY_WME)) + my_error(EE_CANT_OPEN_STREAM, MYF(ME_BELL+ME_WAITTANG),errno); + } + else + { + pthread_mutex_lock(&THR_LOCK_open); + if (my_file_info[Filedes].type != UNOPEN) + { + my_file_info[Filedes].type = STREAM_BY_FDOPEN; + my_file_opened--; /* File is opened with my_open ! */ + my_stream_opened++; + } + pthread_mutex_unlock(&THR_LOCK_open); + } + + DBUG_PRINT("exit",("stream: %lx",fd)); + DBUG_RETURN(fd); +} /* my_fdopen */ + + + /* Make a filehandler-open-typestring from ordinary inputflags */ + +static void make_ftype(register my_string to, register int flag) +{ +#if FILE_BINARY /* If we have binary-files */ + reg3 int org_flag=flag; +#endif + flag&= ~FILE_BINARY; /* remove binary bit */ + if (flag == O_RDONLY) + *to++= 'r'; + else if (flag == O_WRONLY) + *to++= 'w'; + else + { /* Add '+' after theese */ + if (flag == O_RDWR) + *to++= 'r'; + else if (flag & O_APPEND) + *to++= 'a'; + else + *to++= 'w'; /* Create file */ + *to++= '+'; + } +#if FILE_BINARY /* If we have binary-files */ + if (org_flag & FILE_BINARY) + *to++='b'; +#endif + *to='\0'; +} /* make_ftype */ diff --git a/mysys/my_fstream.c b/mysys/my_fstream.c new file mode 100644 index 00000000000..76bd12abe32 --- /dev/null +++ b/mysys/my_fstream.c @@ -0,0 +1,170 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* USE_MY_STREAM isn't set because we can't thrust my_fclose! */ + +#include "mysys_priv.h" +#include "mysys_err.h" +#include <errno.h> + +#ifdef HAVE_FSEEKO +#undef ftell +#undef fseek +#define ftell(A) ftello(A) +#define fseek(A,B,C) fseeko((A),(B),(C)) +#endif + + /* Read a chunk of bytes from a file */ + /* Returns (uint) -1 if error as my_read() */ + +uint my_fread(FILE *stream, byte *Buffer, uint Count, myf MyFlags) + /* File descriptor */ + /* Buffer must be at least count bytes */ + /* Max number of bytes returnd */ + /* Flags on what to do on error */ +{ + uint readbytes; + DBUG_ENTER("my_fread"); + DBUG_PRINT("my",("stream: %lx Buffer: %lx Count: %u MyFlags: %d", + stream, Buffer, Count, MyFlags)); + + if ((readbytes = (uint) fread(Buffer,sizeof(char),(size_t) Count,stream)) + != Count) + { + DBUG_PRINT("error",("Read only %d bytes",readbytes)); + if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) + { + if (ferror(stream)) + my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), + my_filename(fileno(stream)),errno); + else + if (MyFlags & (MY_NABP | MY_FNABP)) + my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), + my_filename(fileno(stream)),errno); + } + my_errno=errno ? errno : -1; + if (ferror(stream) || MyFlags & (MY_NABP | MY_FNABP)) + DBUG_RETURN((uint) -1); /* Return with error */ + } + if (MyFlags & (MY_NABP | MY_FNABP)) + DBUG_RETURN(0); /* Read ok */ + DBUG_RETURN(readbytes); +} /* my_fread */ + + +/* +** Write a chunk of bytes to a stream +** Returns (uint) -1 if error as my_write() +** Does retries if interrupted +*/ + +uint my_fwrite(FILE *stream, const byte *Buffer, uint Count, myf MyFlags) +{ + uint writenbytes=0; + off_t seekptr; +#if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM) + uint errors; +#endif + DBUG_ENTER("my_fwrite"); + DBUG_PRINT("my",("stream: %lx Buffer: %lx Count: %u MyFlags: %d", + stream, Buffer, Count, MyFlags)); + +#if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM) + errors=0; +#endif + seekptr=ftell(stream); + for (;;) + { + uint writen; + if ((writen = (uint) fwrite((char*) Buffer,sizeof(char), + (size_t) Count, stream)) != Count) + { + DBUG_PRINT("error",("Write only %d bytes",writenbytes)); + my_errno=errno; + if (writen != (uint) -1) + { + seekptr+=writen; + Buffer+=writen; + writenbytes+=writen; + Count-=writen; + } +#ifdef EINTR + if (errno == EINTR) + { + VOID(my_fseek(stream,seekptr,MY_SEEK_SET,MYF(0))); + continue; + } +#endif +#if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM) +#ifdef THREAD + if (my_thread_var->abort) + MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */ +#endif + if (errno == ENOSPC && (MyFlags & MY_WAIT_IF_FULL)) + { + if (!(errors++ % MY_WAIT_GIVE_USER_A_MESSAGE)) + my_error(EE_DISK_FULL,MYF(ME_BELL | ME_NOREFRESH)); + sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC); + VOID(my_fseek(stream,seekptr,MY_SEEK_SET,MYF(0))); + continue; + } +#endif + if (ferror(stream) || (MyFlags & (MY_NABP | MY_FNABP))) + { + if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) + { + my_error(EE_WRITE, MYF(ME_BELL+ME_WAITTANG), + my_filename(fileno(stream)),errno); + } + writenbytes=(uint) -1; /* Return that we got error */ + break; + } + } + if (MyFlags & (MY_NABP | MY_FNABP)) + writenbytes=0; /* Everything OK */ + else + writenbytes+=writen; + break; + } + DBUG_RETURN(writenbytes); +} /* my_fwrite */ + + /* Seek to position in file */ + /* ARGSUSED */ + +my_off_t my_fseek(FILE *stream, my_off_t pos, int whence, myf MyFlags) +{ + DBUG_ENTER("my_fseek"); + DBUG_PRINT("my",("stream: %lx pos: %lu whence: %d MyFlags: %d", + stream, pos, whence, MyFlags)); + DBUG_RETURN(fseek(stream, (off_t) pos, whence) ? + MY_FILEPOS_ERROR : (my_off_t) ftell(stream)); +} /* my_seek */ + + + /* Tell current position of file */ + /* ARGSUSED */ + +my_off_t my_ftell(FILE *stream, myf MyFlags) +{ + off_t pos; + DBUG_ENTER("my_ftell"); + DBUG_PRINT("my",("stream: %lx MyFlags: %d",stream, MyFlags)); + pos=ftell(stream); + DBUG_PRINT("exit",("ftell: %lu",(ulong) pos)); + DBUG_RETURN((my_off_t) pos); +} /* my_ftell */ diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c new file mode 100644 index 00000000000..3d674276731 --- /dev/null +++ b/mysys/my_getwd.c @@ -0,0 +1,182 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* my_setwd() and my_getwd() works with intern_filenames !! */ + +#include "mysys_priv.h" +#include <m_string.h> +#include "mysys_err.h" +#ifdef HAVE_GETWD +#include <sys/param.h> +#endif +#if defined(MSDOS) || defined(__WIN__) +#include <m_ctype.h> +#include <dos.h> +#include <direct.h> +#endif + + + /* Gets current working directory in buff. Directory is allways ended + with FN_LIBCHAR */ + /* One must pass a buffer to my_getwd. One can allways use + curr_dir[] */ + +int my_getwd(my_string buf, uint size, myf MyFlags) +{ + my_string pos; + DBUG_ENTER("my_getwd"); + DBUG_PRINT("my",("buf: %lx size: %d MyFlags %d", buf,size,MyFlags)); + +#if ! defined(MSDOS) + if (curr_dir[0]) /* Current pos is saved here */ + VOID(strmake(buf,&curr_dir[0],size-1)); + else +#endif + { +#if defined(HAVE_GETCWD) + if (!getcwd(buf,size-2) && MyFlags & MY_WME) + { + my_errno=errno; + my_error(EE_GETWD,MYF(ME_BELL+ME_WAITTANG),errno); + return(-1); + } +#elif defined(HAVE_GETWD) + { + char pathname[MAXPATHLEN]; + getwd(pathname); + strmake(buf,pathname,size-1); + } +#elif defined(VMS) + if (!getcwd(buf,size-2,1) && MyFlags & MY_WME) + { + my_errno=errno; + my_error(EE_GETWD,MYF(ME_BELL+ME_WAITTANG),errno); + return(-1); + } + intern_filename(buf,buf); +#else +#error "No way to get current directory" +#endif + if (*((pos=strend(buf))-1) != FN_LIBCHAR) /* End with FN_LIBCHAR */ + { + pos[0]= FN_LIBCHAR; + pos[1]=0; + } + (void) strmake(&curr_dir[0],buf,(size_s) (FN_REFLEN-1)); + } + DBUG_RETURN(0); +} /* my_getwd */ + + + /* Set new working directory */ + +int my_setwd(const char *dir, myf MyFlags) +{ + int res; + size_s length; + my_string start,pos; +#if defined(VMS) || defined(MSDOS) + char buff[FN_REFLEN]; +#endif + DBUG_ENTER("my_setwd"); + DBUG_PRINT("my",("dir: '%s' MyFlags %d", dir, MyFlags)); + + start=(my_string) dir; +#if defined(MSDOS) /* MSDOS chdir can't change drive */ +#if !defined(_DDL) && !defined(WIN32) + if ((pos=strchr(dir,FN_DEVCHAR)) != 0) + { + uint drive,drives; + + pos++; /* Skipp FN_DEVCHAR */ + drive=(uint) (toupper(dir[0])-'A'+1); drives= (uint) -1; + if ((pos-(byte*) dir) == 2 && drive > 0 && drive < 32) + { + _dos_setdrive(drive,&drives); + _dos_getdrive(&drives); + } + if (drive != drives) + { + *pos='\0'; /* Dir is now only drive */ + my_errno=errno; + my_error(EE_SETWD,MYF(ME_BELL+ME_WAITTANG),dir,ENOENT); + DBUG_RETURN(-1); + } + dir=pos; /* drive changed, change now path */ + } +#endif + if (*((pos=strend(dir)-1)) == FN_LIBCHAR && pos != dir) + { + strmov(buff,dir)[-1]=0; /* Remove last '/' */ + dir=buff; + } +#endif /* MSDOS*/ + if (! dir[0] || (dir[0] == FN_LIBCHAR && dir[1] == 0)) + dir=FN_ROOTDIR; +#ifdef VMS + { + pos=strmov(buff,dir); + if (pos[-1] != FN_LIBCHAR) + { + pos[0]=FN_LIBCHAR; /* Mark as directory */ + pos[1]=0; + } + system_filename(buff,buff); /* Change to VMS format */ + dir=buff; + } +#endif /* VMS */ + if ((res=chdir((char*) dir)) != 0) + { + my_errno=errno; + if (MyFlags & MY_WME) + my_error(EE_SETWD,MYF(ME_BELL+ME_WAITTANG),start,errno); + } + else + { + if (test_if_hard_path(start)) + { /* Hard pathname */ + pos=strmake(&curr_dir[0],start,(size_s) FN_REFLEN-1); + if (pos[-1] != FN_LIBCHAR) + { + length=(uint) (pos-(char*) curr_dir); + curr_dir[length]=FN_LIBCHAR; /* must end with '/' */ + curr_dir[length+1]='\0'; + } + } + else + curr_dir[0]='\0'; /* Don't save name */ + } + DBUG_RETURN(res); +} /* my_setwd */ + + + + /* Test if hard pathname */ + /* Returns 1 if dirname is a hard path */ + +int test_if_hard_path(register const char *dir_name) +{ + if (dir_name[0] == FN_HOMELIB && dir_name[1] == FN_LIBCHAR) + return (home_dir != NullS && test_if_hard_path(home_dir)); + if (dir_name[0] == FN_LIBCHAR) + return (TRUE); +#ifdef FN_DEVCHAR + return (strchr(dir_name,FN_DEVCHAR) != 0); +#else + return FALSE; +#endif +} /* test_if_hard_path */ diff --git a/mysys/my_init.c b/mysys/my_init.c new file mode 100644 index 00000000000..912e80d9ebd --- /dev/null +++ b/mysys/my_init.c @@ -0,0 +1,301 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include "my_static.h" +#include "mysys_err.h" +#include "m_ctype.h" +#include <m_string.h> +#include <m_ctype.h> +#ifdef THREAD +#include <my_pthread.h> +#endif +#ifdef HAVE_GETRUSAGE +#include <sys/resource.h> +/* extern int getrusage(int, struct rusage *); */ +#endif +#include <signal.h> +#ifdef VMS +#include <my_static.c> +#include <m_ctype.h> +#endif +#ifdef __WIN__ +#ifdef _MSC_VER +#include <locale.h> +#include <crtdbg.h> +#endif +my_bool have_tcpip=0; +static void my_win_init(void); +static my_bool win32_have_tcpip(void); +static my_bool win32_init_tcp_ip(); +#else +#define my_win_init() +#endif +static my_bool my_init_done=0; + + /* Init my_sys functions and my_sys variabels */ + +void my_init(void) +{ + my_string str; + if (my_init_done) + return; + my_init_done=1; +#ifdef THREAD +#if defined(HAVE_PTHREAD_INIT) + pthread_init(); /* Must be called before DBUG_ENTER */ +#endif + my_thread_global_init(); +#ifndef __WIN__ + sigfillset(&my_signals); /* signals blocked by mf_brkhant */ +#endif +#endif + { + DBUG_ENTER("my_init"); + DBUG_PROCESS(my_progname ? my_progname : (char*) "unknown"); + if (!home_dir) + { /* Don't initialize twice */ + my_win_init(); + if ((home_dir=getenv("HOME")) != 0) + home_dir=intern_filename(home_dir_buff,home_dir); +#ifndef VMS + if ((str=getenv("UMASK")) != 0) + my_umask=atoi(str) | 0600; /* Default creation of new files */ + if ((str=getenv("UMASK_DIR")) != 0) + my_umask_dir=atoi(str) | 0700; /* Default creation of new dir's */ +#endif +#ifdef VMS + init_ctype(); /* Stupid linker don't link _ctype.c */ +#endif + DBUG_PRINT("exit",("home: '%s'",home_dir)); + } +#ifdef __WIN__ + win32_init_tcp_ip(); +#endif + DBUG_VOID_RETURN; + } +} /* my_init */ + + + /* End my_sys */ + +void my_end(int infoflag) +{ + FILE *info_file; + if (!(info_file=DBUG_FILE)) + info_file=stderr; + if (infoflag & MY_CHECK_ERROR || info_file != stderr) + { /* Test if some file is left open */ + if (my_file_opened | my_stream_opened) + { + sprintf(errbuff[0],EE(EE_OPEN_WARNING),my_file_opened,my_stream_opened); + (void) my_message_no_curses(EE_OPEN_WARNING,errbuff[0],ME_BELL); + DBUG_PRINT("error",("%s",errbuff[0])); + } + } + if (infoflag & MY_GIVE_INFO || info_file != stderr) + { +#ifdef HAVE_GETRUSAGE + struct rusage rus; + if (!getrusage(RUSAGE_SELF, &rus)) + fprintf(info_file,"\nUser time %.2f, System time %.2f\nMaximum resident set size %ld, Integral resident set size %ld\nNon physical pagefaults %ld, Physical pagefaults %ld, Swaps %ld\nBlocks in %ld out %ld, Messages in %ld out %ld, Signals %ld\nVouluntary context switches %ld, Invouluntary context switches %ld\n", + (rus.ru_utime.tv_sec * SCALE_SEC + + rus.ru_utime.tv_usec / SCALE_USEC) / 100.0, + (rus.ru_stime.tv_sec * SCALE_SEC + + rus.ru_stime.tv_usec / SCALE_USEC) / 100.0, + rus.ru_maxrss, rus.ru_idrss, + rus.ru_minflt, rus.ru_majflt, + rus.ru_nswap, rus.ru_inblock, rus.ru_oublock, + rus.ru_msgsnd, rus.ru_msgrcv, rus.ru_nsignals, + rus.ru_nvcsw, rus.ru_nivcsw); +#endif +#if defined(MSDOS) && !defined(__WIN__) + fprintf(info_file,"\nRun time: %.1f\n",(double) clock()/CLOCKS_PER_SEC); +#endif + free_charsets(); +#if defined(SAFEMALLOC) + TERMINATE(stderr); /* Give statistic on screen */ +#elif defined(__WIN__) && defined(_MSC_VER) + _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR ); + _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDERR ); + _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR ); + _CrtCheckMemory(); + _CrtDumpMemoryLeaks(); +#endif + } +#ifdef THREAD + pthread_mutex_destroy(&THR_LOCK_keycache); + pthread_mutex_destroy(&THR_LOCK_malloc); + pthread_mutex_destroy(&THR_LOCK_open); + DBUG_POP(); /* Must be done before my_thread_end */ + my_thread_end(); + my_thread_global_end(); +#endif +#ifdef __WIN__ + if (have_tcpip); + WSACleanup( ); +#endif /* __WIN__ */ +} /* my_end */ + +#ifdef __WIN__ + +/* + This code is specially for running MySQL, but it should work in + other cases too. + + Inizializzazione delle variabili d'ambiente per Win a 32 bit. + + Vengono inserite nelle variabili d'ambiente (utilizzando cosi' + le funzioni getenv e putenv) i valori presenti nelle chiavi + del file di registro: + + HKEY_LOCAL_MACHINE\software\MySQL + + Se la kiave non esiste nonn inserisce nessun valore +*/ + +/* Crea la stringa d'ambiente */ + +void setEnvString(char *ret, const char *name, const char *value) +{ + DBUG_ENTER("setEnvString"); + strxmov(ret, name,"=",value,NullS); + DBUG_VOID_RETURN ; +} + +static void my_win_init(void) +{ + HKEY hSoftMysql ; + DWORD dimName = 256 ; + DWORD dimData = 1024 ; + DWORD dimNameValueBuffer = 256 ; + DWORD dimDataValueBuffer = 1024 ; + DWORD indexValue = 0 ; + long retCodeEnumValue ; + char NameValueBuffer[256] ; + char DataValueBuffer[1024] ; + char EnvString[1271] ; + const char *targetKey = "Software\\MySQL" ; + DBUG_ENTER("my_win_init"); + + setlocale(LC_CTYPE, ""); /* To get right sortorder */ + + /* apre la chiave HKEY_LOCAL_MACHINES\software\MySQL */ + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,(LPCTSTR)targetKey,0, + KEY_READ,&hSoftMysql) != ERROR_SUCCESS) + DBUG_VOID_RETURN; + + /* + ** Ne legge i valori e li inserisce nell'ambiente + ** suppone che tutti i valori letti siano di tipo stringa + '\0' + ** Legge il valore con indice 0 e lo scarta + */ + retCodeEnumValue = RegEnumValue(hSoftMysql, indexValue++, + (LPTSTR)NameValueBuffer, &dimNameValueBuffer, + NULL, NULL, (LPBYTE)DataValueBuffer, + &dimDataValueBuffer) ; + + while (retCodeEnumValue != ERROR_NO_MORE_ITEMS) + { + char *my_env; + /* Crea la stringa d'ambiente */ + setEnvString(EnvString, NameValueBuffer, DataValueBuffer) ; + + /* Inserisce i dati come variabili d'ambiente */ + my_env=strdup(EnvString); /* variable for putenv must be allocated ! */ + putenv(EnvString) ; + + dimNameValueBuffer = dimName ; + dimDataValueBuffer = dimData ; + + retCodeEnumValue = RegEnumValue(hSoftMysql, indexValue++, + NameValueBuffer, &dimNameValueBuffer, + NULL, NULL, (LPBYTE)DataValueBuffer, + &dimDataValueBuffer) ; + } + + /* chiude la chiave */ + RegCloseKey(hSoftMysql) ; + DBUG_VOID_RETURN ; +} + + +/*------------------------------------------------------------------ +** Name: CheckForTcpip| Desc: checks if tcpip has been installed on system +** According to Microsoft Developers documentation the first registry +** entry should be enough to check if TCP/IP is installed, but as expected +** this doesn't work on all Win32 machines :( +------------------------------------------------------------------*/ + +#define TCPIPKEY "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters" +#define WINSOCK2KEY "SYSTEM\\CurrentControlSet\\Services\\Winsock2\\Parameters" +#define WINSOCKKEY "SYSTEM\\CurrentControlSet\\Services\\Winsock\\Parameters" + +static my_bool win32_have_tcpip(void) +{ + HKEY hTcpipRegKey; + if (RegOpenKeyEx ( HKEY_LOCAL_MACHINE, TCPIPKEY, 0, KEY_READ, + &hTcpipRegKey) != ERROR_SUCCESS) + { + if (RegOpenKeyEx ( HKEY_LOCAL_MACHINE, WINSOCK2KEY, 0, KEY_READ, + &hTcpipRegKey) != ERROR_SUCCESS) + { + if (RegOpenKeyEx ( HKEY_LOCAL_MACHINE, WINSOCKKEY, 0, KEY_READ, + &hTcpipRegKey) != ERROR_SUCCESS) + if (!getenv("HAVE_TCPIP") || have_tcpip) /* Provide a workaround */ + return (FALSE); + } + } + RegCloseKey ( hTcpipRegKey); + return (TRUE); +} + +static my_bool win32_init_tcp_ip() +{ + if (win32_have_tcpip()) + { + WORD wVersionRequested = MAKEWORD( 2, 0 ); + WSADATA wsaData; + /* Be a good citizen: maybe another lib has already initialised + sockets, so dont clobber them unless necessary */ + if (WSAStartup( wVersionRequested, &wsaData )) + { + /* Load failed, maybe because of previously loaded + incompatible version; try again */ + WSACleanup( ); + if (!WSAStartup( wVersionRequested, &wsaData )) + have_tcpip=1; + } + else + { + if (wsaData.wVersion != wVersionRequested) + { + /* Version is no good, try again */ + WSACleanup( ); + if (!WSAStartup( wVersionRequested, &wsaData )) + have_tcpip=1; + } + else + have_tcpip=1; + } + } + return(0); +} +#endif diff --git a/mysys/my_lib.c b/mysys/my_lib.c new file mode 100644 index 00000000000..b8554b08d28 --- /dev/null +++ b/mysys/my_lib.c @@ -0,0 +1,607 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* TODO: check for overun of memory for names. */ +/* Convert MSDOS-TIME to standar time_t */ + +#define USES_TYPES /* sys/types is included */ +#include "mysys_priv.h" +#include <m_string.h> +#include <my_dir.h> /* Structs used by my_dir,includes sys/types */ +#include "mysys_err.h" +#if defined(HAVE_DIRENT_H) +# include <dirent.h> +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# if defined(HAVE_SYS_NDIR_H) +# include <sys/ndir.h> +# endif +# if defined(HAVE_SYS_DIR_H) +# include <sys/dir.h> +# endif +# if defined(HAVE_NDIR_H) +# include <ndir.h> +# endif +# if defined(MSDOS) || defined(__WIN__) +# include <dos.h> +# ifdef __BORLANDC__ +# include <dir.h> +# endif +# endif +#endif +#ifdef VMS +#include <rms.h> +#include <iodef.h> +#include <descrip.h> +#endif +#if defined(THREAD) && defined(HAVE_READDIR_R) +#define READDIR(A,B,C) ((errno=readdir_r(A,B,&C)) != 0 || !C) +#else +#define READDIR(A,B,C) (!(C=readdir(A))) +#endif + + +#define STARTSIZE ONCE_ALLOC_INIT*8 /* some mallocmargin */ + +static int comp_names(struct fileinfo *a,struct fileinfo *b); + + + /* We need this because program don't know with malloc we used */ + +void my_dirend(MY_DIR *buffer) +{ + DBUG_ENTER("my_dirend"); + if (buffer) + my_free((gptr) buffer,MYF(0)); + DBUG_VOID_RETURN; +} /* my_dirend */ + + + /* Compare in sort of filenames */ + +static int comp_names(struct fileinfo *a, struct fileinfo *b) +{ + return (strcmp(a->name,b->name)); +} /* comp_names */ + + +#if !defined(MSDOS) && !defined(__WIN__) + +MY_DIR *my_dir(const char *path, myf MyFlags) +{ + DIR *dirp; + struct dirent *dp; + struct fileinfo *fnames; + char *buffer, *obuffer, *tempptr; + uint fcnt,i,size,firstfcnt, maxfcnt,length; + char tmp_path[FN_REFLEN+1],*tmp_file; + my_ptrdiff_t diff; + bool eof; +#ifdef THREAD + char dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1]; +#endif + DBUG_ENTER("my_dir"); + DBUG_PRINT("my",("path: '%s' stat: %d MyFlags: %d",path,MyFlags)); + +#if defined(THREAD) && !defined(HAVE_READDIR_R) + pthread_mutex_lock(&THR_LOCK_open); +#endif + + dirp = opendir(directory_file_name(tmp_path,(my_string) path)); + size = STARTSIZE; + if (dirp == NULL || ! (buffer = (char *) my_malloc(size, MyFlags))) + goto error; + + fcnt = 0; + tmp_file=strend(tmp_path); + firstfcnt = maxfcnt = (size - sizeof(MY_DIR)) / + (sizeof(struct fileinfo) + FN_LEN); + fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR)); + tempptr = (char *) (fnames + maxfcnt); + +#ifdef THREAD + dp= (struct dirent*) dirent_tmp; +#else + dp=0; +#endif + eof=0; + for (;;) + { + while (fcnt < maxfcnt && + !(eof= READDIR(dirp,(struct dirent*) dirent_tmp,dp))) + { + bzero((gptr) (fnames+fcnt),sizeof(fnames[0])); /* for purify */ + fnames[fcnt].name = tempptr; + tempptr = strmov(tempptr,dp->d_name) + 1; + if (MyFlags & MY_WANT_STAT) + { + VOID(strmov(tmp_file,dp->d_name)); + VOID(my_stat(tmp_path, &fnames[fcnt].mystat, MyFlags)); + } + ++fcnt; + } + if (eof) + break; + size += STARTSIZE; obuffer = buffer; + if (!(buffer = (char *) my_realloc((gptr) buffer, size, + MyFlags | MY_FREE_ON_ERROR))) + goto error; /* No memory */ + length= (uint) (sizeof(struct fileinfo ) * firstfcnt); + diff= PTR_BYTE_DIFF(buffer , obuffer) + (int) length; + fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR)); + tempptr= ADD_TO_PTR(tempptr,diff,char*); + for (i = 0; i < maxfcnt; i++) + fnames[i].name = ADD_TO_PTR(fnames[i].name,diff,char*); + + /* move filenames upp a bit */ + maxfcnt += firstfcnt; + bmove_upp(tempptr,tempptr-length, + (uint) (tempptr- (char*) (fnames+maxfcnt))); + } + + (void) closedir(dirp); + { + MY_DIR * s = (MY_DIR *) buffer; + s->number_off_files = (uint) fcnt; + s->dir_entry = fnames; + } + if (!(MyFlags & MY_DONT_SORT)) + qsort((void *) fnames, (size_s) fcnt, sizeof(struct fileinfo), + (qsort_cmp) comp_names); +#if defined(THREAD) && !defined(HAVE_READDIR_R) + pthread_mutex_unlock(&THR_LOCK_open); +#endif + DBUG_RETURN((MY_DIR *) buffer); + + error: +#if defined(THREAD) && !defined(HAVE_READDIR_R) + pthread_mutex_unlock(&THR_LOCK_open); +#endif + my_errno=errno; + if (dirp) + (void) closedir(dirp); + if (MyFlags & (MY_FAE+MY_WME)) + my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,my_errno); + DBUG_RETURN((MY_DIR *) NULL); +} /* my_dir */ + + +/* + * Convert from directory name to filename. + * On VMS: + * xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1 + * xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1 + * On UNIX, it's simple: just make sure there is a terminating / + + * Returns pointer to dst; + */ + +my_string directory_file_name (my_string dst, const char *src) +{ +#ifndef VMS + + /* Process as Unix format: just remove test the final slash. */ + + my_string end; + + if (src[0] == 0) + src= (char*) "."; /* Use empty as current */ + end=strmov(dst, src); + if (end[-1] != FN_LIBCHAR) + { + end[0]=FN_LIBCHAR; /* Add last '/' */ + end[1]='\0'; + } + return dst; + +#else /* VMS */ + + long slen; + long rlen; + my_string ptr, rptr; + char bracket; + struct FAB fab = cc$rms_fab; + struct NAM nam = cc$rms_nam; + char esa[NAM$C_MAXRSS]; + + if (! src[0]) + src="[.]"; /* Empty is == current dir */ + + slen = strlen (src) - 1; + if (src[slen] == FN_C_AFTER_DIR || src[slen] == FN_C_AFTER_DIR_2 || + src[slen] == FN_DEVCHAR) + { + /* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */ + fab.fab$l_fna = src; + fab.fab$b_fns = slen + 1; + fab.fab$l_nam = &nam; + fab.fab$l_fop = FAB$M_NAM; + + nam.nam$l_esa = esa; + nam.nam$b_ess = sizeof esa; + nam.nam$b_nop |= NAM$M_SYNCHK; + + /* We call SYS$PARSE to handle such things as [--] for us. */ + if (SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL) + { + slen = nam.nam$b_esl - 1; + if (esa[slen] == ';' && esa[slen - 1] == '.') + slen -= 2; + esa[slen + 1] = '\0'; + src = esa; + } + if (src[slen] != FN_C_AFTER_DIR && src[slen] != FN_C_AFTER_DIR_2) + { + /* what about when we have logical_name:???? */ + if (src[slen] == FN_DEVCHAR) + { /* Xlate logical name and see what we get */ + VOID(strmov(dst,src)); + dst[slen] = 0; /* remove colon */ + if (!(src = getenv (dst))) + return dst; /* Can't translate */ + + /* should we jump to the beginning of this procedure? + Good points: allows us to use logical names that xlate + to Unix names, + Bad points: can be a problem if we just translated to a device + name... + For now, I'll punt and always expect VMS names, and hope for + the best! */ + + slen = strlen (src) - 1; + if (src[slen] != FN_C_AFTER_DIR && src[slen] != FN_C_AFTER_DIR_2) + { /* no recursion here! */ + VOID(strmov(dst, src)); + return(dst); + } + } + else + { /* not a directory spec */ + VOID(strmov(dst, src)); + return(dst); + } + } + + bracket = src[slen]; /* End char */ + if (!(ptr = strchr (src, bracket - 2))) + { /* no opening bracket */ + VOID(strmov (dst, src)); + return dst; + } + if (!(rptr = strrchr (src, '.'))) + rptr = ptr; + slen = rptr - src; + VOID(strmake (dst, src, slen)); + + if (*rptr == '.') + { /* Put bracket and add */ + dst[slen++] = bracket; /* (rptr+1) after this */ + } + else + { + /* If we have the top-level of a rooted directory (i.e. xx:[000000]), + then translate the device and recurse. */ + + if (dst[slen - 1] == ':' + && dst[slen - 2] != ':' /* skip decnet nodes */ + && strcmp(src + slen, "[000000]") == 0) + { + dst[slen - 1] = '\0'; + if ((ptr = getenv (dst)) + && (rlen = strlen (ptr) - 1) > 0 + && (ptr[rlen] == FN_C_AFTER_DIR || ptr[rlen] == FN_C_AFTER_DIR_2) + && ptr[rlen - 1] == '.') + { + VOID(strmov(esa,ptr)); + esa[rlen - 1] = FN_C_AFTER_DIR; + esa[rlen] = '\0'; + return (directory_file_name (dst, esa)); + } + else + dst[slen - 1] = ':'; + } + VOID(strmov(dst+slen,"[000000]")); + slen += 8; + } + VOID(strmov(strmov(dst+slen,rptr+1)-1,".DIR.1")); + return dst; + } + VOID(strmov(dst, src)); + if (dst[slen] == '/' && slen > 1) + dst[slen] = 0; + return dst; +#endif /* VMS */ +} /* directory_file_name */ + +#elif defined(WIN32) + +/* +***************************************************************************** +** Read long filename using windows rutines +***************************************************************************** +*/ + +MY_DIR *my_dir(path, MyFlags) +const char *path; +myf MyFlags; +{ + struct fileinfo *fnames; + char *buffer, *obuffer, *tempptr; + int eof,i,fcnt,firstfcnt,length,maxfcnt; + uint size; +#ifdef __BORLANDC__ + struct ffblk find; +#else + struct _finddata_t find; +#endif + ushort mode; + char tmp_path[FN_REFLEN],*tmp_file,attrib; + my_ptrdiff_t diff; + long handle; + DBUG_ENTER("my_dir"); + DBUG_PRINT("my",("path: '%s' stat: %d MyFlags: %d",path,MyFlags)); + + /* Put LIB-CHAR as last path-character if not there */ + + tmp_file=tmp_path; + if (!*path) + *tmp_file++ ='.'; /* From current dir */ + tmp_file= strmov(tmp_file,path); + if (tmp_file[-1] == FN_DEVCHAR) + *tmp_file++= '.'; /* From current dev-dir */ + if (tmp_file[-1] != FN_LIBCHAR) + *tmp_file++ =FN_LIBCHAR; + tmp_file[0]='*'; /* MSDOS needs this !??? */ + tmp_file[1]='.'; + tmp_file[2]='*'; + tmp_file[3]='\0'; + +#ifdef __BORLANDC__ + if ((handle= findfirst(tmp_path,&find,0)) == -1L) + goto error; +#else + if ((handle=_findfirst(tmp_path,&find)) == -1L) + goto error; +#endif + + size = STARTSIZE; + firstfcnt = maxfcnt = (size - sizeof(MY_DIR)) / + (sizeof(struct fileinfo) + FN_LEN); + if ((buffer = (char *) my_malloc(size, MyFlags)) == 0) + goto error; + fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR)); + tempptr = (char *) (fnames + maxfcnt); + + fcnt = 0; + for (;;) + { + do + { + fnames[fcnt].name = tempptr; +#ifdef __BORLANDC__ + tempptr = strmov(tempptr,find.ff_name) + 1; + fnames[fcnt].mystat.st_size=find.ff_fsize; + fnames[fcnt].mystat.st_uid=fnames[fcnt].mystat.st_gid=0; + mode=MY_S_IREAD; attrib=find.ff_attrib; +#else + tempptr = strmov(tempptr,find.name) + 1; + fnames[fcnt].mystat.st_size=find.size; + fnames[fcnt].mystat.st_uid=fnames[fcnt].mystat.st_gid=0; + mode=MY_S_IREAD; attrib=find.attrib; +#endif + if (!(attrib & _A_RDONLY)) + mode|=MY_S_IWRITE; + if (attrib & _A_SUBDIR) + mode|=MY_S_IFDIR; + fnames[fcnt].mystat.st_mode=mode; +#ifdef __BORLANDC__ + fnames[fcnt].mystat.st_mtime=((uint32) find.ff_ftime); +#else + fnames[fcnt].mystat.st_mtime=((uint32) find.time_write); +#endif + ++fcnt; +#ifdef __BORLANDC__ + } while ((eof= findnext(&find)) == 0 && fcnt < maxfcnt); +#else + } while ((eof= _findnext(handle,&find)) == 0 && fcnt < maxfcnt); +#endif + + DBUG_PRINT("test",("eof: %d errno: %d",eof,errno)); + if (eof) + break; + size += STARTSIZE; obuffer = buffer; + if (!(buffer = (char *) my_realloc((gptr) buffer, size, + MyFlags | MY_FREE_ON_ERROR))) + goto error; + length= sizeof(struct fileinfo ) * firstfcnt; + diff= PTR_BYTE_DIFF(buffer , obuffer) +length; + fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR)); + tempptr= ADD_TO_PTR(tempptr,diff,char*); + for (i = 0; i < maxfcnt; i++) + fnames[i].name = ADD_TO_PTR(fnames[i].name,diff,char*); + + /* move filenames upp a bit */ + maxfcnt += firstfcnt; + bmove_upp(tempptr,ADD_TO_PTR(tempptr,-length,char*), + (int) PTR_BYTE_DIFF(tempptr,fnames+maxfcnt)); + } + { + MY_DIR * s = (MY_DIR *) buffer; + s->number_off_files = (uint) fcnt; + s->dir_entry = fnames; + } + if (!(MyFlags & MY_DONT_SORT)) + qsort(fnames,fcnt,sizeof(struct fileinfo),(qsort_cmp) comp_names); +#ifndef __BORLANDC__ + _findclose(handle); +#endif + DBUG_RETURN((MY_DIR *) buffer); + +error: + my_errno=errno; +#ifndef __BORLANDC__ + if (handle != -1) + _findclose(handle); +#endif + if (MyFlags & MY_FAE+MY_WME) + my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno); + DBUG_RETURN((MY_DIR *) NULL); +} /* my_dir */ + +#else /* MSDOS and not WIN32 */ + + +/****************************************************************************** +** At MSDOS you always get stat of files, but time is in packed MSDOS-format +******************************************************************************/ + +MY_DIR *my_dir(path, MyFlags) +const char *path; +myf MyFlags; +{ + struct fileinfo *fnames; + char *buffer, *obuffer, *tempptr; + int eof,i,fcnt,firstfcnt,length,maxfcnt; + uint size; + struct find_t find; + ushort mode; + char tmp_path[FN_REFLEN],*tmp_file,attrib; + my_ptrdiff_t diff; + DBUG_ENTER("my_dir"); + DBUG_PRINT("my",("path: '%s' stat: %d MyFlags: %d",path,MyFlags)); + + /* Put LIB-CHAR as last path-character if not there */ + + tmp_file=tmp_path; + if (!*path) + *tmp_file++ ='.'; /* From current dir */ + tmp_file= strmov(tmp_file,path); + if (tmp_file[-1] == FN_DEVCHAR) + *tmp_file++= '.'; /* From current dev-dir */ + if (tmp_file[-1] != FN_LIBCHAR) + *tmp_file++ =FN_LIBCHAR; + tmp_file[0]='*'; /* MSDOS needs this !??? */ + tmp_file[1]='.'; + tmp_file[2]='*'; + tmp_file[3]='\0'; + + if (_dos_findfirst(tmp_path,_A_NORMAL | _A_SUBDIR, &find)) + goto error; + + size = STARTSIZE; + firstfcnt = maxfcnt = (size - sizeof(MY_DIR)) / + (sizeof(struct fileinfo) + FN_LEN); + if ((buffer = (char *) my_malloc(size, MyFlags)) == 0) + goto error; + fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR)); + tempptr = (char *) (fnames + maxfcnt); + + fcnt = 0; + for (;;) + { + do + { + fnames[fcnt].name = tempptr; + tempptr = strmov(tempptr,find.name) + 1; + fnames[fcnt].mystat.st_size=find.size; + fnames[fcnt].mystat.st_uid=fnames[fcnt].mystat.st_gid=0; + mode=MY_S_IREAD; attrib=find.attrib; + if (!(attrib & _A_RDONLY)) + mode|=MY_S_IWRITE; + if (attrib & _A_SUBDIR) + mode|=MY_S_IFDIR; + fnames[fcnt].mystat.st_mode=mode; + fnames[fcnt].mystat.st_mtime=((uint32) find.wr_date << 16) + + find.wr_time; + ++fcnt; + } while ((eof= _dos_findnext(&find)) == 0 && fcnt < maxfcnt); + + DBUG_PRINT("test",("eof: %d errno: %d",eof,errno)); + if (eof) + break; + size += STARTSIZE; obuffer = buffer; + if (!(buffer = (char *) my_realloc((gptr) buffer, size, + MyFlags | MY_FREE_ON_ERROR))) + goto error; + length= sizeof(struct fileinfo ) * firstfcnt; + diff= PTR_BYTE_DIFF(buffer , obuffer) +length; + fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR)); + tempptr= ADD_TO_PTR(tempptr,diff,char*); + for (i = 0; i < maxfcnt; i++) + fnames[i].name = ADD_TO_PTR(fnames[i].name,diff,char*); + + /* move filenames upp a bit */ + maxfcnt += firstfcnt; + bmove_upp(tempptr,ADD_TO_PTR(tempptr,-length,char*), + (int) PTR_BYTE_DIFF(tempptr,fnames+maxfcnt)); + } + { + MY_DIR * s = (MY_DIR *) buffer; + s->number_off_files = (uint) fcnt; + s->dir_entry = fnames; + } + if (!(MyFlags & MY_DONT_SORT)) + qsort(fnames,fcnt,sizeof(struct fileinfo),(qsort_cmp) comp_names); + DBUG_RETURN((MY_DIR *) buffer); + +error: + if (MyFlags & MY_FAE+MY_WME) + my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno); + DBUG_RETURN((MY_DIR *) NULL); +} /* my_dir */ + +#endif /* WIN32 && MSDOS */ + +/**************************************************************************** +** File status +** Note that MY_STAT is assumed to be same as struct stat +****************************************************************************/ + +int my_fstat(int Filedes, MY_STAT *stat_area, myf MyFlags ) +{ + DBUG_ENTER("my_fstat"); + DBUG_PRINT("my",("fd: %d MyFlags: %d",Filedes,MyFlags)); + DBUG_RETURN(fstat(Filedes, (struct stat *) stat_area)); +} + +MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags) +{ + int m_used; + DBUG_ENTER("my_stat"); + DBUG_PRINT("my", ("path: '%s', stat_area: %lx, MyFlags: %d", path, + (byte *) stat_area, my_flags)); + + if ((m_used= (stat_area == NULL))) + if (!(stat_area = (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags))) + goto error; + if ( ! stat((my_string) path, (struct stat *) stat_area) ) + DBUG_RETURN(stat_area); + my_errno=errno; + if (m_used) /* Free if new area */ + my_free((gptr) stat_area,MYF(0)); + +error: + if (my_flags & (MY_FAE+MY_WME)) + { + my_error(EE_STAT, MYF(ME_BELL+ME_WAITTANG),path,my_errno); + DBUG_RETURN((MY_STAT *) NULL); + } + DBUG_RETURN((MY_STAT *) NULL); +} /* my_stat */ + diff --git a/mysys/my_lock.c b/mysys/my_lock.c new file mode 100644 index 00000000000..4f1506f20cf --- /dev/null +++ b/mysys/my_lock.c @@ -0,0 +1,161 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include "mysys_err.h" +#include <errno.h> +#undef MY_HOW_OFTEN_TO_ALARM +#define MY_HOW_OFTEN_TO_ALARM ((int) my_time_to_wait_for_lock) +#ifdef NO_ALARM_LOOP +#undef NO_ALARM_LOOP +#endif +#include <my_alarm.h> +#ifdef __WIN__ +#include <sys/locking.h> +#endif +#ifdef __EMX__ +#define INCL_BASE +#define INCL_NOPMAPI +#include <os2emx.h> +#endif + +#ifdef HAVE_FCNTL +static struct flock lock; /* Must be static for sun-sparc */ +#endif + + /* Lock a part of a file */ + +int my_lock(File fd, int locktype, my_off_t start, my_off_t length, + myf MyFlags) +{ +#ifdef __EMX__ + FILELOCK LockArea = {0,0}, UnlockArea = {0,0}; + APIRET rc = 0; + fpos_t oldpos; + int lockflags = 0; +#endif +#ifdef HAVE_FCNTL + int value; + ALARM_VARIABLES; +#endif + DBUG_ENTER("my_lock"); + DBUG_PRINT("my",("Fd: %d Op: %d start: %ld Length: %ld MyFlags: %d", + fd,locktype,(long) start,(long) length,MyFlags)); +#ifdef VMS + DBUG_RETURN(0); +#else + if (my_disable_locking) + DBUG_RETURN(0); +#if defined(__EMX__) + if (locktype == F_UNLCK) { + UnlockArea.lOffset = start; + if (length) + UnlockArea.lRange = length; + else + UnlockArea.lRange = 0x7FFFFFFFL; + } else + if (locktype == F_RDLCK || locktype == F_WRLCK) { + if (locktype == F_RDLCK) lockflags |= 1; + LockArea.lOffset = start; + if (length) + LockArea.lRange = length; + else + LockArea.lRange = 0x7FFFFFFFL; + } else { + my_errno = EINVAL; + DBUG_RETURN(-1); + } + if (!LockArea.lRange && !UnlockArea.lRange) + DBUG_RETURN(0); + if (MyFlags & MY_DONT_WAIT) { + if (!(rc = DosSetFileLocks(fd,&UnlockArea,&LockArea,0,lockflags))) + DBUG_RETURN(0); /* Lock was OK */ + if (rc == 175 && locktype == F_RDLCK) { + lockflags &= ~1; + rc = DosSetFileLocks(fd,&UnlockArea,&LockArea,0,lockflags); + } + if (rc == 33) { /* Lock Violation */ + DBUG_PRINT("info",("Was locked, trying with timeout")); + rc = DosSetFileLocks(fd,&UnlockArea,&LockArea,MY_HOW_OFTEN_TO_ALARM * 1000,lockflags); + } + if (!rc) DBUG_RETURN(0); + if (rc == 33) errno = EAGAIN; + else { + errno = EINVAL; + printf("Error: DosSetFileLocks() == %d\n",rc); + } + } else { + while (rc = DosSetFileLocks(fd,&UnlockArea,&LockArea, + MY_HOW_OFTEN_TO_ALARM * 1000,lockflags) && (rc == 33 || rc == 175)) { + printf("."); + if (rc == 175) lockflags &= ~1; + } + if (!rc) DBUG_RETURN(0); + errno = EINVAL; + printf("Error: DosSetFileLocks() == %d\n",rc); + } +#elif defined(HAVE_LOCKING) + if (MyFlags & MY_SEEK_NOT_DONE) + VOID(my_seek(fd,start,MY_SEEK_SET,MYF(MyFlags & ~MY_SEEK_NOT_DONE))); + if (!locking(fd,locktype,(ulong) length) || errno == EINVAL) + DBUG_RETURN(0); +#else +#if defined(HAVE_FCNTL) + lock.l_type= (short) locktype; + lock.l_whence=0L; + lock.l_start=(long) start; + lock.l_len=(long) length; + if (MyFlags & MY_DONT_WAIT) + { + if (fcntl(fd,F_SETLK,&lock) != -1) /* Check if we can lock */ + DBUG_RETURN(0); /* Ok, file locked */ + DBUG_PRINT("info",("Was locked, trying with alarm")); + ALARM_INIT; + while ((value=fcntl(fd,F_SETLKW,&lock)) && ! ALARM_TEST && + errno == EINTR) + { /* Setup again so we don`t miss it */ + ALARM_REINIT; + } + ALARM_END; + if (value != -1) + DBUG_RETURN(0); + if (errno == EINTR) + errno=EAGAIN; + } + else if (fcntl(fd,F_SETLKW,&lock) != -1) /* Wait until a lock */ + DBUG_RETURN(0); +#else + if (MyFlags & MY_SEEK_NOT_DONE) + VOID(my_seek(fd,start,MY_SEEK_SET,MYF(MyFlags & ~MY_SEEK_NOT_DONE))); + if (lockf(fd,locktype,length) != -1) + DBUG_RETURN(0); +#endif /* HAVE_FCNTL */ +#endif /* HAVE_LOCKING */ + + /* We got an error. We don't want EACCES errors */ + my_errno=(errno == EACCES) ? EAGAIN : errno ? errno : -1; + if (MyFlags & MY_WME) + { + if (locktype == F_UNLCK) + my_error(EE_CANTUNLOCK,MYF(ME_BELL+ME_WAITTANG),my_errno); + else + my_error(EE_CANTLOCK,MYF(ME_BELL+ME_WAITTANG),my_errno); + } + DBUG_PRINT("error",("my_errno: %d (%d)",my_errno,errno)); + DBUG_RETURN(-1); +#endif /* ! VMS */ +} /* my_lock */ diff --git a/mysys/my_lockmem.c b/mysys/my_lockmem.c new file mode 100644 index 00000000000..9c77c885797 --- /dev/null +++ b/mysys/my_lockmem.c @@ -0,0 +1,101 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Alloc a block of locked memory */ + +#include "mysys_priv.h" +#include "mysys_err.h" +#include <my_list.h> + +#ifdef HAVE_MLOCK +#include <sys/mman.h> + +struct st_mem_list +{ + LIST list; + byte *page; + uint size; +}; + +LIST *mem_list; + +byte *my_malloc_lock(uint size,myf MyFlags) +{ + int success; + uint pagesize=sysconf(_SC_PAGESIZE); + byte *ptr; + struct st_mem_list *element; + DBUG_ENTER("my_malloc_lock"); + + size=((size-1) & ~(pagesize-1))+pagesize; + if (!(ptr=memalign(pagesize,size))) + { + if (MyFlags & (MY_FAE+MY_WME)) + my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),size); + DBUG_RETURN(0); + } + success = mlock((byte*) ptr,size); + if (success != 0 && geteuid() == 0) + { + DBUG_PRINT("warning",("Failed to lock memory. errno %d\n", + errno)); + fprintf(stderr, "Warning: Failed to lock memory. errno %d\n", + errno); + } + else + { + /* Add block in a list for munlock */ + if (!(element=(struct st_mem_list*) my_malloc(sizeof(*element),MyFlags))) + { + VOID(munlock((byte*) ptr,size)); + free(ptr); + DBUG_RETURN(0); + } + element->list.data=(byte*) element; + element->page=ptr; + element->size=size; + pthread_mutex_lock(&THR_LOCK_malloc); + mem_list=list_add(mem_list,&element->list); + pthread_mutex_unlock(&THR_LOCK_malloc); + } + DBUG_RETURN(ptr); +} + + +void my_free_lock(byte *ptr,myf Myflags __attribute__((unused))) +{ + LIST *list; + struct st_mem_list *element=0; + + pthread_mutex_lock(&THR_LOCK_malloc); + for (list=mem_list ; list ; list=list->next) + { + element=(struct st_mem_list*) list->data; + if (ptr == element->page) + { /* Found locked mem */ + VOID(munlock((byte*) ptr,element->size)); + mem_list=list_delete(mem_list,list); + break; + } + } + pthread_mutex_unlock(&THR_LOCK_malloc); + if (element) + my_free((gptr) element,MYF(0)); + free(ptr); /* Free even if not locked */ +} + +#endif /* HAVE_MLOCK */ diff --git a/mysys/my_lread.c b/mysys/my_lread.c new file mode 100644 index 00000000000..c3b8a6704c3 --- /dev/null +++ b/mysys/my_lread.c @@ -0,0 +1,54 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include "mysys_err.h" + + /* Read a chunk of bytes from a file */ + +uint32 my_lread(int Filedes, byte *Buffer, uint32 Count, myf MyFlags) + /* File descriptor */ + /* Buffer must be at least count bytes */ + /* Max number of bytes returnd */ + /* Flags on what to do on error */ +{ + uint32 readbytes; + DBUG_ENTER("my_lread"); + DBUG_PRINT("my",("Fd: %d Buffer: %ld Count: %ld MyFlags: %d", + Filedes, Buffer, Count, MyFlags)); + + /* Temp hack to get count to int32 while read wants int */ + if ((readbytes = (uint32) read(Filedes, Buffer, (size_t) Count)) != Count) + { + my_errno=errno; + if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) + { + if (readbytes == MY_FILE_ERROR) + my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), + my_filename(Filedes),errno); + else + if (MyFlags & (MY_NABP | MY_FNABP)) + my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), + my_filename(Filedes),errno); + } + if (readbytes == MY_FILE_ERROR || MyFlags & (MY_NABP | MY_FNABP)) + DBUG_RETURN((uint32) -1); /* Return med felkod */ + } + if (MyFlags & (MY_NABP | MY_FNABP)) + DBUG_RETURN(0); /* Ok vid l{sning */ + DBUG_RETURN(readbytes); +} /* my_lread */ diff --git a/mysys/my_lwrite.c b/mysys/my_lwrite.c new file mode 100644 index 00000000000..201c36f619c --- /dev/null +++ b/mysys/my_lwrite.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include "mysys_err.h" + + /* Write a chunk of bytes to a file */ + +uint32 my_lwrite(int Filedes, const byte *Buffer, uint32 Count, myf MyFlags) +{ + uint32 writenbytes; + DBUG_ENTER("my_lwrite"); + DBUG_PRINT("my",("Fd: %d Buffer: %lx Count: %ld MyFlags: %d", + Filedes, Buffer, Count, MyFlags)); + + /* Temp hack to get count to int32 while write wants int */ + if ((writenbytes = (uint32) write(Filedes, Buffer, (size_t) Count)) != Count) + { + my_errno=errno; + if (writenbytes == (uint32) -1 || MyFlags & (MY_NABP | MY_FNABP)) + { + if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) + { + my_error(EE_WRITE, MYF(ME_BELL+ME_WAITTANG), + my_filename(Filedes),errno); + } + DBUG_RETURN((uint32) -1); /* Return med felkod */ + } + } + if (MyFlags & (MY_NABP | MY_FNABP)) + DBUG_RETURN(0); /* Ok vid l{sning */ + DBUG_RETURN(writenbytes); +} /* my_lwrite */ diff --git a/mysys/my_malloc.c b/mysys/my_malloc.c new file mode 100644 index 00000000000..6cae6fe3a4d --- /dev/null +++ b/mysys/my_malloc.c @@ -0,0 +1,84 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#ifdef SAFEMALLOC /* We don't need SAFEMALLOC here */ +#undef SAFEMALLOC +#endif + +#include "mysys_priv.h" +#include "mysys_err.h" +#include <m_string.h> + + /* My memory allocator */ + +gptr my_malloc(unsigned int Size, myf MyFlags) +{ + gptr point; + DBUG_ENTER("my_malloc"); + DBUG_PRINT("my",("Size: %u MyFlags: %d",Size, MyFlags)); + + if (!Size) + Size=1; /* Safety */ + if ((point = malloc(Size)) == NULL) + { + my_errno=errno; + if (MyFlags & MY_FAE) + error_handler_hook=fatal_error_handler_hook; + if (MyFlags & (MY_FAE+MY_WME)) + my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),Size); + if (MyFlags & MY_FAE) + exit(1); + } + else if (MyFlags & MY_ZEROFILL) + bzero(point,Size); + DBUG_PRINT("exit",("ptr: %lx",point)); + DBUG_RETURN(point); +} /* my_malloc */ + + + /* Free memory allocated with my_malloc */ + /*ARGSUSED*/ + +void my_no_flags_free(gptr ptr) +{ + DBUG_ENTER("my_free"); + DBUG_PRINT("my",("ptr: %lx",ptr)); + if (ptr) + free(ptr); + DBUG_VOID_RETURN; +} /* my_free */ + + + /* malloc and copy */ + +gptr my_memdup(const byte *from, uint length, myf MyFlags) +{ + gptr ptr; + if ((ptr=my_malloc(length,MyFlags)) != 0) + memcpy((byte*) ptr, (byte*) from,(size_t) length); + return(ptr); +} + + +my_string my_strdup(const char *from, myf MyFlags) +{ + gptr ptr; + uint length=(uint) strlen(from)+1; + if ((ptr=my_malloc(length,MyFlags)) != 0) + memcpy((byte*) ptr, (byte*) from,(size_t) length); + return((my_string) ptr); +} diff --git a/mysys/my_messnc.c b/mysys/my_messnc.c new file mode 100644 index 00000000000..0dd3be5ba98 --- /dev/null +++ b/mysys/my_messnc.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" + +int my_message_no_curses(uint error __attribute__((unused)), + const char *str, myf MyFlags) +{ + DBUG_ENTER("my_message_no_curses"); + DBUG_PRINT("enter",("message: %s",str)); + (void) fflush(stdout); + if (MyFlags & ME_BELL) + (void) fputc('\007',stderr); /* Bell */ + if (my_progname) + { + (void)fputs(my_progname,stderr); (void)fputs(": ",stderr); + } + (void)fputs(str,stderr); + (void)fputc('\n',stderr); + (void)fflush(stderr); + DBUG_RETURN(0); +} diff --git a/mysys/my_mkdir.c b/mysys/my_mkdir.c new file mode 100644 index 00000000000..773cd26cb03 --- /dev/null +++ b/mysys/my_mkdir.c @@ -0,0 +1,44 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include "mysys_err.h" +#include <sys/types.h> +#include <sys/stat.h> +#ifdef __WIN__ +#include <direct.h> +#endif + +int my_mkdir(const char *dir, int Flags, myf MyFlags) +{ + DBUG_ENTER("my_dir"); + DBUG_PRINT("enter",("dir: %s",dir)); + +#ifdef __WIN__ + if (mkdir(dir)) +#else + if (mkdir((char*) dir, Flags & my_umask_dir)) +#endif + { + my_errno=errno; + DBUG_PRINT("error",("error %d when creating direcory %s",my_errno,dir)); + if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) + my_error(EE_CANT_MKDIR, MYF(ME_BELL+ME_WAITTANG), dir, my_errno); + DBUG_RETURN(-1); + } + DBUG_RETURN(0); +} diff --git a/mysys/my_net.c b/mysys/my_net.c new file mode 100644 index 00000000000..1c91f7ff802 --- /dev/null +++ b/mysys/my_net.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* thread safe version of some common functions */ + +#include "mysys_priv.h" +#include <m_string.h> + +/* for thread safe my_inet_ntoa */ +#if !defined(MSDOS) && !defined(__WIN__) +#include <netdb.h> +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +#endif /* !defined(MSDOS) && !defined(__WIN__) */ + +#ifndef THREAD +#define pthread_mutex_lock(A) +#define pthread_mutex_unlock(A) +#endif + +void my_inet_ntoa(struct in_addr in, char *buf) +{ + char *ptr; + pthread_mutex_lock(&THR_LOCK_net); + ptr=inet_ntoa(in); + strmov(buf,ptr); + pthread_mutex_unlock(&THR_LOCK_net); +} diff --git a/mysys/my_once.c b/mysys/my_once.c new file mode 100644 index 00000000000..0b8b5addc16 --- /dev/null +++ b/mysys/my_once.c @@ -0,0 +1,88 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Not MT-SAFE */ + +#ifdef SAFEMALLOC /* We don't need SAFEMALLOC here */ +#undef SAFEMALLOC +#endif + +#include "mysys_priv.h" +#include "my_static.h" +#include "mysys_err.h" + + /* alloc for things we don't nead to free */ + /* No DBUG_ENTER... here to get smaller dbug-startup */ + +gptr my_once_alloc(unsigned int Size, myf MyFlags) +{ + uint get_size,max_left; + gptr point; + reg1 USED_MEM *next; + reg2 USED_MEM **prev; + + Size= ALIGN_SIZE(Size); + prev= &my_once_root_block; + max_left=0; + for (next=my_once_root_block ; next && next->left < Size ; next= next->next) + { + if (next->left > max_left) + max_left=next->left; + prev= &next->next; + } + if (! next) + { /* Time to alloc new block */ + get_size= Size+ALIGN_SIZE(sizeof(USED_MEM)); + if (max_left*4 < my_once_extra && get_size < my_once_extra) + get_size=my_once_extra; /* Normal alloc */ + + if ((next = (USED_MEM*) malloc(get_size)) == 0) + { + my_errno=errno; + if (MyFlags & (MY_FAE+MY_WME)) + my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),get_size); + return((gptr) 0); + } + DBUG_PRINT("test",("my_once_malloc %u byte malloced",get_size)); + next->next= 0; + next->size= get_size; + next->left= get_size-ALIGN_SIZE(sizeof(USED_MEM)); + *prev=next; + } + point= (gptr) ((char*) next+ (next->size-next->left)); + next->left-= Size; + + return(point); +} /* my_once_alloc */ + + + /* deallocate everything used by my_once_alloc */ + +void my_once_free(void) +{ + reg1 USED_MEM *next,*old; + DBUG_ENTER("my_once_free"); + + for (next=my_once_root_block ; next ; ) + { + old=next; next= next->next ; + free((gptr) old); + } + my_once_root_block=0; + + DBUG_VOID_RETURN; +} /* my_once_free */ diff --git a/mysys/my_open.c b/mysys/my_open.c new file mode 100644 index 00000000000..ef1db41e3f5 --- /dev/null +++ b/mysys/my_open.c @@ -0,0 +1,97 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#define USES_TYPES +#include "mysys_priv.h" +#include "mysys_err.h" +#include <errno.h> +#if defined(MSDOS) || defined(__WIN__) +#include <share.h> +#endif + + /* Open a file */ + +File my_open(const char *FileName, int Flags, myf MyFlags) + /* Path-name of file */ + /* Read | write .. */ + /* Special flags */ +{ + File fd; + DBUG_ENTER("my_open"); + DBUG_PRINT("my",("Name: '%s' Flags: %d MyFlags: %d", + FileName, Flags, MyFlags)); +#if defined(MSDOS) || defined(__WIN__) + if (Flags & O_SHARE) + fd = sopen((my_string) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO); + else + fd = open((my_string) FileName, Flags | O_BINARY); +#elif !defined(NO_OPEN_3) + fd = open(FileName, Flags, 0); /* Normal unix */ +#else + fd = open((my_string) FileName, Flags); +#endif + + if ((int) fd >= 0) + { + if ((int) fd >= MY_NFILE) + DBUG_RETURN(fd); /* safeguard */ + pthread_mutex_lock(&THR_LOCK_open); + if ((my_file_info[fd].name = (char*) my_strdup(FileName,MyFlags))) + { + my_file_opened++; + my_file_info[fd].type = FILE_BY_OPEN; + pthread_mutex_unlock(&THR_LOCK_open); + DBUG_PRINT("exit",("fd: %d",fd)); + DBUG_RETURN(fd); + } + pthread_mutex_unlock(&THR_LOCK_open); + (void) my_close(fd,MyFlags); + my_errno=ENOMEM; + } + else + my_errno=errno; + DBUG_PRINT("error",("Got error %d on open",my_errno)); + if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) + my_error(EE_FILENOTFOUND, MYF(ME_BELL+ME_WAITTANG), FileName,my_errno); + DBUG_RETURN(fd); +} /* my_open */ + + + /* Close a file */ + +int my_close(File fd, myf MyFlags) +{ + int err; + DBUG_ENTER("my_close"); + DBUG_PRINT("my",("fd: %d MyFlags: %d",fd, MyFlags)); + + pthread_mutex_lock(&THR_LOCK_open); + if ((err = close(fd)) != 0) + { + my_errno=errno; + if (MyFlags & (MY_FAE | MY_WME)) + my_error(EE_BADCLOSE, MYF(ME_BELL+ME_WAITTANG),my_filename(fd),errno); + } + if ((uint) fd < MY_NFILE && my_file_info[fd].type != UNOPEN) + { + my_file_opened--; + my_free(my_file_info[fd].name, MYF(0)); + my_file_info[fd].type = UNOPEN; + } + pthread_mutex_unlock(&THR_LOCK_open); + DBUG_RETURN(err); +} /* my_close */ diff --git a/mysys/my_pread.c b/mysys/my_pread.c new file mode 100644 index 00000000000..1190f2cc81b --- /dev/null +++ b/mysys/my_pread.c @@ -0,0 +1,137 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include "mysys_err.h" +#include <errno.h> +#ifdef HAVE_PREAD +#include <unistd.h> +#endif + + /* Read a chunk of bytes from a file */ + +uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset, + myf MyFlags) +{ + uint readbytes; + DBUG_ENTER("my_pread"); + DBUG_PRINT("my",("Fd: %d Seek: %lu Buffer: %lx Count: %u MyFlags: %d", + Filedes, (ulong) offset, Buffer, Count, MyFlags)); + + for (;;) + { +#ifndef __WIN__ + errno=0; /* Linux doesn't reset this */ +#endif +#ifndef HAVE_PREAD + readbytes= (uint) -1; + if (lseek(Filedes, offset, MY_SEEK_SET) == -1L || + (readbytes = (uint) read(Filedes, Buffer, Count)) != Count) +#else + if ((readbytes = (uint) pread(Filedes, Buffer, Count, offset)) != Count) +#endif + { + my_errno=errno; + DBUG_PRINT("warning",("Read only %ld bytes off %ld from %d, errno: %d", + readbytes,Count,Filedes,my_errno)); +#ifdef THREAD + if (readbytes == 0 && errno == EINTR) + continue; /* Interrupted */ +#endif + if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) + { + if ((int) readbytes == -1) + my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), + my_filename(Filedes),my_errno); + else if (MyFlags & (MY_NABP | MY_FNABP)) + my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), + my_filename(Filedes),my_errno); + } + if ((int) readbytes == -1 || (MyFlags & (MY_FNABP | MY_NABP))) + DBUG_RETURN(MY_FILE_ERROR); /* Return with error */ + } + if (MyFlags & (MY_NABP | MY_FNABP)) + DBUG_RETURN(0); /* Ok vid l{sning */ + DBUG_RETURN(readbytes); /* purecov: inspected */ + } +} /* my_pread */ + + + /* Write a chunk of bytes to a file */ + +uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset, + myf MyFlags) +{ + uint writenbytes,errors; + ulong written; + DBUG_ENTER("my_pwrite"); + DBUG_PRINT("my",("Fd: %d Seek: %lu Buffer: %lx Count: %d MyFlags: %d", + Filedes, (ulong) offset,Buffer, Count, MyFlags)); + errors=0; written=0L; + + for (;;) + { +#ifndef HAVE_PREAD + writenbytes= (uint) -1; + if (lseek(Filedes, offset, MY_SEEK_SET) != -1L && + (writenbytes = (uint) write(Filedes, Buffer, Count)) == Count) +#else + if ((writenbytes = (uint) pwrite(Filedes, Buffer, Count,offset)) == Count) +#endif + break; + if ((int) writenbytes != -1) + { /* Safegueard */ + written+=writenbytes; + Buffer+=writenbytes; + Count-=writenbytes; + offset+=writenbytes; + } + my_errno=errno; + DBUG_PRINT("error",("Write only %d bytes",writenbytes)); +#ifndef NO_BACKGROUND +#ifdef THREAD + if (my_thread_var->abort) + MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */ +#endif + if (my_errno == ENOSPC && (MyFlags & MY_WAIT_IF_FULL)) + { + if (!(errors++ % MY_WAIT_GIVE_USER_A_MESSAGE)) + my_error(EE_DISK_FULL,MYF(ME_BELL | ME_NOREFRESH), + my_filename(Filedes)); + VOID(sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC)); + continue; + } + if ((writenbytes == 0 && my_errno == EINTR) || + (writenbytes > 0 && (uint) writenbytes != (uint) -1)) + continue; /* Retry */ +#endif + if (MyFlags & (MY_NABP | MY_FNABP)) + { + if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) + { + my_error(EE_WRITE, MYF(ME_BELL+ME_WAITTANG), + my_filename(Filedes),my_errno); + } + DBUG_RETURN(MY_FILE_ERROR); /* Error on read */ + } + else + break; /* Return bytes written */ + } + if (MyFlags & (MY_NABP | MY_FNABP)) + DBUG_RETURN(0); /* Want only errors */ + DBUG_RETURN(writenbytes+written); /* purecov: inspected */ +} /* my_write */ diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c new file mode 100644 index 00000000000..4bf3e5e702a --- /dev/null +++ b/mysys/my_pthread.c @@ -0,0 +1,476 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Functions to get threads more portable */ + +#include "mysys_priv.h" +#ifdef THREAD +#include <signal.h> +#include <m_string.h> +#include <thr_alarm.h> +#include <assert.h> +#if !defined(MSDOS) && !defined(__WIN__) +#include <netdb.h> +#endif + +#if (defined(__BSD__) || defined(_BSDI_VERSION)) && !defined(HAVE_mit_thread) +#define SCHED_POLICY SCHED_RR +#else +#define SCHED_POLICY SCHED_OTHER +#endif + +#ifndef my_pthread_setprio +void my_pthread_setprio(pthread_t thread_id,int prior) +{ +#ifdef HAVE_PTHREAD_SETSCHEDPARAM + struct sched_param tmp_sched_param; + bzero((char*) &tmp_sched_param,sizeof(tmp_sched_param)); + tmp_sched_param.sched_priority=prior; + VOID(pthread_setschedparam(thread_id,SCHED_POLICY,&tmp_sched_param)); +#endif +} +#endif + +#ifndef my_pthread_getprio +int my_pthread_getprio(pthread_t thread_id) +{ +#ifdef HAVE_PTHREAD_SETSCHEDPARAM + struct sched_param tmp_sched_param; + int policy; + if (!pthread_getschedparam(thread_id,&policy,&tmp_sched_param)) + { + DBUG_PRINT("thread",("policy: %d priority: %d", + policy,tmp_sched_param.sched_priority)); + return tmp_sched_param.sched_priority; + } +#endif + return -1; +} +#endif + +#ifndef my_pthread_attr_setprio +void my_pthread_attr_setprio(pthread_attr_t *attr, int priority) +{ +#ifdef HAVE_PTHREAD_SETSCHEDPARAM + struct sched_param tmp_sched_param; + bzero((char*) &tmp_sched_param,sizeof(tmp_sched_param)); + tmp_sched_param.sched_priority=priority; + VOID(pthread_attr_setschedparam(attr,&tmp_sched_param)); +#endif +} +#endif + + +/* To allow use of pthread_getspecific with two arguments */ + +#ifdef HAVE_NONPOSIX_PTHREAD_GETSPECIFIC +#undef pthread_getspecific +#ifdef HAVE_UNIXWARE7_THREADS +#define pthread_getspecific thr_getspecific +#endif + +void *my_pthread_getspecific_imp(pthread_key_t key) +{ + void *value; + if (pthread_getspecific(key,(void *) &value)) + return 0; + return value; +} +#endif + + +/* Some functions for RTS threads, AIX, Siemens Unix and UnixWare 7 + (and DEC OSF/1 3.2 too) */ + +int my_pthread_create_detached=1; + +#if defined(HAVE_NONPOSIX_SIGWAIT) || defined(HAVE_DEC_3_2_THREADS) + +int my_sigwait(sigset_t *set,int *sig) +{ + int signal=sigwait(set); + if (signal < 0) + return errno; + *sig=signal; + return 0; +} +#endif + +/* localtime_r for SCO 3.2V4.2 */ + +#ifndef HAVE_LOCALTIME_R + +extern pthread_mutex_t LOCK_localtime_r; + +struct tm *localtime_r(const time_t *clock, struct tm *res) +{ + struct tm *tmp; + pthread_mutex_lock(&LOCK_localtime_r); + tmp=localtime(clock); + *res= *tmp; + pthread_mutex_unlock(&LOCK_localtime_r); + return res; +} +#endif + + +/**************************************************************************** +** Replacement of sigwait if the system doesn't have one (like BSDI 3.0) +** +** Note: +** This version of sigwait() is assumed to called in a loop so the signalmask +** is permanently modified to reflect the signal set. This is done to get +** a much faster implementation. +** +** This implementation isn't thread safe: It assumes that only one +** thread is using sigwait. +** +** If one later supplies a different signal mask, all old signals that +** was used before are unblocked and set to SIGDFL. +** +** Author: Gary Wisniewski <garyw@spidereye.com.au>, much modified by Monty +****************************************************************************/ + +#if !defined(HAVE_SIGWAIT) && !defined(HAVE_mit_thread) && !defined(sigwait) && !defined(__WIN__) && !defined(HAVE_rts_threads) && !defined(HAVE_NONPOSIX_SIGWAIT) && !defined(HAVE_DEC_3_2_THREADS) + +#if !defined(DONT_USE_SIGSUSPEND) + +static sigset_t sigwait_set,rev_sigwait_set,px_recd; + +void px_handle_sig(int sig) +{ + sigaddset(&px_recd, sig); +} + + +void sigwait_setup(sigset_t *set) +{ + int i; + struct sigaction sact,sact1; + sigset_t unblock_mask; + + sact.sa_flags = 0; + sact.sa_handler = px_handle_sig; + memcpy_fixed(&sact.sa_mask,set,sizeof(*set)); /* handler isn't thread_safe */ + sigemptyset(&unblock_mask); + pthread_sigmask(SIG_UNBLOCK,(sigset_t*) 0,&rev_sigwait_set); + + for (i = 1; i <= sizeof(sigwait_set)*8; i++) + { + if (sigismember(set,i)) + { + sigdelset(&rev_sigwait_set,i); + if (!sigismember(&sigwait_set,i)) + sigaction(i, &sact, (struct sigaction*) 0); + } + else + { + sigdelset(&px_recd,i); /* Don't handle this */ + if (sigismember(&sigwait_set,i)) + { /* Remove the old handler */ + sigaddset(&unblock_mask,i); + sigdelset(&rev_sigwait_set,i); + sact1.sa_flags = 0; + sact1.sa_handler = SIG_DFL; + sigemptyset(&sact1.sa_mask); + sigaction(i, &sact1, 0); + } + } + } + memcpy_fixed(&sigwait_set,set,sizeof(*set)); + pthread_sigmask(SIG_BLOCK,(sigset_t*) set,(sigset_t*) 0); + pthread_sigmask(SIG_UNBLOCK,&unblock_mask,(sigset_t*) 0); +} + + +int sigwait(sigset_t *setp, int *sigp) +{ + if (memcmp(setp,&sigwait_set,sizeof(sigwait_set))) + sigwait_setup(setp); /* Init or change of set */ + + for (;;) + { + /* + This is a fast, not 100% portable implementation to find the signal. + Because the handler is blocked there should be at most 1 bit set, but + the specification on this is somewhat shady so we use a set instead a + single variable. + */ + + ulong *ptr= (ulong*) &px_recd; + ulong *end=ptr+sizeof(px_recd)/sizeof(ulong); + + for ( ; ptr != end ; ptr++) + { + if (*ptr) + { + ulong set= *ptr; + int found= (int) ((char*) ptr - (char*) &px_recd)*8+1; + while (!(set & 1)) + { + found++; + set>>=1; + } + *sigp=found; + sigdelset(&px_recd,found); + return 0; + } + } + sigsuspend(&rev_sigwait_set); + } + return 0; +} +#else /* !DONT_USE_SIGSUSPEND */ + +/**************************************************************************** +** Replacement of sigwait if the system doesn't have one (like BSDI 3.0) +** +** Note: +** This version of sigwait() is assumed to called in a loop so the signalmask +** is permanently modified to reflect the signal set. This is done to get +** a much faster implementation. +** +** This implementation uses a extra thread to handle the signals and one +** must always call sigwait() with the same signal mask! +** +** BSDI 3.0 NOTE: +** +** pthread_kill() doesn't work on a thread in a select() or sleep() loop? +** After adding the sleep to sigwait_thread, all signals are checked and +** delivered every second. This isn't that terrible performance vice, but +** someone should report this to BSDI and ask for a fix! +** Another problem is that when the sleep() ends, every select() in other +** threads are interrupted! +****************************************************************************/ + +static sigset_t pending_set; +static bool inited=0; +static pthread_cond_t COND_sigwait; +static pthread_mutex_t LOCK_sigwait; + + +void sigwait_handle_sig(int sig) +{ + pthread_mutex_lock(&LOCK_sigwait); + sigaddset(&pending_set, sig); + VOID(pthread_cond_signal(&COND_sigwait)); /* inform sigwait() about signal */ + pthread_mutex_unlock(&LOCK_sigwait); +} + +extern pthread_t alarm_thread; + +void *sigwait_thread(void *set_arg) +{ + sigset_t *set=(sigset_t*) set_arg; + + int i; + struct sigaction sact; + sact.sa_flags = 0; + sact.sa_handler = sigwait_handle_sig; + memcpy_fixed(&sact.sa_mask,set,sizeof(*set)); /* handler isn't thread_safe */ + sigemptyset(&pending_set); + + for (i = 1; i <= sizeof(pending_set)*8; i++) + { + if (sigismember(set,i)) + { + sigaction(i, &sact, (struct sigaction*) 0); + } + } + sigaddset(set,THR_CLIENT_ALARM); + pthread_sigmask(SIG_UNBLOCK,(sigset_t*) set,(sigset_t*) 0); + alarm_thread=pthread_self(); /* For thr_alarm */ + + for (;;) + { /* Wait for signals */ +#ifdef HAVE_NOT_BROKEN_SELECT + fd_set fd; + FD_ZERO(&fd); + select(0,&fd,0,0,0); +#else + sleep(1); /* Because of broken BSDI */ +#endif + } +} + + +int sigwait(sigset_t *setp, int *sigp) +{ + if (!inited) + { + pthread_attr_t thr_attr; + pthread_t sigwait_thread_id; + inited=1; + sigemptyset(&pending_set); + pthread_mutex_init(&LOCK_sigwait,NULL); + pthread_cond_init(&COND_sigwait,NULL); + + pthread_attr_init(&thr_attr); + pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); + pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); + pthread_attr_setstacksize(&thr_attr,8196); + my_pthread_attr_setprio(&thr_attr,100); /* Very high priority */ + VOID(pthread_create(&sigwait_thread_id,&thr_attr,sigwait_thread,setp)); + VOID(pthread_attr_destroy(&thr_attr)); + } + + pthread_mutex_lock(&LOCK_sigwait); + for (;;) + { + ulong *ptr= (ulong*) &pending_set; + ulong *end=ptr+sizeof(pending_set)/sizeof(ulong); + + for ( ; ptr != end ; ptr++) + { + if (*ptr) + { + ulong set= *ptr; + int found= (int) ((char*) ptr - (char*) &pending_set)*8+1; + while (!(set & 1)) + { + found++; + set>>=1; + } + *sigp=found; + sigdelset(&pending_set,found); + pthread_mutex_unlock(&LOCK_sigwait); + return 0; + } + } + VOID(pthread_cond_wait(&COND_sigwait,&LOCK_sigwait)); + } + return 0; +} + +#endif /* DONT_USE_SIGSUSPEND */ +#endif /* HAVE_SIGWAIT */ + +/***************************************************************************** +** Implement pthread_signal for systems that can't use signal() with threads +** Currently this is only used with BSDI 3.0 +*****************************************************************************/ + +#ifdef USE_PTHREAD_SIGNAL + +int pthread_signal(int sig, void (*func)()) +{ + struct sigaction sact; + sact.sa_flags= 0; + sact.sa_handler= func; + sigemptyset(&sact.sa_mask); + sigaction(sig, &sact, (struct sigaction*) 0); + return 0; +} + +#endif + +/***************************************************************************** +** Patches for AIX and DEC OSF/1 3.2 +*****************************************************************************/ + +#if (defined(HAVE_NONPOSIX_PTHREAD_MUTEX_INIT) && !defined(HAVE_UNIXWARE7_THREADS)) || defined(HAVE_DEC_3_2_THREADS) +#undef pthread_mutex_init +#undef pthread_cond_init + +#include <netdb.h> + +int my_pthread_mutex_init(pthread_mutex_t *mp, const pthread_mutexattr_t *attr) +{ + int error; + if (!attr) + error=pthread_mutex_init(mp,pthread_mutexattr_default); + else + error=pthread_mutex_init(mp,*attr); + return error; +} + +int my_pthread_cond_init(pthread_cond_t *mp, const pthread_condattr_t *attr) +{ + int error; + if (!attr) + error=pthread_cond_init(mp,pthread_condattr_default); + else + error=pthread_cond_init(mp,*attr); + return error; +} + +#endif + +/* +** Emulate SOLARIS style calls, not because it's better, but just to make the +** usage of getbostbyname_r simpler. +*/ + +#if !defined(my_gethostbyname_r) && defined(HAVE_GETHOSTBYNAME_R) + +#if defined(HAVE_GLIBC2_STYLE_GETHOSTBYNAME_R) + +struct hostent *my_gethostbyname_r(const char *name, + struct hostent *result, char *buffer, + int buflen, int *h_errnop) +{ + struct hostent *hp; + assert((size_t) buflen >= sizeof(*result)); + if (gethostbyname_r(name,result, buffer, (size_t) buflen, &hp, h_errnop)) + return 0; + return hp; +} + +#elif defined(_HPUX_SOURCE) || (defined(_AIX) && !defined(_AIX32_THREADS)) + +struct hostent *my_gethostbyname_r(const char *name, + struct hostent *result, char *buffer, + int buflen, int *h_errnop) +{ + assert(buflen >= sizeof(struct hostent_data)); + if (gethostbyname_r(name,result,(struct hostent_data *) buffer) == -1) + { + *h_errnop= errno; + return 0; + } + return result; +} + +#else + +struct hostent *my_gethostbyname_r(const char *name, + struct hostent *result, char *buffer, + int buflen, int *h_errnop) +{ + struct hostent *hp; + assert(buflen >= sizeof(struct hostent_data)); + hp= gethostbyname_r(name,result,(struct hostent_data *) buffer); + *h_errnop= errno; + return hp; +} + +#endif /* GLIBC2_STYLE_GETHOSTBYNAME_R */ +#endif + + +/* Some help functions */ + +int pthread_no_free(void *not_used __attribute__((unused))) +{ + return 0; +} + +int pthread_dummy(int ret) +{ + return ret; +} +#endif /* THREAD */ diff --git a/mysys/my_quick.c b/mysys/my_quick.c new file mode 100644 index 00000000000..6151d5037ae --- /dev/null +++ b/mysys/my_quick.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Quicker interface to read & write. Used with my_nosys.h */ + +#include "mysys_priv.h" +#include "my_nosys.h" + + +uint my_quick_read(File Filedes,byte *Buffer,uint Count,myf MyFlags) +{ + uint readbytes; + + if ((readbytes = (uint) read(Filedes, Buffer, Count)) != Count) + { + my_errno=errno; + return readbytes; + } + return (MyFlags & (MY_NABP | MY_FNABP)) ? 0 : readbytes; +} + + +uint my_quick_write(File Filedes,const byte *Buffer,uint Count) +{ + if ((uint) write(Filedes,Buffer,Count) != Count) + { + my_errno=errno; + return (uint) -1; + } + return 0; +} diff --git a/mysys/my_read.c b/mysys/my_read.c new file mode 100644 index 00000000000..b317630f4bd --- /dev/null +++ b/mysys/my_read.c @@ -0,0 +1,66 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include "mysys_err.h" +#include <errno.h> + + + /* Read a chunk of bytes from a file */ + +uint my_read(File Filedes, byte *Buffer, uint Count, myf MyFlags) + /* File descriptor */ + /* Buffer must be at least count bytes */ + /* Max number of bytes returnd */ + /* Flags on what to do on error */ +{ + uint readbytes; + DBUG_ENTER("my_read"); + DBUG_PRINT("my",("Fd: %d Buffer: %lx Count: %u MyFlags: %d", + Filedes, Buffer, Count, MyFlags)); + + for (;;) + { + errno=0; /* Linux doesn't reset this */ + if ((readbytes = (uint) read(Filedes, Buffer, Count)) != Count) + { + my_errno=errno ? errno : -1; + DBUG_PRINT("warning",("Read only %ld bytes off %ld from %d, errno: %d", + readbytes,Count,Filedes,my_errno)); +#ifdef THREAD + if (readbytes == 0 && errno == EINTR) + continue; /* Interrupted */ +#endif + if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) + { + if ((int) readbytes == -1) + my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), + my_filename(Filedes),my_errno); + else if (MyFlags & (MY_NABP | MY_FNABP)) + my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), + my_filename(Filedes),my_errno); + } + if ((int) readbytes == -1 || (MyFlags & (MY_FNABP | MY_NABP))) + DBUG_RETURN(MY_FILE_ERROR); /* Return with error */ + } + + if (MyFlags & (MY_NABP | MY_FNABP)) + readbytes=0; /* Ok on read */ + break; + } + DBUG_RETURN(readbytes); +} /* my_read */ diff --git a/mysys/my_realloc.c b/mysys/my_realloc.c new file mode 100644 index 00000000000..c9d8edd6ddf --- /dev/null +++ b/mysys/my_realloc.c @@ -0,0 +1,65 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#ifdef SAFEMALLOC /* We don't need SAFEMALLOC here */ +#undef SAFEMALLOC +#endif + +#include "mysys_priv.h" +#include "mysys_err.h" + + /* My memory re allocator */ + +gptr my_realloc(gptr oldpoint, uint Size, myf MyFlags) +{ + gptr point; + DBUG_ENTER("my_realloc"); + DBUG_PRINT("my",("ptr: %lx Size: %u MyFlags: %d",oldpoint, Size, MyFlags)); + + if (!oldpoint && (MyFlags & MY_ALLOW_ZERO_PTR)) + DBUG_RETURN(my_malloc(Size,MyFlags)); +#ifdef USE_HALLOC + if (!(point = malloc(Size))) + { + if (MyFlags & MY_FREE_ON_ERROR) + my_free(oldpoint,MyFlags); + if (MyFlags & MY_HOLD_ON_ERROR) + DBUG_RETURN(oldpoint); + my_errno=errno; + if (MyFlags & MY_FAE+MY_WME) + my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),Size); + } + else + { + memcpy(point,oldpoint,Size); + free(oldpoint); + } +#else + if ((point = realloc(oldpoint,Size)) == NULL) + { + if (MyFlags & MY_FREE_ON_ERROR) + my_free(oldpoint,MyFLAGS); + if (MyFlags & MY_HOLD_ON_ERROR) + DBUG_RETURN(oldpoint); + my_errno=errno; + if (MyFlags & (MY_FAE+MY_WME)) + my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG), Size); + } +#endif + DBUG_PRINT("exit",("ptr: %lx",point)); + DBUG_RETURN(point); +} /* my_realloc */ diff --git a/mysys/my_redel.c b/mysys/my_redel.c new file mode 100644 index 00000000000..da03b026c9f --- /dev/null +++ b/mysys/my_redel.c @@ -0,0 +1,98 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#define USES_TYPES /* sys/types is included */ +#include "mysys_priv.h" +#include <my_dir.h> +#include "mysys_err.h" +#if defined(HAVE_SYS_UTIME_H) +#include <sys/utime.h> +#elif defined(HAVE_UTIME_H) +#include <utime.h> +#elif !defined(HPUX) +struct utimbuf { + time_t actime; + time_t modtime; +}; +#endif + + /* Rename with copy stat form old file */ + /* Copy stats from old file to new file, deletes orginal and */ + /* changes new file name to old file name */ + +int my_redel(const char *org_name, const char *tmp_name, myf MyFlags) +{ + DBUG_ENTER("my_redel"); + DBUG_PRINT("my",("org_name: '%s' tmp_name: '%s' MyFlags: %d", + org_name,tmp_name,MyFlags)); + + if (my_copystat(org_name,tmp_name,MyFlags) < 0 || + my_delete(org_name,MyFlags) || + my_rename(tmp_name,org_name,MyFlags)) + DBUG_RETURN(1); + DBUG_RETURN(0); +} /* my_redel */ + + + /* Copy stat from one file to another */ + /* Return -1 if can't get stat, 1 if wrong type of file */ + +int my_copystat(const char *from, const char *to, int MyFlags) +{ + struct stat statbuf; + + if (stat((char*) from, &statbuf)) + { + my_errno=errno; + if (MyFlags & (MY_FAE+MY_WME)) + my_error(EE_STAT, MYF(ME_BELL+ME_WAITTANG),from,errno); + return -1; /* Can't get stat on input file */ + } + if ((statbuf.st_mode & S_IFMT) != S_IFREG) + return 1; + VOID(chmod(to, statbuf.st_mode & 07777)); /* Copy modes */ + +#if !defined(MSDOS) && !defined(__WIN__) && !defined(__EMX__) + if (statbuf.st_nlink > 1 && MyFlags & MY_LINK_WARNING) + { + if (MyFlags & MY_LINK_WARNING) + my_error(EE_LINK_WARNING,MYF(ME_BELL+ME_WAITTANG),from,statbuf.st_nlink); + } + VOID(chown(to, statbuf.st_uid, statbuf.st_gid)); /* Copy ownership */ +#endif /* MSDOS */ + +#ifndef VMS +#ifndef __ZTC__ + if (MyFlags & MY_COPYTIME) + { + struct utimbuf timep; + timep.actime = statbuf.st_atime; + timep.modtime = statbuf.st_mtime; + VOID(utime((char*) to, &timep));/* Update last accessed and modified times */ + } +#else + if (MyFlags & MY_COPYTIME) + { + time_t time[2]; + time[0]= statbuf.st_atime; + time[1]= statbuf.st_mtime; + VOID(utime((char*) to, time));/* Update last accessed and modified times */ + } +#endif +#endif + return 0; +} /* my_copystat */ diff --git a/mysys/my_rename.c b/mysys/my_rename.c new file mode 100644 index 00000000000..ea895ffcf76 --- /dev/null +++ b/mysys/my_rename.c @@ -0,0 +1,60 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#define USES_TYPES +#include "mysys_priv.h" +#include <my_dir.h> +#include "mysys_err.h" + +#undef my_rename + /* On unix rename deletes to file if it exists */ + +int my_rename(const char *from, const char *to, myf MyFlags) +{ + int error = 0; + DBUG_ENTER("my_rename"); + DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags)); + +#if defined(HAVE_FILE_VERSIONS) + { /* Check that there isn't a old file */ + int save_errno; + MY_STAT my_stat_result; + save_errno=my_errno; + if (my_stat(to,&my_stat_result,MYF(0))) + { + my_errno=EEXIST; + error= -1; + if (MyFlags & MY_FAE+MY_WME) + my_error(EE_LINK, MYF(ME_BELL+ME_WAITTANG),from,to,my_errno); + DBUG_RETURN(error); + } + my_errno=save_errno; + } +#endif +#if defined(HAVE_RENAME) + if (rename(from,to)) +#else + if (link(from, to) || unlink(from)) +#endif + { + my_errno=errno; + error = -1; + if (MyFlags & (MY_FAE+MY_WME)) + my_error(EE_LINK, MYF(ME_BELL+ME_WAITTANG),from,to,my_errno); + } + DBUG_RETURN(error); +} /* my_rename */ diff --git a/mysys/my_seek.c b/mysys/my_seek.c new file mode 100644 index 00000000000..12f8ced0642 --- /dev/null +++ b/mysys/my_seek.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" + + /* Seek to position in file */ + /*ARGSUSED*/ + +my_off_t my_seek(File fd, my_off_t pos, int whence, myf MyFlags) +{ + reg1 os_off_t newpos; + DBUG_ENTER("my_seek"); + DBUG_PRINT("my",("Fd: %d Pos: %lu Whence: %d MyFlags: %d", + fd, (ulong) pos, whence, MyFlags)); + newpos=lseek(fd, pos, whence); + if (newpos == (os_off_t) -1) + { + my_errno=errno; + DBUG_PRINT("error",("lseek: %lu, errno: %d",newpos,errno)); + DBUG_RETURN(MY_FILEPOS_ERROR); + } + DBUG_RETURN((my_off_t) newpos); +} /* my_seek */ + + + /* Tell current position of file */ + /* ARGSUSED */ + +my_off_t my_tell(File fd, myf MyFlags) +{ + os_off_t pos; + DBUG_ENTER("my_tell"); + DBUG_PRINT("my",("Fd: %d MyFlags: %d",fd, MyFlags)); +#ifdef HAVE_TELL + pos=tell(fd); +#else + pos=lseek(fd, 0L, MY_SEEK_CUR); +#endif + if (pos == (os_off_t) -1) + my_errno=errno; + DBUG_PRINT("exit",("pos: %lu",pos)); + DBUG_RETURN((my_off_t) pos); +} /* my_tell */ diff --git a/mysys/my_static.c b/mysys/my_static.c new file mode 100644 index 00000000000..db942d96db9 --- /dev/null +++ b/mysys/my_static.c @@ -0,0 +1,100 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* + Static variables for mysys library. All definied here for easy making of + a shared library +*/ + +#ifndef stdin +#include "mysys_priv.h" +#include "my_static.h" +#include "my_alarm.h" +#endif + + /* from my_init */ +my_string home_dir=0,my_progname=0; +char NEAR curr_dir[FN_REFLEN]= {0}, + NEAR home_dir_buff[FN_REFLEN]= {0}; +uint my_stream_opened=0,my_file_opened=0; +int NEAR my_umask=0664, NEAR my_umask_dir=0777; +#ifndef THREAD +int NEAR my_errno=0; +#endif +struct my_file_info my_file_info[MY_NFILE]= {{0,UNOPEN}}; + + /* From mf_brkhant */ +int NEAR my_dont_interrupt=0; +volatile int _my_signals=0; +struct st_remember _my_sig_remember[MAX_SIGNALS]={{0,0}}; +#ifdef THREAD +sigset_t my_signals; /* signals blocked by mf_brkhant */ +#endif + + /* from mf_keycache.c */ +my_bool key_cache_inited=0; + + /* from mf_reccache.c */ +ulong my_default_record_cache_size=RECORD_CACHE_SIZE; + + /* from soundex.c */ + /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */ + /* :::::::::::::::::::::::::: */ +const char *soundex_map= "01230120022455012623010202"; + + /* from my_malloc */ +USED_MEM* my_once_root_block=0; /* pointer to first block */ +uint my_once_extra=ONCE_ALLOC_INIT; /* Memory to alloc / block */ + + /* from my_tempnam */ +#ifndef HAVE_TEMPNAM +int _my_tempnam_used=0; +#endif + + /* from safe_malloc */ +uint sf_malloc_prehunc=0, /* If you have problem with core- */ + sf_malloc_endhunc=0, /* dump when malloc-message.... */ + /* set theese to 64 or 128 */ + sf_malloc_quick=0; /* set if no calls to sanity */ +long lCurMemory = 0L; /* Current memory usage */ +long lMaxMemory = 0L; /* Maximum memory usage */ +uint cNewCount = 0; /* Number of times NEW() was called */ +byte *sf_min_adress= (byte*) ~(unsigned long) 0L, + *sf_max_adress= (byte*) 0L; + +/* Root of the linked list of remembers */ +struct remember *pRememberRoot = NULL; + + /* from my_alarm */ +int volatile my_have_got_alarm=0; /* declare variable to reset */ +ulong my_time_to_wait_for_lock=2; /* In seconds */ + + /* from errors.c */ +#ifdef SHARED_LIBRARY +char * NEAR globerrs[GLOBERRS]; /* my_error_messages is here */ +#endif +void (*my_abort_hook)(int) = (void(*)(int)) exit; +int (*error_handler_hook)(uint error,const char *str,myf MyFlags)= + my_message_no_curses; +int (*fatal_error_handler_hook)(uint error,const char *str,myf MyFlags)= + my_message_no_curses; + + /* How to disable options */ +my_bool NEAR my_disable_locking=0; +my_bool NEAR my_disable_async_io=0; +my_bool NEAR my_disable_flush_key_blocks=0; +my_bool NEAR mysys_uses_curses=0; diff --git a/mysys/my_static.h b/mysys/my_static.h new file mode 100644 index 00000000000..dd80a8da1f9 --- /dev/null +++ b/mysys/my_static.h @@ -0,0 +1,82 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* + Static variables for mysys library. All definied here for easy making of + a shared library +*/ + +#include "mysys_priv.h" +#include <signal.h> + +#define MAX_SIGNALS 10 /* Max signals under a dont-allow */ +#define MIN_KEYBLOCK (min(IO_SIZE,1024)) +#define MAX_KEYBLOCK 8192 /* Max keyblocklength == 8*IO_SIZE */ +#define MAX_BLOCK_TYPES MAX_KEYBLOCK/MIN_KEYBLOCK + +struct st_remember { + int number; + sig_handler (*func)(int number); +}; + +typedef struct sec_link { + struct sec_link *next_hash,**prev_hash;/* Blocks linked acc. to hash-value */ + struct sec_link *next_used,*prev_used; + struct sec_link *next_changed,**prev_changed; + File file; + my_off_t diskpos; + byte *buffer; + my_bool changed; +} SEC_LINK; + +struct irem { + struct remember *_pNext; /* Linked list of structures */ + struct remember *_pPrev; /* Other link */ + my_string _sFileName; /* File in which memory was new'ed */ + uint _uLineNum; /* Line number in above file */ + uint _uDataSize; /* Size requested */ + long _lSpecialValue; /* Underrun marker value */ +}; + +struct remember { + struct irem tInt; + char aData[1]; +}; + +extern char NEAR curr_dir[FN_REFLEN],NEAR home_dir_buff[FN_REFLEN]; + +extern volatile int _my_signals; +extern struct st_remember _my_sig_remember[MAX_SIGNALS]; + +extern my_bool key_cache_inited; + +extern const char *soundex_map; + +extern USED_MEM* my_once_root_block; +extern uint my_once_extra; + +#ifndef HAVE_TEMPNAM +extern int _my_tempnam_used; +#endif + +extern byte *sf_min_adress,*sf_max_adress; +extern uint cNewCount; +extern struct remember *pRememberRoot; + +#if defined(THREAD) && !defined(__WIN__) +extern sigset_t my_signals; /* signals blocked by mf_brkhant */ +#endif diff --git a/mysys/my_tempnam.c b/mysys/my_tempnam.c new file mode 100644 index 00000000000..7e5b953fe53 --- /dev/null +++ b/mysys/my_tempnam.c @@ -0,0 +1,142 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include <m_string.h> +#include "my_static.h" +#include "mysys_err.h" + +#define TMP_EXT ".tmp" /* Extension of tempfile */ +#if ! defined(P_tmpdir) +#define P_tmpdir "" +#endif + +#ifdef HAVE_TEMPNAM +#ifndef MSDOS +extern char **environ; +#endif +#endif + +/* Make a uniq temp file name by using dir and adding something after + pfx to make name uniq. Name is made by adding a uniq 8 length-string and + TMP_EXT after pfx. + Returns pointer to malloced area for filename. Should be freed by + free(). + The name should be uniq, but it isn't checked if it file allready exists. + Uses tempnam() if function exist on system. + This function fixes that if dir is given it's used. For example + MSDOS tempnam() uses always TMP environment-variable if it exists. +*/ + /* ARGSUSED */ + +my_string my_tempnam(const char *dir, const char *pfx, + myf MyFlags __attribute__((unused))) +{ +#ifdef _MSC_VER + char temp[FN_REFLEN],*end,*res,**old_env,*temp_env[1]; + old_env=environ; + if (dir) + { + end=strend(dir)-1; + if (!dir[0]) + { /* Change empty string to current dir */ + temp[0]= FN_CURLIB; + temp[1]= 0; + dir=temp; + } + else if (*end == FN_DEVCHAR) + { /* Get current dir for drive */ + _fullpath(temp,dir,FN_REFLEN); + dir=temp; + } + else if (*end == FN_LIBCHAR && dir < end && end[-1] != FN_DEVCHAR) + { + strmake(temp,dir,(uint) (end-dir)); /* Copy and remove last '\' */ + dir=temp; + } + environ=temp_env; /* Force use of dir (dir not checked) */ + temp_env[0]=0; + } + res=tempnam((char*) dir,(my_string) pfx); + environ=old_env; + return res; +#else +#ifdef __ZTC__ + if (!dir) + { /* If empty test first if TMP can be used */ + dir=getenv("TMP"); + } + return tempnam((char*) dir,(my_string) pfx); /* Use stand. dir with prefix */ +#else +#ifdef HAVE_TEMPNAM + char temp[2],*res,**old_env,*temp_env[1]; + + if (dir && !dir[0]) + { /* Change empty string to current dir */ + temp[0]= FN_CURLIB; + temp[1]= 0; + dir=temp; + } + old_env=environ; + if (dir) + { /* Don't use TMPDIR if dir is given */ + environ=temp_env; + temp_env[0]=0; + } + res=tempnam((char*) dir,(my_string) pfx); /* Use stand. dir with prefix */ + environ=old_env; + if (!res) + DBUG_PRINT("error",("Got error: %d from tempnam",errno)); + return res; +#else + register long uniq; + register int length; + my_string pos,end_pos; + DBUG_ENTER("my_tempnam"); + /* Make a uniq nummber */ + pthread_mutex_lock(&THR_LOCK_open); + uniq= ((long) getpid() << 20) + (long) _my_tempnam_used++ ; + pthread_mutex_unlock(&THR_LOCK_open); + if (!dir && !(dir=getenv("TMPDIR"))) /* Use this if possibly */ + dir=P_tmpdir; /* Use system default */ + length=strlen(dir)+strlen(pfx)+1; + + DBUG_PRINT("test",("mallocing %d byte",length+8+sizeof(TMP_EXT)+1)); + if (!(pos=(char*) malloc(length+8+sizeof(TMP_EXT)+1))) + { + if (MyFlags & MY_FAE+MY_WME) + my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG), + length+8+sizeof(TMP_EXT)+1); + DBUG_RETURN(NullS); + } + end_pos=strmov(pos,dir); + if (end_pos != pos && end_pos[-1] != FN_LIBCHAR) + *end_pos++=FN_LIBCHAR; + end_pos=strmov(end_pos,pfx); + + for (length=0 ; length < 8 && uniq ; length++) + { + *end_pos++= _dig_vec[(int) (uniq & 31)]; + uniq >>= 5; + } + VOID(strmov(end_pos,TMP_EXT)); + DBUG_PRINT("exit",("tempnam: '%s'",pos)); + DBUG_RETURN(pos); +#endif /* HAVE_TEMPNAM */ +#endif /* __ZTC__ */ +#endif /* _MSC_VER */ +} /* my_tempnam */ diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c new file mode 100644 index 00000000000..d879da8e65d --- /dev/null +++ b/mysys/my_thr_init.c @@ -0,0 +1,194 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* +** Functions to handle initializating and allocationg of all mysys & debug +** thread variables. +*/ + +#include "mysys_priv.h" +#include <m_string.h> + +#ifdef THREAD +#ifdef USE_TLS +pthread_key(struct st_my_thread_var*, THR_KEY_mysys); +#else +pthread_key(struct st_my_thread_var, THR_KEY_mysys); +#endif +pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open,THR_LOCK_keycache, + THR_LOCK_lock,THR_LOCK_isam,THR_LOCK_myisam,THR_LOCK_heap, + THR_LOCK_net, THR_LOCK_charset; +#ifndef HAVE_LOCALTIME_R +pthread_mutex_t LOCK_localtime_r; +#endif +#ifdef __WIN__ +pthread_mutex_t THR_LOCK_thread; +#endif + +/* FIXME Note. TlsAlloc does not set an auto destructor, so + the function my_thread_global_free must be called from + somewhere before final exit of the library */ + +my_bool my_thread_global_init(void) +{ + if (pthread_key_create(&THR_KEY_mysys,free)) + { + fprintf(stderr,"Can't initialize threads: error %d\n",errno); + exit(1); + } + pthread_mutex_init(&THR_LOCK_malloc,NULL); + pthread_mutex_init(&THR_LOCK_open,NULL); + pthread_mutex_init(&THR_LOCK_keycache,NULL); + pthread_mutex_init(&THR_LOCK_lock,NULL); + pthread_mutex_init(&THR_LOCK_isam,NULL); + pthread_mutex_init(&THR_LOCK_myisam,NULL); + pthread_mutex_init(&THR_LOCK_heap,NULL); + pthread_mutex_init(&THR_LOCK_net,NULL); + pthread_mutex_init(&THR_LOCK_charset,NULL); +#ifdef __WIN__ + pthread_mutex_init(&THR_LOCK_thread,NULL); +#endif +#ifndef HAVE_LOCALTIME_R + pthread_mutex_init(&LOCK_localtime_r,NULL); +#endif + return my_thread_init(); +} + +void my_thread_global_end(void) +{ +#if defined(USE_TLS) + (void) TlsFree(THR_KEY_mysys); +#endif +} + +static long thread_id=0; + +my_bool my_thread_init(void) +{ + struct st_my_thread_var *tmp; + pthread_mutex_lock(&THR_LOCK_lock); +#if !defined(__WIN__) || defined(USE_TLS) + if (my_pthread_getspecific(struct st_my_thread_var *,THR_KEY_mysys)) + { + pthread_mutex_unlock(&THR_LOCK_lock); + return 0; /* Safequard */ + } + /* We must have many calloc() here because these are freed on + pthread_exit */ + if (!(tmp=(struct st_my_thread_var *) + calloc(1,sizeof(struct st_my_thread_var)))) + { + pthread_mutex_unlock(&THR_LOCK_lock); + return 1; + } + pthread_setspecific(THR_KEY_mysys,tmp); + +#else + if (THR_KEY_mysys.id) /* Allready initialized */ + { + pthread_mutex_unlock(&THR_LOCK_lock); + return 0; + } + tmp= &THR_KEY_mysys; +#endif + tmp->id= ++thread_id; + pthread_mutex_init(&tmp->mutex,NULL); + pthread_cond_init(&tmp->suspend, NULL); + pthread_mutex_unlock(&THR_LOCK_lock); + return 0; +} + +void my_thread_end(void) +{ + struct st_my_thread_var *tmp=my_thread_var; + if (tmp) + { +#if !defined(DBUG_OFF) + if (tmp->dbug) + { + free(tmp->dbug); + tmp->dbug=0; + } +#endif +#if !defined(__bsdi__) || defined(HAVE_mit_thread) /* bsdi dumps core here */ + pthread_cond_destroy(&tmp->suspend); +#endif + pthread_mutex_destroy(&tmp->mutex); +#if !defined(__WIN__) || defined(USE_TLS) + free(tmp); +#endif + } +#if !defined(__WIN__) || defined(USE_TLS) + pthread_setspecific(THR_KEY_mysys,0); +#endif +} + +struct st_my_thread_var *_my_thread_var(void) +{ + struct st_my_thread_var *tmp= + my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); +#if defined(USE_TLS) + /* This can only happen in a .DLL */ + if (!tmp) + { + my_thread_init(); + tmp=my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); + } +#endif + return tmp; +} + +/**************************************************************************** +** Get name of current thread. +****************************************************************************/ + +#define UNKNOWN_THREAD -1 + +long my_thread_id() +{ +#if defined(HAVE_PTHREAD_GETSEQUENCE_NP) + return pthread_getsequence_np(pthread_self()); +#elif (defined(__sun) || defined(__sgi) || defined(__linux__)) && !defined(HAVE_mit_thread) + return pthread_self(); +#else + return my_thread_var->id; +#endif +} + +#ifdef DBUG_OFF +char *my_thread_name(void) +{ + return "no_name"; +} + +#else + +char *my_thread_name(void) +{ + char name_buff[100]; + struct st_my_thread_var *tmp=my_thread_var; + if (!tmp->name[0]) + { + long id=my_thread_id(); + sprintf(name_buff,"T@%ld", id); + strmake(tmp->name,name_buff,THREAD_NAME_SIZE); + } + return tmp->name; +} +#endif /* DBUG_OFF */ + +#endif /* THREAD */ diff --git a/mysys/my_vsnprintf.c b/mysys/my_vsnprintf.c new file mode 100644 index 00000000000..63730926156 --- /dev/null +++ b/mysys/my_vsnprintf.c @@ -0,0 +1,94 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include "mysys_err.h" +#include <m_string.h> +#include <stdarg.h> +#include <m_ctype.h> + + + +int my_vsnprintf(char* str, size_t n, const char* fmt, va_list ap) +{ + uint olen = 0, plen; + const char *tpos; + reg1 char *endpos; + reg2 char * par; + char* ebuff = str; + + endpos=ebuff; + tpos = fmt; + + while (*tpos) + { + if (tpos[0] != '%') + { + if(olen + 1 >= n) + break; + + *endpos++= *tpos++; /* Copy ordinary char */ + olen++; + continue; + } + if (*++tpos == '%') /* test if %% */ + { + olen--; + } + else + { + /* Skipp if max size is used (to be compatible with printf) */ + while (isdigit(*tpos) || *tpos == '.' || *tpos == '-') + tpos++; + if (*tpos == 's') /* String parameter */ + { + par = va_arg(ap, char *); + plen = (uint) strlen(par); + if (olen + plen < n) /* Replace if possible */ + { + endpos=strmov(endpos,par); + tpos++; + olen+=plen; + continue; + } + } + else if (*tpos == 'd' || *tpos == 'u') /* Integer parameter */ + { + register int iarg; + iarg = va_arg(ap, int); + if(olen + 16 >= n) break; + + if (*tpos == 'd') + plen= (uint) (int2str((long) iarg,endpos, -10) - endpos); + else + plen= (uint) (int2str((long) (uint) iarg,endpos,10)- endpos); + if (olen + plen < n) /* Replace parameter if possible */ + { + endpos+=plen; + tpos++; + olen+=plen; + continue; + } + } + } + *endpos++='%'; /* % used as % or unknown code */ + } + *endpos='\0'; + /* End of errmessage */ + return olen; +} + diff --git a/mysys/my_wincond.c b/mysys/my_wincond.c new file mode 100644 index 00000000000..3643d0ec0a6 --- /dev/null +++ b/mysys/my_wincond.c @@ -0,0 +1,141 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/***************************************************************************** +** The following is a simple implementation of posix conditions +*****************************************************************************/ + +#include "mysys_priv.h" +#if defined(THREAD) && defined(__WIN__) +#include <m_string.h> +#undef getpid +#include <process.h> +#include <sys/timeb.h> + +int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) +{ + cond->waiting=0; + cond->semaphore=CreateSemaphore(NULL,0,0x7FFFFFFF,NullS); + if (!cond->semaphore) + return ENOMEM; + return 0; +} + +int pthread_cond_destroy(pthread_cond_t *cond) +{ + return CloseHandle(cond->semaphore) ? 0 : EINVAL; +} + + +int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + InterlockedIncrement(&cond->waiting); + LeaveCriticalSection(mutex); + WaitForSingleObject(cond->semaphore,INFINITE); + InterlockedDecrement(&cond->waiting); + EnterCriticalSection(mutex); + return 0 ; +} + +int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + struct timespec *abstime) +{ + struct _timeb curtime; + int result; + long timeout; + _ftime(&curtime); + timeout= ((long) (abstime->tv_sec - curtime.time)*1000L + + (long)((abstime->tv_nsec/1000) - curtime.millitm)/1000L); + if (timeout < 0) /* Some safety */ + timeout = 0L; + InterlockedIncrement(&cond->waiting); + LeaveCriticalSection(mutex); + result=WaitForSingleObject(cond->semaphore,timeout); + InterlockedDecrement(&cond->waiting); + EnterCriticalSection(mutex); + + return result == WAIT_TIMEOUT ? ETIMEDOUT : 0; +} + + +int pthread_cond_signal(pthread_cond_t *cond) +{ + long prev_count; + if (cond->waiting) + ReleaseSemaphore(cond->semaphore,1,&prev_count); + return 0; +} + + +int pthread_cond_broadcast(pthread_cond_t *cond) +{ + long prev_count; + if (cond->waiting) + ReleaseSemaphore(cond->semaphore,cond->waiting,&prev_count); + return 0 ; +} + + +int pthread_attr_init(pthread_attr_t *connect_att) +{ + connect_att->dwStackSize = 0; + connect_att->dwCreatingFlag = 0; + connect_att->priority = 0; + return 0; +} + +int pthread_attr_setstacksize(pthread_attr_t *connect_att,DWORD stack) +{ + connect_att->dwStackSize=stack; + return 0; +} + +int pthread_attr_setprio(pthread_attr_t *connect_att,int priority) +{ + connect_att->priority=priority; + return 0; +} + +int pthread_attr_destroy(pthread_attr_t *connect_att) +{ + bzero((gptr) connect_att,sizeof(*connect_att)); + return 0; +} + +/**************************************************************************** +** Fix localtime_r() to be a bit safer +****************************************************************************/ + +struct tm *localtime_r(const time_t *timep,struct tm *tmp) +{ + if (*timep == (time_t) -1) /* This will crash win32 */ + { + bzero(tmp,sizeof(*tmp)); + } + else + { + struct tm *res=localtime(timep); + if (!res) /* Wrong date */ + { + bzero(tmp,sizeof(*tmp)); /* Keep things safe */ + return 0; + } + *tmp= *res; + } + return tmp; +} +#endif /* __WIN__ */ diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c new file mode 100644 index 00000000000..436fc954d93 --- /dev/null +++ b/mysys/my_winthread.c @@ -0,0 +1,111 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/***************************************************************************** +** Simulation of posix threads calls for WIN95 and NT +*****************************************************************************/ + +#include "mysys_priv.h" +#if defined(THREAD) && defined(__WIN__) +#include <m_string.h> +#undef getpid +#include <process.h> + +extern pthread_mutex_t THR_LOCK_thread; + +struct pthread_map +{ + HANDLE pthreadself; + pthread_handler func; + void *param; +}; + +/* +** We have tried to use '_beginthreadex' instead of '_beginthread' here +** but in this case the program leaks about 512 characters for each +** created thread ! +** As we want to save the created thread handler for other threads to +** use and to be returned by pthread_self() (instead of the Win32 pseudo +** handler), we have to go trough pthread_start() to catch the returned handler +** in the new thread. +*/ + +static pthread_handler_decl(pthread_start,param) +{ + pthread_handler func=((struct pthread_map *) param)->func; + void *func_param=((struct pthread_map *) param)->param; + my_thread_init(); + pthread_mutex_lock(&THR_LOCK_thread); /* Wait for beingthread to return */ + win_pthread_self=((struct pthread_map *) param)->pthreadself; + pthread_mutex_unlock(&THR_LOCK_thread); + free((char*) param); + pthread_exit((*func)(func_param)); + return 0; +} + + +int pthread_create(pthread_t *thread_id, pthread_attr_t *attr, + pthread_handler func, void *param) +{ + HANDLE hThread; + struct pthread_map *map; + DBUG_ENTER("pthread_create"); + + if (!(map=malloc(sizeof(*map)))) + DBUG_RETURN(-1); + map->func=func; + map->param=param; + pthread_mutex_lock(&THR_LOCK_thread); +#ifdef __BORLANDC__ + hThread=(HANDLE)_beginthread((void(_USERENTRY *)(void *)) pthread_start, + attr->dwStackSize ? attr->dwStackSize : + 65535, (void*) map); +#else + hThread=(HANDLE)_beginthread(pthread_start, + attr->dwStackSize ? attr->dwStackSize : + 65535, (void*) map); +#endif + DBUG_PRINT("info", ("hThread=%lu",(long) hThread)); + *thread_id=map->pthreadself=hThread; + pthread_mutex_unlock(&THR_LOCK_thread); + + if ((long) hThread == -1L) + { + long error=errno; + DBUG_PRINT("error", + ("Can't create thread to handle request (error %ld)",error)); + DBUG_RETURN(error ? error : -1); + } + VOID(SetThreadPriority(hThread, attr->priority)) ; + DBUG_RETURN(0); +} + + +void pthread_exit(unsigned A) +{ + _endthread(); +} + +/* This is neaded to get the macro pthread_setspecific to work */ + +int win_pthread_setspecific(void *a,void *b,uint length) +{ + memcpy(a,b,length); + return 0; +} + +#endif diff --git a/mysys/my_write.c b/mysys/my_write.c new file mode 100644 index 00000000000..0ff32094ed7 --- /dev/null +++ b/mysys/my_write.c @@ -0,0 +1,77 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include "mysys_err.h" +#include <errno.h> + + /* Write a chunk of bytes to a file */ + +uint my_write(int Filedes, const byte *Buffer, uint Count, myf MyFlags) +{ + uint writenbytes,errors; + ulong written; + DBUG_ENTER("my_write"); + DBUG_PRINT("my",("Fd: %d Buffer: %lx Count: %d MyFlags: %d", + Filedes, Buffer, Count, MyFlags)); + errors=0; written=0L; + + for (;;) + { + if ((writenbytes = (uint) write(Filedes, Buffer, Count)) == Count) + break; + if ((int) writenbytes != -1) + { /* Safeguard */ + written+=writenbytes; + Buffer+=writenbytes; + Count-=writenbytes; + } + my_errno=errno; + DBUG_PRINT("error",("Write only %d bytes",writenbytes)); +#ifndef NO_BACKGROUND +#ifdef THREAD + if (my_thread_var->abort) + MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */ +#endif + if (my_errno == ENOSPC && (MyFlags & MY_WAIT_IF_FULL)) + { + if (!(errors++ % MY_WAIT_GIVE_USER_A_MESSAGE)) + my_error(EE_DISK_FULL,MYF(ME_BELL | ME_NOREFRESH), + my_filename(Filedes)); + VOID(sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC)); + continue; + } + if ((writenbytes == 0 && my_errno == EINTR) || + (writenbytes > 0 && (uint) writenbytes != (uint) -1)) + continue; /* Retry */ +#endif + if (MyFlags & (MY_NABP | MY_FNABP)) + { + if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) + { + my_error(EE_WRITE, MYF(ME_BELL+ME_WAITTANG), + my_filename(Filedes),my_errno); + } + DBUG_RETURN(MY_FILE_ERROR); /* Error on read */ + } + else + break; /* Return bytes written */ + } + if (MyFlags & (MY_NABP | MY_FNABP)) + DBUG_RETURN(0); /* Want only errors */ + DBUG_RETURN(writenbytes+written); +} /* my_write */ diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h new file mode 100644 index 00000000000..86c32202e99 --- /dev/null +++ b/mysys/mysys_priv.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include <global.h> +#include <my_sys.h> + +#ifdef USE_SYSTEM_WRAPPERS +#include "system_wrappers.h" +#endif + +#ifdef THREAD +extern pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open,THR_LOCK_keycache, + THR_LOCK_lock,THR_LOCK_isam,THR_LOCK_net,THR_LOCK_charset; +#else /* THREAD */ +#define pthread_mutex_lock(A) +#define pthread_mutex_unlock(A) +#endif diff --git a/mysys/ptr_cmp.c b/mysys/ptr_cmp.c new file mode 100644 index 00000000000..65b2c51aafd --- /dev/null +++ b/mysys/ptr_cmp.c @@ -0,0 +1,158 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* + get_ptr_compare(len) returns a pointer to a optimal byte-compare function + for a array of stringpointer where all strings have size len. + The bytes are compare as unsigned chars. + Because the size is saved in a static variable. + When using threads the program must have called my_init and the thread + my_init_thread() + */ + +#include "mysys_priv.h" + +static int ptr_compare(uint *compare_length, uchar **a, uchar **b); +static int ptr_compare_0(uint *compare_length, uchar **a, uchar **b); +static int ptr_compare_1(uint *compare_length, uchar **a, uchar **b); +static int ptr_compare_2(uint *compare_length, uchar **a, uchar **b); +static int ptr_compare_3(uint *compare_length, uchar **a, uchar **b); + + /* Get a pointer to a optimal byte-compare function for a given size */ + +qsort2_cmp get_ptr_compare (uint size) +{ + if (size < 4) + return (qsort2_cmp) ptr_compare; + switch (size & 3) { + case 0: return (qsort2_cmp) ptr_compare_0; + case 1: return (qsort2_cmp) ptr_compare_1; + case 2: return (qsort2_cmp) ptr_compare_2; + case 3: return (qsort2_cmp) ptr_compare_3; + } + return 0; /* Impossible */ +} + + + /* + Compare to keys to see witch is smaller. + Loop unrolled to make it quick !! + */ + +#define cmp(N) if (first[N] != last[N]) return (int) first[N] - (int) last[N] + +static int ptr_compare(uint *compare_length, uchar **a, uchar **b) +{ + reg3 int length= *compare_length; + reg1 uchar *first,*last; + + first= *a; last= *b; + while (--length) + { + if (*first++ != *last++) + return (int) first[-1] - (int) last[-1]; + } + return (int) first[0] - (int) last[0]; +} + + +static int ptr_compare_0(uint *compare_length,uchar **a, uchar **b) +{ + reg3 int length= *compare_length; + reg1 uchar *first,*last; + + first= *a; last= *b; + loop: + cmp(0); + cmp(1); + cmp(2); + cmp(3); + if ((length-=4)) + { + first+=4; + last+=4; + goto loop; + } + return (0); +} + + +static int ptr_compare_1(uint *compare_length,uchar **a, uchar **b) +{ + reg3 int length= *compare_length-1; + reg1 uchar *first,*last; + + first= *a+1; last= *b+1; + cmp(-1); + loop: + cmp(0); + cmp(1); + cmp(2); + cmp(3); + if ((length-=4)) + { + first+=4; + last+=4; + goto loop; + } + return (0); +} + +static int ptr_compare_2(uint *compare_length,uchar **a, uchar **b) +{ + reg3 int length= *compare_length-2; + reg1 uchar *first,*last; + + first= *a +2 ; last= *b +2; + cmp(-2); + cmp(-1); + loop: + cmp(0); + cmp(1); + cmp(2); + cmp(3); + if ((length-=4)) + { + first+=4; + last+=4; + goto loop; + } + return (0); +} + +static int ptr_compare_3(uint *compare_length,uchar **a, uchar **b) +{ + reg3 int length= *compare_length-3; + reg1 uchar *first,*last; + + first= *a +3 ; last= *b +3; + cmp(-3); + cmp(-2); + cmp(-1); + loop: + cmp(0); + cmp(1); + cmp(2); + cmp(3); + if ((length-=4)) + { + first+=4; + last+=4; + goto loop; + } + return (0); +} diff --git a/mysys/queues.c b/mysys/queues.c new file mode 100644 index 00000000000..f33856b892d --- /dev/null +++ b/mysys/queues.c @@ -0,0 +1,141 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* + Code for generell handling of priority Queues. + Implemention of queues from "Algoritms in C" by Robert Sedgewick. +*/ + +#include "mysys_priv.h" +#include <queues.h> + + + /* The actuall code for handling queues */ + +int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key, + pbool max_at_top, int (*compare) (void *, byte *, byte *), + void *first_cmp_arg) +{ + DBUG_ENTER("init_queue"); + if ((queue->root= (byte **) my_malloc((max_elements+1)*sizeof(void*), + MYF(MY_WME))) == 0) + DBUG_RETURN(1); + queue->elements=0; + queue->compare=compare; + queue->first_cmp_arg=first_cmp_arg; + queue->max_elements=max_elements; + queue->offset_to_key=offset_to_key; + queue->max_at_top= max_at_top ? (-1 ^ 1) : 0; + DBUG_RETURN(0); +} + +void delete_queue(QUEUE *queue) +{ + DBUG_ENTER("delete_queue"); + if (queue->root) + { + my_free((gptr) queue->root,MYF(0)); + queue->root=0; + } + DBUG_VOID_RETURN; +} + + + /* Code for insert, search and delete of elements */ + +void queue_insert(register QUEUE *queue, byte *element) +{ + reg2 uint idx,next; + +#ifndef DBUG_OFF + if (queue->elements < queue->max_elements) +#endif + { + queue->root[0]=element; + idx= ++queue->elements; + + while ((queue->compare(queue->first_cmp_arg, + element+queue->offset_to_key, + queue->root[(next=idx >> 1)]+queue->offset_to_key) + ^ queue->max_at_top) < 0) + { + queue->root[idx]=queue->root[next]; + idx=next; + } + queue->root[idx]=element; + } +} + + /* Remove item from queue */ + /* Returns pointer to removed element */ + +byte *queue_remove(register QUEUE *queue, uint idx) +{ +#ifndef DBUG_OFF + if (idx >= queue->max_elements) + return 0; +#endif + { + byte *element=queue->root[++idx]; /* Intern index starts from 1 */ + queue->root[idx]=queue->root[queue->elements--]; + _downheap(queue,idx); + return element; + } +} + + + /* Fix when element on top has been replaced */ + +#ifndef queue_replaced +void queue_replaced(queue) +QUEUE *queue; +{ + _downheap(queue,1); +} +#endif + + /* Fix heap when index have changed */ + +void _downheap(register QUEUE *queue, uint idx) +{ + byte *element; + uint elements,half_queue,next_index,offset_to_key; + int cmp; + + offset_to_key=queue->offset_to_key; + element=queue->root[idx]; + half_queue=(elements=queue->elements) >> 1; + + while (idx <= half_queue) + { + next_index=idx+idx; + if (next_index < elements && + (queue->compare(queue->first_cmp_arg, + queue->root[next_index]+offset_to_key, + queue->root[next_index+1]+offset_to_key) ^ + queue->max_at_top) > 0) + next_index++; + if ((cmp=queue->compare(queue->first_cmp_arg, + queue->root[next_index]+offset_to_key, + element+offset_to_key)) == 0 || + (cmp ^ queue->max_at_top) > 0) + break; + queue->root[idx]=queue->root[next_index]; + idx=next_index; + } + queue->root[idx]=element; +} diff --git a/mysys/raid.cc b/mysys/raid.cc new file mode 100644 index 00000000000..a92647d1d95 --- /dev/null +++ b/mysys/raid.cc @@ -0,0 +1,809 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* --------------------------------------------------------* +* +* RAID support for MySQL. Raid 0 (stiping) only implemented yet. +* +* Why RAID? Why it must be in MySQL? +* +* This is because then you can: +* 1. Have bigger tables than your OS limit. In time of writing this +* we are hitting to 2GB limit under linux/ext2 +* 2. You can get more speed from IO bottleneck by putting +* Raid dirs on different physical disks. +* 3. Getting more fault tolerance (not implemented yet) +* +* Why not to use RAID: +* +* 1. You are losing some processor power to calculate things, +* do more syscalls and interrupts. +* +* Functionality is supplied by two classes: RaidFd and RaidName. +* RaidFd supports funtionality over file descriptors like +* open/create/write/seek/close. RaidName supports functionality +* like rename/delete where we have no relations to filedescriptors. +* RaidName can be prorably unchanged for different Raid levels. RaidFd +* have to be virtual I think ;). +* You can speed up some calls in MySQL code by skipping RAID code. +* For example LOAD DATA INFILE never needs to read RAID-ed files. +* This can be done adding proper "#undef my_read" or similar undef-s +* in your code. Check out the raid.h! +* +* Some explanation about _seek_vector[] +* This is seek cache. RAID seeks too much and we cacheing this. We +* fool it and just storing new position in file to _seek_vector. +* When there is no seeks to do, we are putting RAID_SEEK_DONE into it. +* Any other value requires seeking to that position. +* +* TODO: +* +* +* - Implement other fancy things like RAID 1 (mirroring) and RAID 5. +* Should not to be very complex. +* +* - Optimize big blob writes by resorting write buffers and writing +* big chunks at once instead of doing many syscalls. - after thinking I +* found this is useless. This is because same thing one can do with just +* increasing RAID_CHUNKSIZE. Monty, what do you think? tonu. +* +* - If needed, then implement missing syscalls. One known to miss is stat(); +* +* - Make and use a thread safe dynamic_array buffer. The used one +* will not work if needs to be extended at the same time someone is +* accessing it. +* +* +* tonu@mysql.com & monty@mysql.com +* --------------------------------------------------------*/ + +#ifdef __GNUC__ +#pragma implementation // gcc: Class implementation +#endif + +#include "mysys_priv.h" +#include "my_dir.h" +#include <m_string.h> +#include <assert.h> + +const char *raid_type_string[]={"none","striped"}; + + +extern "C" { + const char *my_raid_type(int raid_type) + { + return raid_type_string[raid_type]; + } +} + +#if defined(USE_RAID) && !defined(MYSQL_CLIENT) + +#define RAID_SEEK_DONE ~(off_t) 0 +#define RAID_SIZE_UNKNOWN ~(my_off_t) 0 + +DYNAMIC_ARRAY RaidFd::_raid_map; + + +/* --------------- C compatibility ---------------*/ + +extern "C" { + + void init_raid(void) + { + /* Allocate memory for global file to raid map */ + init_dynamic_array(&RaidFd::_raid_map, sizeof(RaidFd*), 4096, 1024); + } + void end_raid(void) + { + /* Free memory used by raid */ + delete_dynamic(&RaidFd::_raid_map); + } + + bool is_raid(File fd) + { + return RaidFd::IsRaid(fd); + } + + File my_raid_create(const char *FileName, int CreateFlags, int access_flags, + uint raid_type, uint raid_chunks, ulong raid_chunksize, + myf MyFlags) + { + DBUG_ENTER("my_raid_create"); + DBUG_PRINT("enter",("Filename: %s CreateFlags: %d access_flags: %d MyFlags: %d", + FileName, CreateFlags, access_flags, MyFlags)); + if (raid_type) + { + RaidFd *raid = new RaidFd(raid_type, raid_chunks , raid_chunksize); + File res = raid->Create(FileName,CreateFlags,access_flags,MyFlags); + if (res < 0 || set_dynamic(&RaidFd::_raid_map,(char*) &raid,res)) + { + delete raid; + DBUG_RETURN(-1); + } + DBUG_RETURN(res); + } + else + DBUG_RETURN(my_create(FileName, CreateFlags, access_flags, MyFlags)); + } + + File my_raid_open(const char *FileName, int Flags, + uint raid_type, uint raid_chunks, ulong raid_chunksize, + myf MyFlags) + { + DBUG_ENTER("my_raid_open"); + DBUG_PRINT("enter",("Filename: %s Flags: %d MyFlags: %d", + FileName, Flags, MyFlags)); + if (raid_type) + { + RaidFd *raid = new RaidFd(raid_type, raid_chunks , raid_chunksize); + File res = raid->Open(FileName,Flags,MyFlags); + if (res < 0 || set_dynamic(&RaidFd::_raid_map,(char*) &raid,res)) + { + delete raid; + DBUG_RETURN(-1); + } + DBUG_RETURN(res); + } + else + DBUG_RETURN(my_open(FileName, Flags, MyFlags)); + } + + my_off_t my_raid_seek(File fd, my_off_t pos,int whence,myf MyFlags) + { + DBUG_ENTER("my_raid_seek"); + DBUG_PRINT("enter",("Fd: %d pos: %lu whence: %d MyFlags: %d", + fd, (ulong) pos, whence, MyFlags)); + + assert(pos != MY_FILEPOS_ERROR); + + if (is_raid(fd)) + { + RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); + DBUG_RETURN(raid->Seek(pos,whence,MyFlags)); + } + else + DBUG_RETURN(my_seek(fd, pos, whence, MyFlags)); + } + + my_off_t my_raid_tell(File fd,myf MyFlags) + { + DBUG_ENTER("my_raid_tell"); + DBUG_PRINT("enter",("Fd: %d MyFlags: %d", + fd, MyFlags)); + if (is_raid(fd)) + { + RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); + DBUG_RETURN(raid->Tell(MyFlags)); + } + else + DBUG_RETURN(my_tell(fd, MyFlags)); + } + + uint my_raid_write(File fd,const byte *Buffer, uint Count, myf MyFlags) + { + DBUG_ENTER("my_raid_write"); + DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u MyFlags: %d", + fd, Buffer, Count, MyFlags)); + if (is_raid(fd)) + { + RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); + DBUG_RETURN(raid->Write(Buffer,Count,MyFlags)); + } else + DBUG_RETURN(my_write(fd,Buffer,Count,MyFlags)); + } + + uint my_raid_read(File fd, byte *Buffer, uint Count, myf MyFlags) + { + DBUG_ENTER("my_raid_read"); + DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u MyFlags: %d", + fd, Buffer, Count, MyFlags)); + if (is_raid(fd)) + { + RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); + DBUG_RETURN(raid->Read(Buffer,Count,MyFlags)); + } else + DBUG_RETURN(my_read(fd,Buffer,Count,MyFlags)); + } + + uint my_raid_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset, + myf MyFlags) + { + DBUG_ENTER("my_raid_pread"); + DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u offset: %u MyFlags: %d", + Filedes, Buffer, Count, offset, MyFlags)); + if (is_raid(Filedes)) + { + assert(offset != MY_FILEPOS_ERROR); + + RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,Filedes,RaidFd**)); + /* Returning value isn't important because real seek is done later. */ + raid->Seek(offset,MY_SEEK_SET,MyFlags); + DBUG_RETURN(raid->Read(Buffer,Count,MyFlags)); + } + else + DBUG_RETURN(my_pread(Filedes, Buffer, Count, offset, MyFlags)); + } + + uint my_raid_pwrite(int Filedes, const byte *Buffer, uint Count, + my_off_t offset, myf MyFlags) + { + DBUG_ENTER("my_raid_pwrite"); + DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u offset: %u MyFlags: %d", + Filedes, Buffer, Count, offset, MyFlags)); + if (is_raid(Filedes)) + { + assert(offset != MY_FILEPOS_ERROR); + + RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,Filedes,RaidFd**)); + /* Returning value isn't important because real seek is done later. */ + raid->Seek(offset,MY_SEEK_SET,MyFlags); + DBUG_RETURN(raid->Write(Buffer,Count,MyFlags)); + } + else + DBUG_RETURN(my_pwrite(Filedes, Buffer, Count, offset, MyFlags)); + } + + int my_raid_lock(File fd, int locktype, my_off_t start, my_off_t length, + myf MyFlags) + { + DBUG_ENTER("my_raid_lock"); + DBUG_PRINT("enter",("Fd: %d start: %u length: %u MyFlags: %d", + fd, start, length, MyFlags)); + if (my_disable_locking) + DBUG_RETURN(0); + if (is_raid(fd)) + { + RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); + DBUG_RETURN(raid->Lock(locktype, start, length, MyFlags)); + } + else + DBUG_RETURN(my_lock(fd, locktype, start, length, MyFlags)); + } + + int my_raid_close(File fd, myf MyFlags) + { + DBUG_ENTER("my_raid_close"); + DBUG_PRINT("enter",("Fd: %d MyFlags: %d", + fd, MyFlags)); + if (is_raid(fd)) + { + RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); + RaidFd *tmp=0; + set_dynamic(&RaidFd::_raid_map,(char*) &tmp,fd); + int res = raid->Close(MyFlags); + delete raid; + DBUG_RETURN(res); + } + else + DBUG_RETURN(my_close(fd, MyFlags)); + } + + int my_raid_chsize(File fd, my_off_t newlength, myf MyFlags) + { + DBUG_ENTER("my_raid_chsize"); + DBUG_PRINT("enter",("Fd: %d newlength: %u MyFlags: %d", + fd, newlength, MyFlags)); + if (is_raid(fd)) + { + RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); + DBUG_RETURN(raid->Chsize(fd, newlength, MyFlags)); + } + else + DBUG_RETURN(my_chsize(fd, newlength, MyFlags)); + } + + int my_raid_rename(const char *from, const char *to, + uint raid_chunks, myf MyFlags) + { + char from_tmp[FN_REFLEN]; + char to_tmp[FN_REFLEN]; + DBUG_ENTER("my_raid_rename"); + + uint from_pos = dirname_length(from); + uint to_pos = dirname_length(to); + memcpy(from_tmp, from, from_pos); + memcpy(to_tmp, to, to_pos); + for (uint i = 0 ; i < raid_chunks ; i++ ) + { + sprintf(from_tmp+from_pos,"%02x/%s", i, from + from_pos); + sprintf(to_tmp+to_pos,"%02x/%s", i, to+ to_pos); + /* Convert if not unix */ + unpack_filename(from_tmp, from_tmp); + unpack_filename(to_tmp,to_tmp); + if (my_rename(from_tmp, to_tmp, MyFlags)) + DBUG_RETURN(-1); + } + DBUG_RETURN(0); + } + + int my_raid_delete(const char *from, uint raid_chunks, myf MyFlags) + { + char from_tmp[FN_REFLEN]; + uint from_pos = dirname_length(from); + DBUG_ENTER("my_raid_delete"); + + if (!raid_chunks) + DBUG_RETURN(my_delete(from,MyFlags)); + for (uint i = 0 ; i < raid_chunks ; i++ ) + { + memcpy(from_tmp, from, from_pos); + sprintf(from_tmp+from_pos,"%02x/%s", i, from + from_pos); + /* Convert if not unix */ + unpack_filename(from_tmp, from_tmp); + if (my_delete(from_tmp, MyFlags)) + DBUG_RETURN(-1); + } + DBUG_RETURN(0); + } + + int my_raid_redel(const char *old_name, const char *new_name, + uint raid_chunks, myf MyFlags) + { + char new_name_buff[FN_REFLEN], old_name_buff[FN_REFLEN]; + char *new_end, *old_end; + uint i,old_length,new_length; + int error=0; + DBUG_ENTER("my_raid_redel"); + + old_end=old_name_buff+dirname_part(old_name_buff,old_name); + old_length=dirname_length(old_name); + new_end=new_name_buff+dirname_part(new_name_buff,new_name); + new_length=dirname_length(new_name); + for (i=0 ; i < raid_chunks ; i++) + { + MY_STAT status; + sprintf(new_end,"%02x",i); + if (my_stat(new_name_buff,&status, MYF(0))) + { + DBUG_PRINT("info",("%02x exists, skipping directory creation",i)); + } + else + { + if (my_mkdir(new_name_buff,0777,MYF(0))) + { + DBUG_PRINT("error",("mkdir failed for %02x",i)); + DBUG_RETURN(-1); + } + } + strxmov(strend(new_end),"/",new_name+new_length,NullS); + sprintf(old_end,"%02x/%s",i, old_name+old_length); + if (my_redel(old_name_buff, new_name_buff, MyFlags)) + error=1; + } + DBUG_RETURN(error); + } +} + +int my_raid_fstat(int fd, MY_STAT *stat_area, myf MyFlags ) +{ + DBUG_ENTER("my_raid_fstat"); + if (is_raid(fd)) + { + RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); + DBUG_RETURN(raid->Fstat(fd, stat_area, MyFlags)); + } + else + DBUG_RETURN(my_fstat(fd, stat_area, MyFlags)); +} + + +/* -------------- RaidFd base class begins ----------------*/ +/* + RaidFd - raided file is identified by file descriptor + this is useful when we open/write/read/close files +*/ + + +bool RaidFd:: +IsRaid(File fd) +{ + DBUG_ENTER("RaidFd::IsRaid"); + DBUG_RETURN((uint) fd < _raid_map.elements && + *dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); +} + + +RaidFd:: +RaidFd(uint raid_type, uint raid_chunks, ulong raid_chunksize) + :_raid_type(raid_type), _raid_chunks(raid_chunks), + _raid_chunksize(raid_chunksize), _position(0), _fd_vector(0), + _size(RAID_SIZE_UNKNOWN) +{ + DBUG_ENTER("RaidFd::RaidFd"); + DBUG_PRINT("enter",("RaidFd_type: %u Disks: %u Chunksize: %d", + raid_type, raid_chunks, raid_chunksize)); + + /* TODO: Here we should add checks if the malloc fails */ + _seek_vector=0; /* In case of errors */ + my_multi_malloc(MYF(MY_WME), + &_seek_vector,sizeof(off_t)*_raid_chunks, + &_fd_vector, sizeof(File) *_raid_chunks, + NullS); + if (!RaidFd::_raid_map.buffer) + { /* Not initied */ + pthread_mutex_lock(&THR_LOCK_open); /* Ensure that no other thread */ + if (!RaidFd::_raid_map.buffer) /* has done init in between */ + init_raid(); + pthread_mutex_unlock(&THR_LOCK_open); + } + DBUG_VOID_RETURN; +} + + +RaidFd:: +~RaidFd() { + DBUG_ENTER("RaidFd::~RaidFd"); + /* We don't have to free _fd_vector ! */ + my_free((char*) _seek_vector, MYF(MY_ALLOW_ZERO_PTR)); + DBUG_VOID_RETURN; +} + + +File RaidFd:: +Create(const char *FileName, int CreateFlags, int access_flags, myf MyFlags) +{ + char RaidFdFileName[FN_REFLEN]; + DBUG_ENTER("RaidFd::Create"); + DBUG_PRINT("enter", + ("FileName: %s CreateFlags: %d access_flags: %d MyFlags: %d", + FileName, CreateFlags, access_flags, MyFlags)); + char DirName[FN_REFLEN]; + uint pos = dirname_part(DirName, FileName); + MY_STAT status; + if (!_seek_vector) + DBUG_RETURN(-1); /* Not enough memory */ + + uint i = _raid_chunks-1; + do + { + /* Create subdir */ + (void)sprintf(RaidFdFileName,"%s%02x", DirName,i); + unpack_dirname(RaidFdFileName,RaidFdFileName); /* Convert if not unix */ + if (my_stat(RaidFdFileName,&status, MYF(0))) + { + DBUG_PRINT("info",("%02x exists, skipping directory creation",i)); + } + else + { + if (my_mkdir(RaidFdFileName,0777,MYF(0))) + { + DBUG_PRINT("error",("mkdir failed for %d",i)); + goto error; + } + } + /* Create file */ + sprintf(RaidFdFileName,"%s%02x/%s",DirName, i, FileName + pos); + unpack_filename(RaidFdFileName,RaidFdFileName); /* Convert if not unix */ + _fd = my_create(RaidFdFileName, CreateFlags ,access_flags, (myf)MyFlags); + if (_fd < 0) + goto error; + _fd_vector[i]=_fd; + _seek_vector[i]=RAID_SEEK_DONE; + } while (i--); + _size=0; + DBUG_RETURN(_fd); /* Last filenr is pointer to map */ + +error: + { + int save_errno=my_errno; + while (++i < _raid_chunks) + { + my_close(_fd_vector[i],MYF(0)); + sprintf(RaidFdFileName,"%s%02x/%s",DirName, i, FileName + pos); + unpack_filename(RaidFdFileName,RaidFdFileName); + my_delete(RaidFdFileName,MYF(0)); + } + my_errno=save_errno; + } + DBUG_RETURN(-1); +} + + +File RaidFd:: +Open(const char *FileName, int Flags, myf MyFlags) +{ + DBUG_ENTER("RaidFd::Open"); + DBUG_PRINT("enter",("FileName: %s Flags: %d MyFlags: %d", + FileName, Flags, MyFlags)); + char DirName[FN_REFLEN]; + uint pos = dirname_part(DirName, FileName); + if (!_seek_vector) + DBUG_RETURN(-1); /* Not enough memory */ + + for( uint i = 0 ; i < _raid_chunks ; i++ ) + { + char RaidFdFileName[FN_REFLEN]; + sprintf(RaidFdFileName,"%s%02x/%s",DirName, i, FileName + pos); + unpack_filename(RaidFdFileName,RaidFdFileName); /* Convert if not unix */ + _fd = my_open(RaidFdFileName, Flags, MyFlags); + if (_fd < 0) + { + int save_errno=my_errno; + while (i-- != 0) + my_close(_fd_vector[i],MYF(0)); + my_errno=save_errno; + DBUG_RETURN(_fd); + } + _fd_vector[i]=_fd; + _seek_vector[i]=RAID_SEEK_DONE; + } + Seek(0L,MY_SEEK_END,MYF(0)); // Trick. We just need to know, how big the file is + DBUG_PRINT("info",("MYD file logical size: %llu", _size)); + DBUG_RETURN(_fd); +} + + +int RaidFd:: +Write(const byte *Buffer, uint Count, myf MyFlags) +{ + DBUG_ENTER("RaidFd::Write"); + DBUG_PRINT("enter",("Count: %d MyFlags: %d", + Count, MyFlags)); + const byte *bufptr = Buffer; + uint res=0, GotBytes, ReadNowCount; + + // Loop until data is written + do { + Calculate(); + // Do seeks when neccessary + if (_seek_vector[_this_block] != RAID_SEEK_DONE) + { + if (my_seek(_fd_vector[_this_block], _seek_vector[_this_block], + MY_SEEK_SET, + MyFlags) == MY_FILEPOS_ERROR) + DBUG_RETURN(-1); + _seek_vector[_this_block]=RAID_SEEK_DONE; + } + ReadNowCount = min(Count, _remaining_bytes); + GotBytes = my_write(_fd_vector[_this_block], bufptr, ReadNowCount, + MyFlags); + DBUG_PRINT("loop",("Wrote bytes: %d", GotBytes)); + if (GotBytes == MY_FILE_ERROR) + DBUG_RETURN(-1); + res+= GotBytes; + if (MyFlags & (MY_NABP | MY_FNABP)) + GotBytes=ReadNowCount; + bufptr += GotBytes; + Count -= GotBytes; + _position += GotBytes; + } while(Count); + set_if_bigger(_size,_position); + DBUG_RETURN(res); +} + + +int RaidFd:: +Read(const byte *Buffer, uint Count, myf MyFlags) +{ + DBUG_ENTER("RaidFd::Read"); + DBUG_PRINT("enter",("Count: %d MyFlags: %d", + Count, MyFlags)); + byte *bufptr = (byte *)Buffer; + uint res= 0, GotBytes, ReadNowCount; + + // Loop until all data is read (Note that Count may be 0) + while (Count) + { + Calculate(); + // Do seek when neccessary + if (_seek_vector[_this_block] != RAID_SEEK_DONE) + { + if (my_seek(_fd_vector[_this_block], _seek_vector[_this_block], + MY_SEEK_SET, + MyFlags) == MY_FILEPOS_ERROR) + DBUG_RETURN(-1); + _seek_vector[_this_block]=RAID_SEEK_DONE; + } + // and read + ReadNowCount = min(Count, _remaining_bytes); + GotBytes = my_read(_fd_vector[_this_block], bufptr, ReadNowCount, + MyFlags & ~(MY_NABP | MY_FNABP)); + DBUG_PRINT("loop",("Got bytes: %u", GotBytes)); + if (GotBytes == MY_FILE_ERROR) + DBUG_RETURN(-1); + if (!GotBytes) // End of file. + { + DBUG_RETURN((MyFlags & (MY_NABP | MY_FNABP)) ? -1 : (int) res); + } + res+= GotBytes; + bufptr += GotBytes; + Count -= GotBytes; + _position += GotBytes; + } + DBUG_RETURN((MyFlags & (MY_NABP | MY_FNABP)) ? 0 : res); +} + + +int RaidFd:: +Lock(int locktype, my_off_t start, my_off_t length, myf MyFlags) +{ + DBUG_ENTER("RaidFd::Lock"); + DBUG_PRINT("enter",("locktype: %d start: %lu length: %lu MyFlags: %d", + locktype, start, length, MyFlags)); + my_off_t bufptr = start; + // Loop until all data is locked + while(length) + { + Calculate(); + for (uint i = _this_block ; (i < _raid_chunks) && length ; i++ ) + { + uint ReadNowCount = min(length, _remaining_bytes); + uint GotBytes = my_lock(_fd_vector[i], locktype, bufptr, ReadNowCount, + MyFlags); + if ((int) GotBytes == -1) + DBUG_RETURN(-1); + bufptr += ReadNowCount; + length -= ReadNowCount; + Calculate(); + } + } + DBUG_RETURN(0); +} + + +int RaidFd:: +Close(myf MyFlags) +{ + DBUG_ENTER("RaidFd::Close"); + DBUG_PRINT("enter",("MyFlags: %d", + MyFlags)); + for (uint i = 0 ; i < _raid_chunks ; ++i ) + { + int err = my_close(_fd_vector[i], MyFlags); + if (err != 0) + DBUG_RETURN(err); + } + /* _fd_vector is erased when RaidFd is released */ + DBUG_RETURN(0); +} + + +my_off_t RaidFd:: +Seek(my_off_t pos,int whence,myf MyFlags) +{ + DBUG_ENTER("RaidFd::Seek"); + DBUG_PRINT("enter",("Pos: %lu Whence: %d MyFlags: %d", + (ulong) pos, whence, MyFlags)); + switch (whence) { + case MY_SEEK_CUR: + // FIXME: This is wrong, what is going on there + // Just I am relied on fact that MySQL 3.23.7 never uses MY_SEEK_CUR + // for anything else except things like ltell() + break; + case MY_SEEK_SET: + if ( _position != pos) // we can be already in right place + { + uint i; + off_t _rounds; + _position = pos; + Calculate(); + _rounds = _total_block / _raid_chunks; // INT() assumed + _rounds*= _raid_chunksize; + for (i = 0; i < _raid_chunks ; i++ ) + if ( i < _this_block ) + _seek_vector[i] = _rounds + _raid_chunksize; + else if ( i == _this_block ) + _seek_vector[i] = _rounds + _raid_chunksize -_remaining_bytes; + else // if ( i > _this_block ) + _seek_vector[i] = _rounds; + } + break; + case MY_SEEK_END: + if (_size==RAID_SIZE_UNKNOWN) // We don't know table size yet + { + uint i; + _position = 0; + for (i = 0; i < _raid_chunks ; i++ ) + { + my_off_t newpos = my_seek(_fd_vector[i], 0L, MY_SEEK_END, MyFlags); + if (newpos == MY_FILEPOS_ERROR) + DBUG_RETURN (MY_FILEPOS_ERROR); + _seek_vector[i]=RAID_SEEK_DONE; + _position += newpos; + } + _size=_position; + } + else if (_position != _size) // Aren't we also already in the end? + { + uint i; + off_t _rounds; + _position = _size; + Calculate(); + _rounds = _total_block / _raid_chunks; // INT() assumed + _rounds*= _raid_chunksize; + for (i = 0; i < _raid_chunks ; i++ ) + if ( i < _this_block ) + _seek_vector[i] = _rounds + _raid_chunksize; + else if ( i == _this_block ) + _seek_vector[i] = _rounds + _raid_chunksize - _remaining_bytes; + else // if ( i > _this_block ) + _seek_vector[i] = _rounds; + _position=_size; + } + } + DBUG_RETURN(_position); +} + + +my_off_t RaidFd:: +Tell(myf MyFlags) +{ + DBUG_ENTER("RaidFd::Tell"); + DBUG_PRINT("enter",("MyFlags: %d _position %d", + MyFlags,_position)); + DBUG_RETURN(_position); +} + +int RaidFd:: +Chsize(File fd, my_off_t newlength, myf MyFlags) +{ + DBUG_ENTER("RaidFd::Chsize"); + DBUG_PRINT("enter",("Fd: %d, newlength: %d, MyFlags: %d", + fd, newlength,MyFlags)); + _position = newlength; + Calculate(); + uint _rounds = _total_block / _raid_chunks; // INT() assumed + for (uint i = 0; i < _raid_chunks ; i++ ) + { + int newpos; + if ( i < _this_block ) + newpos = my_chsize(_fd_vector[i], + _this_block * _raid_chunksize + (_rounds + 1) * + _raid_chunksize, + MyFlags); + else if ( i == _this_block ) + newpos = my_chsize(_fd_vector[i], + _this_block * _raid_chunksize + _rounds * + _raid_chunksize + (newlength % _raid_chunksize), + MyFlags); + else // this means: i > _this_block + newpos = my_chsize(_fd_vector[i], + _this_block * _raid_chunksize + _rounds * + _raid_chunksize, MyFlags); + if (newpos) + DBUG_RETURN(1); + } + DBUG_RETURN(0); +} + + +int RaidFd:: +Fstat(int fd, MY_STAT *stat_area, myf MyFlags ) +{ + DBUG_ENTER("RaidFd::Fstat"); + DBUG_PRINT("enter",("fd: %d MyFlags: %d",fd,MyFlags)); + uint i; + int error=0; + MY_STAT my_stat; + stat_area->st_size=0; + stat_area->st_mtime=0; + stat_area->st_atime=0; + stat_area->st_ctime=0; + + for(i=0 ; i < _raid_chunks ; i++) + { + if (my_fstat(_fd_vector[i],&my_stat,MyFlags)) + error=1; + stat_area->st_size+=my_stat.st_size; + set_if_bigger(stat_area->st_mtime,my_stat.st_mtime); + set_if_bigger(stat_area->st_atime,my_stat.st_atime); + set_if_bigger(stat_area->st_ctime,my_stat.st_ctime); + } + DBUG_RETURN(error); +} + +#endif /* defined(USE_RAID) && !defined(MYSQL_CLIENT) */ diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c new file mode 100644 index 00000000000..d715f69e38a --- /dev/null +++ b/mysys/safemalloc.c @@ -0,0 +1,518 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* + * [This posting refers to an article entitled "oops, corrupted memory + * again!" in net.lang.c. I am posting it here because it is source.] + * + * My tool for approaching this problem is to build another level of data + * abstraction on top of malloc() and free() that implements some checking. + * This does a number of things for you: + * - Checks for overruns and underruns on allocated data + * - Keeps track of where in the program the memory was malloc'ed + * - Reports on pieces of memory that were not free'ed + * - Records some statistics such as maximum memory used + * - Marks newly malloc'ed and newly free'ed memory with special values + * You can use this scheme to: + * - Find bugs such as overrun, underrun, etc because you know where + * a piece of data was malloc'ed and where it was free'ed + * - Find bugs where memory was not free'ed + * - Find bugs where newly malloc'ed memory is used without initializing + * - Find bugs where newly free'ed memory is still used + * - Determine how much memory your program really uses + * - and other things + */ + +/* + * To implement my scheme you must have a C compiler that has __LINE__ and + * __FILE__ macros. If your compiler doesn't have these then (a) buy another: + * compilers that do are available on UNIX 4.2bsd based systems and the PC, + * and probably on other machines; or (b) change my scheme somehow. I have + * recomendations on both these points if you would like them (e-mail please). + * + * There are 4 functions in my package: + * char *NEW( uSize ) Allocate memory of uSize bytes + * (equivalent to malloc()) + * char *REA( pPtr, uSize) Allocate memory of uSize bytes, move data and + * free pPtr. + * (equivalent to realloc()) + * FREE( pPtr ) Free memory allocated by NEW + * (equivalent to free()) + * TERMINATE(file) End system, report errors and stats on file + * I personally use two more functions, but have not included them here: + * char *STRSAVE( sPtr ) Save a copy of the string in dynamic memory + * char *RENEW( pPtr, uSize ) + * (equivalent to realloc()) + */ + +/* + * Memory sub-system, written by Bjorn Benson + Fixed to use my_sys scheme by Michael Widenius + */ + +#ifndef SAFEMALLOC +#define SAFEMALLOC /* Get protos from my_sys */ +#endif + +#include "mysys_priv.h" +#include <m_string.h> +#include "my_static.h" +#include "mysys_err.h" + +#define pNext tInt._pNext +#define pPrev tInt._pPrev +#define sFileName tInt._sFileName +#define uLineNum tInt._uLineNum +#define uDataSize tInt._uDataSize +#define lSpecialValue tInt._lSpecialValue + + /* Static functions prototypes */ + +static int check_ptr(const char *where, byte *ptr, const char *sFile, + uint uLine); +static int _checkchunk(struct remember *pRec, const char *sFile, uint uLine); + +/* + * Note: both these refer to the NEW'ed + * data only. They do not include + * malloc() roundoff or the extra + * space required by the remember + * structures. + */ + +#define ALLOC_VAL (uchar) 0xA5 /* NEW'ed memory is filled with this */ + /* value so that references to it will */ + /* end up being very strange. */ +#define FREE_VAL (uchar) 0x8F /* FREE'ed memory is filled with this */ + /* value so that references to it will */ + /* also end up being strange. */ + +#define MAGICKEY 0x14235296 /* A magic value for underrun key */ +#define MAGICEND0 0x68 /* Magic values for overrun keys */ +#define MAGICEND1 0x34 /* " */ +#define MAGICEND2 0x7A /* " */ +#define MAGICEND3 0x15 /* " */ + + /* Warning: do not change the MAGICEND? values to */ + /* something with the high bit set. Various C */ + /* compilers (like the 4.2bsd one) do not do the */ + /* sign extension right later on in this code and */ + /* you will get erroneous errors. */ + + +/* + * gptr _mymalloc( uint uSize, my_string sFile, uint uLine, MyFlags ) + * Allocate some memory. + */ + +gptr _mymalloc (uint uSize, const char *sFile, uint uLine, myf MyFlags) +{ + struct remember *pTmp; + DBUG_ENTER("_mymalloc"); + DBUG_PRINT("enter",("Size: %u",uSize)); + + if (!sf_malloc_quick) + (void) _sanity (sFile, uLine); + + /* Allocate the physical memory */ + pTmp = (struct remember *) malloc ( + sizeof (struct irem) /* remember data */ + + sf_malloc_prehunc + + uSize /* size requested */ + + 4 /* overrun mark */ + + sf_malloc_endhunc + ); + + /* Check if there isn't anymore memory avaiable */ + if (pTmp == NULL) + { + if (MyFlags & MY_FAE) + error_handler_hook=fatal_error_handler_hook; + if (MyFlags & (MY_FAE+MY_WME)) + { + char buff[SC_MAXWIDTH]; + my_errno=errno; + sprintf(buff,"Out of memory at line %d, '%s'", uLine, sFile); + my_message(EE_OUTOFMEMORY,buff,MYF(ME_BELL+ME_WAITTANG)); + sprintf(buff,"needed %d byte (%ldk), memory in use: %ld bytes (%ldk)", + uSize, (uSize + 1023L) / 1024L, + lMaxMemory, (lMaxMemory + 1023L) / 1024L); + my_message(EE_OUTOFMEMORY,buff,MYF(ME_BELL+ME_WAITTANG)); + } + DBUG_PRINT("error",("Out of memory, in use: %ld at line %d, '%s'", + lMaxMemory,uLine, sFile)); + if (MyFlags & MY_FAE) + exit(1); + DBUG_RETURN ((gptr) NULL); + } + + /* Fill up the structure */ + *((long*) ((char*) &pTmp -> lSpecialValue+sf_malloc_prehunc)) = MAGICKEY; + pTmp -> aData[uSize + sf_malloc_prehunc+0] = MAGICEND0; + pTmp -> aData[uSize + sf_malloc_prehunc+1] = MAGICEND1; + pTmp -> aData[uSize + sf_malloc_prehunc+2] = MAGICEND2; + pTmp -> aData[uSize + sf_malloc_prehunc+3] = MAGICEND3; + pTmp -> sFileName = (my_string) sFile; + pTmp -> uLineNum = uLine; + pTmp -> uDataSize = uSize; + pTmp -> pPrev = NULL; + + /* Add this remember structure to the linked list */ + pthread_mutex_lock(&THR_LOCK_malloc); + if ((pTmp->pNext=pRememberRoot)) + { + pRememberRoot -> pPrev = pTmp; + } + pRememberRoot = pTmp; + + /* Keep the statistics */ + lCurMemory += uSize; + if (lCurMemory > lMaxMemory) { + lMaxMemory = lCurMemory; + } + cNewCount++; + pthread_mutex_unlock(&THR_LOCK_malloc); + + /* Set the memory to the aribtrary wierd value */ +#ifdef HAVE_purify + if (MyFlags & MY_ZEROFILL) +#endif + bfill(&pTmp -> aData[sf_malloc_prehunc],uSize, + (char) (MyFlags & MY_ZEROFILL ? 0 : ALLOC_VAL)); + /* Return a pointer to the real data */ + DBUG_PRINT("exit",("ptr: %lx",&(pTmp -> aData[sf_malloc_prehunc]))); + if (sf_min_adress > &(pTmp -> aData[sf_malloc_prehunc])) + sf_min_adress = &(pTmp -> aData[sf_malloc_prehunc]); + if (sf_max_adress < &(pTmp -> aData[sf_malloc_prehunc])) + sf_max_adress = &(pTmp -> aData[sf_malloc_prehunc]); + DBUG_RETURN ((gptr) &(pTmp -> aData[sf_malloc_prehunc])); +} + +/* + * Allocate some new memory and move old memoryblock there. + * Free then old memoryblock + */ + +gptr _myrealloc (register gptr pPtr, register uint uSize, + const char *sFile, uint uLine, myf MyFlags) +{ + struct remember *pRec; + gptr ptr; + DBUG_ENTER("_myrealloc"); + + if (!pPtr && (MyFlags & MY_ALLOW_ZERO_PTR)) + DBUG_RETURN(_mymalloc(uSize,sFile,uLine,MyFlags)); + + if (!sf_malloc_quick) + (void) _sanity (sFile, uLine); + + if (check_ptr("Reallocating",(byte*) pPtr,sFile,uLine)) + DBUG_RETURN((gptr) NULL); + + pRec = (struct remember *) ((char*) pPtr - sizeof (struct irem)- + sf_malloc_prehunc); + if (*((long*) ((char*) &pRec -> lSpecialValue+sf_malloc_prehunc)) + != MAGICKEY) + { + fprintf (stderr, "Reallocating unallocated data at line %d, '%s'\n", + uLine, sFile); + DBUG_PRINT("safe",("Reallocating unallocated data at line %d, '%s'", + uLine, sFile)); + (void) fflush(stderr); + DBUG_RETURN((gptr) NULL); + } + + if ((ptr=_mymalloc(uSize,sFile,uLine,MyFlags))) /* Allocate new area */ + { + uSize=min(uSize,pRec-> uDataSize); /* Move as much as possibly */ + memcpy((byte*) ptr,pPtr,(size_t) uSize); /* Copy old data */ + _myfree(pPtr,sFile,uLine,0); /* Free not needed area */ + } + else + { + if (MyFlags & MY_HOLD_ON_ERROR) + DBUG_RETURN(pPtr); + if (MyFlags & MY_FREE_ON_ERROR) + _myfree(pPtr,sFile,uLine,0); + } + DBUG_RETURN(ptr); +} /* _myrealloc */ + + +/* + * void _myfree( my_string pPtr, my_string sFile, uint uLine, myf myflags) + * Deallocate some memory. + */ + +void _myfree (gptr pPtr, const char *sFile, uint uLine, myf myflags) +{ + struct remember *pRec; + DBUG_ENTER("_myfree"); + DBUG_PRINT("enter",("ptr: %lx",pPtr)); + + if (!sf_malloc_quick) + (void) _sanity (sFile, uLine); + + if ((!pPtr && (myflags & MY_ALLOW_ZERO_PTR)) || + check_ptr("Freeing",(byte*) pPtr,sFile,uLine)) + DBUG_VOID_RETURN; + + /* Calculate the address of the remember structure */ + pRec = (struct remember *) ((byte*) pPtr-sizeof(struct irem)- + sf_malloc_prehunc); + + /* Check to make sure that we have a real remember structure */ + /* Note: this test could fail for four reasons: */ + /* (1) The memory was already free'ed */ + /* (2) The memory was never new'ed */ + /* (3) There was an underrun */ + /* (4) A stray pointer hit this location */ + + if (*((long*) ((char*) &pRec -> lSpecialValue+sf_malloc_prehunc)) + != MAGICKEY) + { + fprintf (stderr, "Freeing unallocated data at line %d, '%s'\n", + uLine, sFile); + DBUG_PRINT("safe",("Unallocated data at line %d, '%s'",uLine,sFile)); + (void) fflush(stderr); + DBUG_VOID_RETURN; + } + + /* Remove this structure from the linked list */ + pthread_mutex_lock(&THR_LOCK_malloc); + if (pRec -> pPrev) { + pRec -> pPrev -> pNext = pRec -> pNext; + } else { + pRememberRoot = pRec -> pNext; + } + if (pRec -> pNext) { + pRec -> pNext -> pPrev = pRec -> pPrev; + } + /* Handle the statistics */ + lCurMemory -= pRec -> uDataSize; + cNewCount--; + pthread_mutex_unlock(&THR_LOCK_malloc); + +#ifndef HAVE_purify + /* Mark this data as free'ed */ + bfill(&pRec->aData[sf_malloc_prehunc],pRec->uDataSize,(pchar) FREE_VAL); +#endif + *((long*) ((char*) &pRec -> lSpecialValue+sf_malloc_prehunc)) = ~MAGICKEY; + + /* Actually free the memory */ + free ((my_string ) pRec); + DBUG_VOID_RETURN; +} + + /* Check if we have a wrong pointer */ + +static int check_ptr(const char *where, byte *ptr, const char *sFile, + uint uLine) +{ + if (!ptr) + { + fprintf (stderr, "%s NULL pointer at line %d, '%s'\n", + where,uLine, sFile); + DBUG_PRINT("safe",("Null pointer at line %d '%s'", uLine, sFile)); + (void) fflush(stderr); + return 1; + } +#ifndef _MSC_VER + if ((long) ptr & (MY_ALIGN(1,sizeof(char *))-1)) + { + fprintf (stderr, "%s wrong aligned pointer at line %d, '%s'\n", + where,uLine, sFile); + DBUG_PRINT("safe",("Wrong aligned pointer at line %d, '%s'", + uLine,sFile)); + (void) fflush(stderr); + return 1; + } +#endif + if (ptr < sf_min_adress || ptr > sf_max_adress) + { + fprintf (stderr, "%s pointer out of range at line %d, '%s'\n", + where,uLine, sFile); + DBUG_PRINT("safe",("Pointer out of range at line %d '%s'", + uLine,sFile)); + (void) fflush(stderr); + return 1; + } + return 0; +} + + +/* + * TERMINATE(FILE *file) + * Report on all the memory pieces that have not been + * free'ed as well as the statistics. + */ + +void TERMINATE (FILE *file) +{ + struct remember *pPtr; + DBUG_ENTER("TERMINATE"); + pthread_mutex_lock(&THR_LOCK_malloc); + + /* Report the difference between number of calls to */ + /* NEW and the number of calls to FREE. >0 means more */ + /* NEWs than FREEs. <0, etc. */ + + if (cNewCount) + { + if (file) + { + fprintf (file, "cNewCount: %d\n", cNewCount); + (void) fflush(file); + } + DBUG_PRINT("safe",("cNewCount: %d",cNewCount)); + } + + /* Report on all the memory that was allocated with NEW */ + /* but not free'ed with FREE. */ + + if ((pPtr=pRememberRoot)) + { + if (file) + { + fprintf(file, "Memory that was not free'ed (%ld bytes):\n",lCurMemory); + (void) fflush(file); + } + DBUG_PRINT("safe",("Memory that was not free'ed (%ld bytes):",lCurMemory)); + while (pPtr) + { + if (file) + { + fprintf (file, + "\t%6u bytes at 0x%09lx, allocated at line %4u in '%s'\n", + pPtr -> uDataSize, + (ulong) &(pPtr -> aData[sf_malloc_prehunc]), + pPtr -> uLineNum, pPtr -> sFileName); + (void) fflush(file); + } + DBUG_PRINT("safe", + ("%6u bytes at 0x%09lx, allocated at line %4d in '%s'", + pPtr -> uDataSize, &(pPtr -> aData[sf_malloc_prehunc]), + pPtr -> uLineNum, pPtr -> sFileName)); + pPtr = pPtr -> pNext; + } + } + /* Report the memory usage statistics */ + if (file) + { + fprintf (file, "Maximum memory usage: %ld bytes (%ldk)\n", + lMaxMemory, (lMaxMemory + 1023L) / 1024L); + (void) fflush(file); + } + DBUG_PRINT("safe",("Maximum memory usage: %ld bytes (%ldk)", + lMaxMemory, (lMaxMemory + 1023L) / 1024L)); + pthread_mutex_unlock(&THR_LOCK_malloc); + DBUG_VOID_RETURN; +} + + + /* Returns 0 if chunk is ok */ + +static int _checkchunk (register struct remember *pRec, const char *sFile, + uint uLine) +{ + reg1 uint uSize; + reg2 my_string magicp; + reg3 int flag=0; + + /* Check for a possible underrun */ + if (*((long*) ((char*) &pRec -> lSpecialValue+sf_malloc_prehunc)) + != MAGICKEY) + { + fprintf (stderr, "Memory allocated at %s:%d was underrun,", + pRec -> sFileName, pRec -> uLineNum); + fprintf (stderr, " discovered at %s:%d\n", sFile, uLine); + (void) fflush(stderr); + DBUG_PRINT("safe",("Underrun at %lx, allocated at %s:%d", + &(pRec -> aData[sf_malloc_prehunc]), + pRec -> sFileName, + pRec -> uLineNum)); + flag=1; + } + + /* Check for a possible overrun */ + uSize = pRec -> uDataSize; + magicp = &(pRec -> aData[uSize+sf_malloc_prehunc]); + if (*magicp++ != MAGICEND0 || + *magicp++ != MAGICEND1 || + *magicp++ != MAGICEND2 || + *magicp++ != MAGICEND3) + { + fprintf (stderr, "Memory allocated at %s:%d was overrun,", + pRec -> sFileName, pRec -> uLineNum); + fprintf (stderr, " discovered at '%s:%d'\n", sFile, uLine); + (void) fflush(stderr); + DBUG_PRINT("safe",("Overrun at %lx, allocated at %s:%d", + &(pRec -> aData[sf_malloc_prehunc]), + pRec -> sFileName, + pRec -> uLineNum)); + flag=1; + } + return(flag); +} + + + /* Returns how many wrong chunks */ + +int _sanity (const char *sFile, uint uLine) +{ + reg1 struct remember *pTmp; + reg2 int flag=0; + uint count=0; + + pthread_mutex_lock(&THR_LOCK_malloc); + count=cNewCount; + for (pTmp = pRememberRoot; pTmp != NULL && count-- ; pTmp = pTmp -> pNext) + flag+=_checkchunk (pTmp, sFile, uLine); + pthread_mutex_unlock(&THR_LOCK_malloc); + if (count || pTmp) + { + const char *format="Safemalloc link list destroyed, discovered at '%s:%d'"; + fprintf (stderr, format, sFile, uLine); fputc('\n',stderr); + (void) fflush(stderr); + DBUG_PRINT("safe",(format, sFile, uLine)); + flag=1; + } + return flag; +} /* _sanity */ + + + /* malloc and copy */ + +gptr _my_memdup(const byte *from, uint length, const char *sFile, uint uLine, + myf MyFlags) +{ + gptr ptr; + if ((ptr=_mymalloc(length,sFile,uLine,MyFlags)) != 0) + memcpy((byte*) ptr, (byte*) from,(size_t) length); + return(ptr); +} /*_my_memdup */ + + +my_string _my_strdup(const char *from, const char *sFile, uint uLine, + myf MyFlags) +{ + gptr ptr; + uint length=(uint) strlen(from)+1; + if ((ptr=_mymalloc(length,sFile,uLine,MyFlags)) != 0) + memcpy((byte*) ptr, (byte*) from,(size_t) length); + return((my_string) ptr); +} /* _my_strdup */ diff --git a/mysys/string.c b/mysys/string.c new file mode 100644 index 00000000000..f7e265a43e6 --- /dev/null +++ b/mysys/string.c @@ -0,0 +1,117 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* + Code for handling strings with can grow dynamicly. + Copyright Monty Program KB. + By monty. +*/ + +#include "mysys_priv.h" +#include <m_string.h> + +my_bool init_dynamic_string(DYNAMIC_STRING *str, const char *init_str, + uint init_alloc, uint alloc_increment) +{ + uint length; + DBUG_ENTER("init_dynamic_string"); + + if (!alloc_increment) + alloc_increment=128; + length=1; + if (init_str && (length=strlen(init_str)+1) < init_alloc) + init_alloc=((length+alloc_increment-1)/alloc_increment)*alloc_increment; + if (!init_alloc) + init_alloc=alloc_increment; + + if (!(str->str=(char*) my_malloc(init_alloc,MYF(MY_WME)))) + DBUG_RETURN(TRUE); + str->length=length-1; + if (init_str) + memcpy(str->str,init_str,length); + str->max_length=init_alloc; + str->alloc_increment=alloc_increment; + DBUG_RETURN(FALSE); +} + +my_bool dynstr_set(DYNAMIC_STRING *str, const char *init_str) +{ + uint length; + DBUG_ENTER("dynstr_set"); + + if (init_str && (length=strlen(init_str)+1) > str->max_length) + { + str->max_length=((length+str->alloc_increment-1)/str->alloc_increment)* + str->alloc_increment; + if (!str->max_length) + str->max_length=str->alloc_increment; + if (!(str->str=(char*) my_realloc(str->str,str->max_length,MYF(MY_WME)))) + DBUG_RETURN(TRUE); + } + if (init_str) + { + str->length=length-1; + memcpy(str->str,init_str,length); + } + else + str->length=0; + DBUG_RETURN(FALSE); +} + +my_bool dynstr_realloc(DYNAMIC_STRING *str, ulong additional_size) +{ + DBUG_ENTER("dynstr_realloc"); + + if (!additional_size) DBUG_RETURN(FALSE); + if (str->length + additional_size > str->max_length) + { + str->max_length=((str->length + additional_size+str->alloc_increment-1)/ + str->alloc_increment)*str->alloc_increment; + if (!(str->str=(char*) my_realloc(str->str,str->max_length,MYF(MY_WME)))) + DBUG_RETURN(TRUE); + } + DBUG_RETURN(FALSE); +} + + +my_bool dynstr_append(DYNAMIC_STRING *str, const char *append) +{ + char *new_ptr; + uint length=(uint) strlen(append)+1; + if (str->length+length > str->max_length) + { + uint new_length=(str->length+length+str->alloc_increment-1)/ + str->alloc_increment; + new_length*=str->alloc_increment; + if (!(new_ptr=(char*) my_realloc(str->str,new_length,MYF(MY_WME)))) + return TRUE; + str->str=new_ptr; + str->max_length=new_length; + } + memcpy(str->str + str->length,append,length); + str->length+=length-1; + return FALSE; +} + +void dynstr_free(DYNAMIC_STRING *str) +{ + if (str->str) + { + my_free(str->str,MYF(MY_WME)); + str->str=0; + } +} diff --git a/mysys/test_charset.c b/mysys/test_charset.c new file mode 100644 index 00000000000..a04bdbd9a58 --- /dev/null +++ b/mysys/test_charset.c @@ -0,0 +1,59 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include <global.h> +#include <m_ctype.h> +#include <my_sys.h> +#include <mysql_version.h> + +#include <stdio.h> + +extern void _print_csinfo(); + +int main(int argc, char **argv) { + const char *the_set = MYSQL_CHARSET; + char *cs_list; + int argcnt = 1; + + my_init(); + + if (argc > argcnt && argv[argcnt][0] == '-' && argv[argcnt][1] == '#') + DBUG_PUSH(argv[argcnt++]+2); + + if (argc > argcnt) + the_set = argv[argcnt++]; + + if (argc > argcnt) + charsets_dir = argv[argcnt++]; + + if (set_default_charset_by_name(the_set, MYF(MY_WME))) + return 1; + + puts("CHARSET INFO:"); + _print_csinfo(default_charset_info); + fflush(stdout); + + cs_list = list_charsets(MYF(MY_COMPILED_SETS | MY_CONFIG_SETS)); + printf("LIST OF CHARSETS (compiled + *.conf):\n%s\n", cs_list); + free(cs_list); + + cs_list = list_charsets(MYF(MY_INDEX_SETS | MY_LOADED_SETS)); + printf("LIST OF CHARSETS (index + loaded):\n%s\n", cs_list); + free(cs_list); + + return 0; +} diff --git a/mysys/test_dir.c b/mysys/test_dir.c new file mode 100644 index 00000000000..fafdde137b6 --- /dev/null +++ b/mysys/test_dir.c @@ -0,0 +1,50 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* TODO: Test all functions */ + +#define USES_TYPES +#include "mysys_priv.h" +#include "my_dir.h" + +int main(int argc, char *argv[]) +{ + MY_DIR *a; + uint f; + DBUG_ENTER ("main"); + DBUG_PROCESS (argv[0]); + + if (--argc > 0 && (*(++argv))[0] == '-' && (*argv)[1] == '#' ) + DBUG_PUSH (*argv+2); + + a = my_dir("./", 0); + for (f = 0; f < a->number_off_files; f++) + { + printf("%s\n", a->dir_entry[f].name); + } + + a = my_dir("./", MY_WANT_STAT); + for (f = 0; f < a->number_off_files; f++) + { + printf("%s %d %d %d %s\n", a->dir_entry[f].name, + (int) a->dir_entry[f].mystat.st_size, + (int) a->dir_entry[f].mystat.st_uid, + (int) a->dir_entry[f].mystat.st_gid, + S_ISDIR(a->dir_entry[f].mystat.st_mode) ? "dir" : ""); + } + return 0; +} diff --git a/mysys/test_fn.c b/mysys/test_fn.c new file mode 100644 index 00000000000..224b899ebe1 --- /dev/null +++ b/mysys/test_fn.c @@ -0,0 +1,70 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" + +const char *test_names[]= +{ + "/usr/my/include/srclib/myfunc/dbug/test", + "test", + "dbug/test", + "/usr/my/srclib/myfunc/dbug/test", + "/usr/monty/oldcopy/jazz/setupp.frm", + "~/monty.tst", + "~/dbug/monty.tst", + "./hejsan", + "./dbug/test", + "../dbug/test", + "../myfunc/test", + "../../monty/rutedit", + "/usr/monty//usr/monty/rutedit", + "/usr/./monty/rutedit", + "/usr/my/../monty/rutedit", + "/usr/my/~/rutedit", + "~/../my", + "~/../my/srclib/myfunc/test", + "~/../my/srclib/myfunc/./dbug/test", + "/../usr/my/srclib/dbug", + "c/../my", + "/c/../my", + NullS, +}; + +int main(int argc __attribute__((unused)), char **argv) +{ + const char **pos; + char buff[FN_REFLEN],buff2[FN_REFLEN]; + DBUG_ENTER ("main"); + DBUG_PROCESS (argv[0]); + MY_INIT(argv[0]); + + if (argv[1] && argv[1][1] == '#') + DBUG_PUSH(argv[1]+2); + + for (pos=test_names; *pos ; pos++) + { + printf("org : '%s'\n",*pos); + printf("pack: '%s'\n",fn_format(buff,*pos,"","",8)); + printf("unpack: '%s'\n",fn_format(buff2,*pos,"","",4)); + if (strcmp(unpack_filename(buff,buff),buff2) != 0) + { + printf("error on cmp: '%s' != '%s'\n",buff,buff2); + } + puts(""); + } + DBUG_RETURN(0); +} diff --git a/mysys/test_vsnprintf.c b/mysys/test_vsnprintf.c new file mode 100644 index 00000000000..b9ffb014181 --- /dev/null +++ b/mysys/test_vsnprintf.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "mysys_priv.h" + +static void my_printf(const char * fmt, ...) +{ + char buf[32]; + int n; + va_list ar; + va_start(ar, fmt); + n = my_vsnprintf(buf, sizeof(buf),fmt, ar); + printf(buf); + printf("n=%d, strlen=%d\n", n, strlen(buf)); + va_end(ar); +} + +int main() +{ + + my_printf("Hello\n"); + my_printf("Hello int, %d\n", 1); + my_printf("Hello string '%s'\n", "I am a string"); + my_printf("Hello hack hack hack hack hack hack hack %d\n", 1); + my_printf("Hello %d hack %d\n", 1, 4); + my_printf("Hello %d hack hack hack hack hack %d\n", 1, 4); + my_printf("Hello '%s' hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n", "hack"); + my_printf("Hello hhhhhhhhhhhhhh %d sssssssssssssss\n", 1); + my_printf("Hello %u\n", 1); + return 0; +} diff --git a/mysys/testhash.c b/mysys/testhash.c new file mode 100644 index 00000000000..a8fbf800595 --- /dev/null +++ b/mysys/testhash.c @@ -0,0 +1,291 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Test av hash libarary: stor test */ + +#include <global.h> +#include <my_sys.h> +#include <hash.h> +#include <m_string.h> + +#define MAX_RECORDS 100000 +#define MAX_KEYS 3 + +static int get_options(int argc, char *argv[]); +static int do_test(); +static int rnd(int max_value); + +static uint testflag=0,recant=10000,reclength=37; +static uint16 key1[1000]; + +#ifdef DBUG_OFF +#define hash_check(A) 0 +#else +my_bool hash_check(HASH *hash); +#endif +void free_record(void *record); + +static byte *hash2_key(const byte *rec,uint *length, + my_bool not_used __attribute__((unused))) +{ + *length=(uint) (uchar) rec[reclength-1]; + return (byte*) rec; +} + + /* Huvudprogrammet */ + +int main(int argc,char *argv[]) +{ + MY_INIT(argv[0]); + DBUG_PROCESS(argv[0]); + + get_options(argc,argv); + + exit(do_test()); +} + +static int do_test() +{ + register uint i,j; + uint n1,n2,n3; + uint write_count,update,delete; + ulong pos; + unsigned long key_check; + char *record,*recpos,oldrecord[120],key[10]; + HASH hash,hash2; + DBUG_ENTER("do_test"); + + write_count=update=delete=0; + key_check=0; + bzero((char*) key1,sizeof(key1[0])*1000); + + printf("- Creating hash\n"); + if (hash_init(&hash,recant/2,0,6,0,free_record,0)) + goto err; + printf("- Writing records:s\n"); + + for (i=0 ; i < recant ; i++) + { + n1=rnd(1000); n2=rnd(100); n3=rnd(min(recant*5,MAX_RECORDS)); + record= (char*) my_malloc(reclength,MYF(MY_FAE)); + sprintf(record,"%6d:%4d:%8d:Pos: %4d ",n1,n2,n3,write_count); + if (hash_insert(&hash,record)) + { + printf("Error: %d in write at record: %d\n",my_errno,i); + goto err; + } + key1[n1]++; + key_check+=n1; + write_count++; + } + if (hash_check(&hash)) + { + puts("Heap keys crashed"); + goto err; + } + printf("- Delete\n"); + for (i=0 ; i < write_count/10 ; i++) + { + for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ; + if (j != 0) + { + sprintf(key,"%6d",j); + if (!(recpos=hash_search(&hash,key,0))) + { + printf("can't find key1: \"%s\"\n",key); + goto err; + } + key1[atoi(recpos)]--; + key_check-=atoi(recpos); + memcpy(oldrecord,recpos,reclength); + if (hash_delete(&hash,recpos)) + { + printf("error: %d; can't delete record: \"%s\"\n", my_errno,oldrecord); + goto err; + } + delete++; + if (testflag == 2 && hash_check(&hash)) + { + puts("Heap keys crashed"); + goto err; + } + } + } + if (hash_check(&hash)) + { + puts("Hash keys crashed"); + goto err; + } + + printf("- Update\n"); + for (i=0 ; i < write_count/10 ; i++) + { + n1=rnd(1000); n2=rnd(100); n3=rnd(min(recant*2,MAX_RECORDS)); + for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ; + if (j) + { + sprintf(key,"%6d",j); + if (!(recpos=hash_search(&hash,key,0))) + { + printf("can't find key1: \"%s\"\n",key); + goto err; + } + key1[atoi(recpos)]--; + key_check=key_check-atoi(recpos)+n1; + key1[n1]++; + sprintf(recpos,"%6d:%4d:%8d:XXX: %4d ",n1,n2,n3,update); + update++; + if (hash_update(&hash,recpos,key,0)) + { + printf("can't update key1: \"%s\"\n",key); + goto err; + } + if (testflag == 3 && hash_check(&hash)) + { + printf("Heap keys crashed for %d update\n",update); + goto err; + } + } + } + if (hash_check(&hash)) + { + puts("Heap keys crashed"); + goto err; + } + + for (j=0 ; j < 1000 ; j++) + if (key1[j] > 1) + break; + if (key1[j] > 1) + { + printf("- Testing identical read\n"); + sprintf(key,"%6d",j); + pos=1; + if (!(recpos=hash_search(&hash,key,0))) + { + printf("can't find key1: \"%s\"\n",key); + goto err; + } + while (hash_next(&hash,key,0) && pos < (ulong) (key1[j]+10)) + pos++; + if (pos != (ulong) key1[j]) + { + printf("Found %ld copies of key: %s. Should be %d",pos,key,key1[j]); + goto err; + } + } + printf("- Creating output heap-file 2\n"); + if (hash_init(&hash2,hash.records,0,0,hash2_key,free_record,0)) + goto err; + + printf("- Copying and removing records\n"); + pos=0; + while ((recpos=hash_element(&hash,0))) + { + record=(byte*) my_malloc(reclength,MYF(MY_FAE)); + memcpy(record,recpos,reclength); + record[reclength-1]=rnd(5)+1; + if (hash_insert(&hash2,record)) + { + printf("Got error when inserting record: %*s",reclength,record); + goto err; + } + key_check-=atoi(record); + write_count++; + if (hash_delete(&hash,recpos)) + { + printf("Got error when deleting record: %*s",reclength,recpos); + goto err; + } + if (testflag==4) + { + if (hash_check(&hash) || hash_check(&hash2)) + { + puts("Hash keys crashed"); + goto err; + } + } + pos++; + } + if (hash_check(&hash) || hash_check(&hash2)) + { + puts("Hash keys crashed"); + goto err; + } + if (key_check != 0) + { + printf("Key check didn't get to 0 (%ld)\n",key_check); + } + + printf("\nFollowing test have been made:\n"); + printf("Write records: %d\nUpdate records: %d\nDelete records: %d\n", write_count, + update,delete); + hash_free(&hash); hash_free(&hash2); + my_end(MY_GIVE_INFO); + DBUG_RETURN(0); +err: + printf("Got error: %d when using hashing\n",my_errno); + DBUG_RETURN(-1); +} /* main */ + + + /* l{ser optioner */ + /* OBS! intierar endast DEBUG - ingen debuggning h{r ! */ + +static int get_options(int argc, char **argv) +{ + char *pos,*progname; + DEBUGGER_OFF; + + progname= argv[0]; + + while (--argc >0 && *(pos = *(++argv)) == '-' ) { + switch(*++pos) { + case 'm': /* records */ + recant=atoi(++pos); + break; + case 't': + testflag=atoi(++pos); /* testmod */ + break; + case 'V': + case 'I': + case '?': + printf("%s Ver 1.0 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE); + puts("TCX Datakonsult AB, by Monty, for your professional use\n"); + printf("Usage: %s [-?ABIKLWv] [-m#] [-t#]\n",progname); + exit(0); + case '#': + DEBUGGER_ON; + DBUG_PUSH (++pos); + break; + } + } + return 0; +} /* get options */ + + /* Ge ett randomv{rde inom ett intervall 0 <=x <= n */ + +static int rnd(int max_value) +{ + return (int) ((rand() & 32767)/32767.0*max_value); +} /* rnd */ + + +void free_record(void *record) +{ + my_free(record,MYF(0)); +} diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c new file mode 100644 index 00000000000..a681c1b110d --- /dev/null +++ b/mysys/thr_alarm.c @@ -0,0 +1,874 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include <global.h> +#include <errno.h> +#include <my_pthread.h> +#include <signal.h> +#include <my_sys.h> +#include <m_string.h> +#include <queues.h> +#include "thr_alarm.h" + +#ifdef THREAD + +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> /* AIX needs this for fd_set */ +#endif + +#ifndef ETIME +#define ETIME ETIMEDOUT +#endif + +static my_bool alarm_aborted=1; +my_bool thr_alarm_inited=0; + +#if !defined(__WIN__) && !defined(__OS2__) +#ifndef DONT_USE_THR_ALARM /* thr_alarm disabled */ + +static pthread_mutex_t LOCK_alarm; +static sigset_t full_signal_set; +static QUEUE alarm_queue; +pthread_t alarm_thread; + +#ifdef USE_ALARM_THREAD +static pthread_cond_t COND_alarm; +static void *alarm_handler(void *arg); +#define reschedule_alarms() pthread_cond_signal(&COND_alarm) +#else +#define reschedule_alarms() pthread_kill(alarm_thread,THR_SERVER_ALARM) +#endif + +#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD) +static sig_handler thread_alarm(int sig __attribute__((unused))); +#endif + +static int compare_ulong(void *not_used __attribute__((unused)), + byte *a_ptr,byte* b_ptr) +{ + ulong a=*((ulong*) a_ptr),b= *((ulong*) b_ptr); + return (a < b) ? -1 : (a == b) ? 0 : 1; +} + +void init_thr_alarm(uint max_alarms) +{ + sigset_t s; + DBUG_ENTER("init_thr_alarm"); + alarm_aborted=0; + init_queue(&alarm_queue,max_alarms+1,offsetof(ALARM,expire_time),0, + compare_ulong,NullS); + sigfillset(&full_signal_set); /* Neaded to block signals */ + pthread_mutex_init(&LOCK_alarm,NULL); +#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD) +#if defined(HAVE_mit_thread) + sigset(THR_CLIENT_ALARM,thread_alarm); /* int. thread system calls */ +#else + { + struct sigaction sact; + sact.sa_flags = 0; + sact.sa_handler = thread_alarm; + sigaction(THR_CLIENT_ALARM, &sact, (struct sigaction*) 0); + } +#endif +#endif + sigemptyset(&s); + sigaddset(&s, THR_SERVER_ALARM); + alarm_thread=pthread_self(); +#if defined(USE_ALARM_THREAD) + { + pthread_attr_t thr_attr; + pthread_attr_init(&thr_attr); + pthread_cond_init(&COND_alarm,NULL); + pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); + pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); + pthread_attr_setstacksize(&thr_attr,8196); + + my_pthread_attr_setprio(&thr_attr,100); /* Very high priority */ + VOID(pthread_create(&alarm_thread,&thr_attr,alarm_handler,NULL)); + VOID(pthread_attr_destroy(&thr_attr)); + } +#elif defined(USE_ONE_SIGNAL_HAND) + pthread_sigmask(SIG_BLOCK, &s, NULL); /* used with sigwait() */ +#if THR_SERVER_ALARM == THR_CLIENT_ALARM + sigset(THR_CLIENT_ALARM,process_alarm); /* Linuxthreads */ + pthread_sigmask(SIG_UNBLOCK, &s, NULL); +#endif +#else + pthread_sigmask(SIG_UNBLOCK, &s, NULL); + sigset(THR_SERVER_ALARM,process_alarm); +#endif + DBUG_VOID_RETURN; +} + +/* +** Request alarm after sec seconds. +** A pointer is returned with points to a non-zero int when the alarm has been +** given. This can't be called from the alarm-handling thread. +** Returns 0 if no more alarms are allowed (aborted by process) +*/ + +bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) +{ + ulong now; + sigset_t old_mask; + my_bool reschedule; + DBUG_ENTER("thr_alarm"); + DBUG_PRINT("enter",("thread: %s sec: %d",my_thread_name(),sec)); + + now=(ulong) time((time_t*) 0); + pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); + pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */ + if (alarm_aborted) + { /* No signal thread */ + DBUG_PRINT("info", ("alarm aborted")); + pthread_mutex_unlock(&LOCK_alarm); + pthread_sigmask(SIG_SETMASK,&old_mask,NULL); + DBUG_RETURN(1); + } + if (alarm_queue.elements == alarm_queue.max_elements) + { + DBUG_PRINT("info", ("alarm queue full")); + fprintf(stderr,"Warning: thr_alarm queue is full\n"); + pthread_mutex_unlock(&LOCK_alarm); + pthread_sigmask(SIG_SETMASK,&old_mask,NULL); + DBUG_RETURN(1); + } + reschedule= (!alarm_queue.elements || + (int) (((ALARM*) queue_top(&alarm_queue))->expire_time - now) > + (int) sec); + if (!alarm_data) + { + if (!(alarm_data=(ALARM*) my_malloc(sizeof(ALARM),MYF(MY_WME)))) + { + DBUG_PRINT("info", ("failed my_malloc()")); + pthread_mutex_unlock(&LOCK_alarm); + pthread_sigmask(SIG_SETMASK,&old_mask,NULL); + DBUG_RETURN(1); + } + alarm_data->malloced=1; + } + else + alarm_data->malloced=0; + alarm_data->expire_time=now+sec; + alarm_data->alarmed=0; + alarm_data->thread=pthread_self(); + queue_insert(&alarm_queue,(byte*) alarm_data); + + /* Reschedule alarm if the current one has more than sec left */ + if (reschedule) + { + DBUG_PRINT("info", ("reschedule")); + if (pthread_equal(pthread_self(),alarm_thread)) + alarm(sec); /* purecov: inspected */ + else + reschedule_alarms(); /* Reschedule alarms */ + } + pthread_mutex_unlock(&LOCK_alarm); + pthread_sigmask(SIG_SETMASK,&old_mask,NULL); + (*alrm)= &alarm_data->alarmed; + DBUG_RETURN(0); +} + + +/* +** Remove alarm from list of alarms +*/ + +void thr_end_alarm(thr_alarm_t *alarmed) +{ + ALARM *alarm_data; + sigset_t old_mask; + uint i; + bool found=0; + DBUG_ENTER("thr_end_alarm"); + + pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); + pthread_mutex_lock(&LOCK_alarm); + + alarm_data= (ALARM*) ((byte*) *alarmed - offsetof(ALARM,alarmed)); + for (i=0 ; i < alarm_queue.elements ; i++) + { + if ((ALARM*) queue_element(&alarm_queue,i) == alarm_data) + { + queue_remove(&alarm_queue,i),MYF(0); + if (alarm_data->malloced) + my_free((gptr) alarm_data,MYF(0)); + found=1; + break; + } + } + if (!found) + { +#ifdef MAIN + printf("Warning: Didn't find alarm %lx in queue of %d alarms\n", + (long) *alarmed, alarm_queue.elements); +#endif + DBUG_PRINT("warning",("Didn't find alarm %lx in queue\n",*alarmed)); + } + if (alarm_aborted && !alarm_queue.elements) + delete_queue(&alarm_queue); + pthread_mutex_unlock(&LOCK_alarm); + pthread_sigmask(SIG_SETMASK,&old_mask,NULL); + DBUG_VOID_RETURN; +} + + /* + Come here when some alarm in queue is due. + Mark all alarms with are finnished in list. + Shedule alarms to be sent again after 1-10 sec (many alarms at once) + If alarm_aborted is set then all alarms are given and resent + every second. + */ + +sig_handler process_alarm(int sig __attribute__((unused))) +{ + sigset_t old_mask; + ALARM *alarm_data; + DBUG_ENTER("process_alarm"); + DBUG_PRINT("info",("sig: %d active alarms: %d",sig,alarm_queue.elements)); + +#if THR_SERVER_ALARM == THR_CLIENT_ALARM + if (!pthread_equal(pthread_self(),alarm_thread)) + { +#if defined(MAIN) && !defined(__bsdi__) + printf("thread_alarm\n"); fflush(stdout); +#endif +#ifdef DONT_REMEMBER_SIGNAL + sigset(THR_CLIENT_ALARM,process_alarm); /* int. thread system calls */ +#endif + DBUG_VOID_RETURN; + } +#endif + +#if defined(MAIN) && !defined(__bsdi__) + printf("process_alarm\n"); fflush(stdout); +#endif +#ifndef USE_ALARM_THREAD + pthread_sigmask(SIG_SETMASK,&full_signal_set,&old_mask); + pthread_mutex_lock(&LOCK_alarm); +#endif + if (alarm_queue.elements) + { + if (alarm_aborted) + { + uint i; + for (i=0 ; i < alarm_queue.elements ;) + { + alarm_data=(ALARM*) queue_element(&alarm_queue,i); + alarm_data->alarmed=1; /* Info to thread */ + if (pthread_equal(alarm_data->thread,alarm_thread) || + pthread_kill(alarm_data->thread, THR_CLIENT_ALARM)) + { +#ifdef MAIN + printf("Warning: pthread_kill couldn't find thread!!!\n"); +#endif + queue_remove(&alarm_queue,i); /* No thread. Remove alarm */ + } + else + i++; /* Signal next thread */ + } +#ifndef USE_ALARM_THREAD + if (alarm_queue.elements) + alarm(1); /* Signal soon again */ +#endif + } + else + { + ulong now=(ulong) time((time_t*) 0); + ulong next=now+10-(now%10); + while ((alarm_data=(ALARM*) queue_top(&alarm_queue))->expire_time <= now) + { + alarm_data->alarmed=1; /* Info to thread */ + DBUG_PRINT("info",("sending signal to waiting thread")); + if (pthread_equal(alarm_data->thread,alarm_thread) || + pthread_kill(alarm_data->thread, THR_CLIENT_ALARM)) + { +#ifdef MAIN + printf("Warning: pthread_kill couldn't find thread!!!\n"); +#endif + queue_remove(&alarm_queue,0); /* No thread. Remove alarm */ + if (!alarm_queue.elements) + break; + } + else + { + alarm_data->expire_time=next; + queue_replaced(&alarm_queue); + } + } +#ifndef USE_ALARM_THREAD + if (alarm_queue.elements) + { +#ifdef __bsdi__ + alarm(0); /* Remove old alarm */ +#endif + alarm((uint) (alarm_data->expire_time-now)); + } +#endif + } + } +#ifndef USE_ALARM_THREAD +#if defined(DONT_REMEMBER_SIGNAL) && !defined(USE_ONE_SIGNAL_HAND) + sigset(THR_SERVER_ALARM,process_alarm); +#endif + pthread_mutex_unlock(&LOCK_alarm); + pthread_sigmask(SIG_SETMASK,&old_mask,NULL); +#endif + DBUG_VOID_RETURN; +} + + +/* +** Shedule all alarms now. +** When all alarms are given, Free alarm memory and don't allow more alarms. +*/ + +void end_thr_alarm(void) +{ + DBUG_ENTER("end_thr_alarm"); + pthread_mutex_lock(&LOCK_alarm); + if (!alarm_aborted) + { + DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements)); + alarm_aborted=1; /* mark aborted */ + if (!alarm_queue.elements) + delete_queue(&alarm_queue); + if (pthread_equal(pthread_self(),alarm_thread)) + alarm(1); /* Shut down everything soon */ + else + reschedule_alarms(); + } + pthread_mutex_unlock(&LOCK_alarm); + DBUG_VOID_RETURN; +} + + +/* +** Remove another thread from the alarm +*/ + +void thr_alarm_kill(pthread_t thread_id) +{ + uint i; + pthread_mutex_lock(&LOCK_alarm); + for (i=0 ; i < alarm_queue.elements ; i++) + { + if (pthread_equal(((ALARM*) queue_element(&alarm_queue,i))->thread, + thread_id)) + { + ALARM *tmp=(ALARM*) queue_remove(&alarm_queue,i); + tmp->expire_time=0; + queue_insert(&alarm_queue,(byte*) tmp); + reschedule_alarms(); + break; + } + } + pthread_mutex_unlock(&LOCK_alarm); +} + + +/* +** This is here for thread to get interruptet from read/write/fcntl +** ARGSUSED +*/ + +#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD) +static sig_handler thread_alarm(int sig) +{ +#ifdef MAIN + printf("thread_alarm\n"); fflush(stdout); +#endif +#ifdef DONT_REMEMBER_SIGNAL + sigset(sig,thread_alarm); /* int. thread system calls */ +#endif +} +#endif + + +#ifdef HAVE_TIMESPEC_TS_SEC +#define tv_sec ts_sec +#define tv_nsec ts_nsec +#endif + +/* set up a alarm thread with uses 'sleep' to sleep between alarms */ + +#ifdef USE_ALARM_THREAD +static void *alarm_handler(void *arg __attribute__((unused))) +{ + int error; + struct timespec abstime; +#ifdef MAIN + puts("Starting alarm thread"); +#endif + my_thread_init(); + pthread_mutex_lock(&LOCK_alarm); + for (;;) + { + if (alarm_queue.elements) + { + ulong sleep_time,now=time((time_t*) 0); + if (alarm_aborted) + sleep_time=now+1; + else + sleep_time= ((ALARM*) queue_top(&alarm_queue))->expire_time; + if (sleep_time > now) + { + abstime.tv_sec=sleep_time; + abstime.tv_nsec=0; + if ((error=pthread_cond_timedwait(&COND_alarm,&LOCK_alarm,&abstime)) && + error != ETIME && error != ETIMEDOUT) + { +#ifdef MAIN + printf("Got error: %d from ptread_cond_timedwait (errno: %d)\n", + error,errno); +#endif + } + } + } + else if (alarm_aborted) + break; + else if ((error=pthread_cond_wait(&COND_alarm,&LOCK_alarm))) + { +#ifdef MAIN + printf("Got error: %d from ptread_cond_wait (errno: %d)\n", + error,errno); +#endif + } + process_alarm(0); + } + bzero((char*) &alarm_thread,sizeof(alarm_thread)); /* For easy debugging */ + pthread_mutex_unlock(&LOCK_alarm); + pthread_exit(0); + return 0; /* Impossible */ +} +#endif + + +#ifdef MAIN + +static pthread_cond_t COND_thread_count; +static pthread_mutex_t LOCK_thread_count; +static uint thread_count; + +#ifdef HPUX +typedef int * fd_set_ptr; +#else +typedef fd_set * fd_set_ptr; +#endif + +static void *test_thread(void *arg) +{ + int i,param=*((int*) arg),wait_time,retry; + time_t start_time; + thr_alarm_t got_alarm; + fd_set fd; + FD_ZERO(&fd); + my_thread_init(); + printf("Tread %d (%s) started\n",param,my_thread_name()); fflush(stdout); + for (i=1 ; i <= 10 ; i++) + { + wait_time=param ? 11-i : i; + start_time=time((time_t*) 0); + if (thr_alarm(&got_alarm,wait_time,0)) + { + printf("Thread: %s Alarms aborted\n",my_thread_name()); + break; + } + if (wait_time == 3) + { + printf("Thread: %s Simulation of no alarm needed\n",my_thread_name()); + fflush(stdout); + } + else + { + for (retry=0 ; !thr_got_alarm(got_alarm) && retry < 10 ; retry++) + { + printf("Thread: %s Waiting %d sec\n",my_thread_name(),wait_time); + select(0,(fd_set_ptr) &fd,0,0,0); + } + if (!thr_got_alarm(got_alarm)) + { + printf("Thread: %s didn't get an alarm. Aborting!\n", + my_thread_name()); + break; + } + if (wait_time == 7) + { /* Simulate alarm-miss */ + fd_set readFDs; + uint max_connection=fileno(stdin); + FD_ZERO(&readFDs); + FD_SET(max_connection,&readFDs); + retry=0; + for (;;) + { + printf("Thread: %s Simulating alarm miss\n",my_thread_name()); + fflush(stdout); + if (select(max_connection+1, (fd_set_ptr) &readFDs,0,0,0) < 0) + { + if (errno == EINTR) + break; /* Got new interrupt */ + printf("Got errno: %d from select. Retrying..\n",errno); + if (retry++ >= 3) + { + printf("Warning: Interrupt of select() doesn't set errno!\n"); + break; + } + } + else /* This shouldn't happen */ + { + if (!FD_ISSET(max_connection,&readFDs)) + { + printf("Select interrupted, but errno not set\n"); + fflush(stdout); + if (retry++ >= 3) + break; + continue; + } + VOID(getchar()); /* Somebody was playing */ + } + } + } + } + printf("Thread: %s Slept for %d (%d) sec\n",my_thread_name(), + (int) (time((time_t*) 0)-start_time), wait_time); fflush(stdout); + thr_end_alarm(&got_alarm); + fflush(stdout); + } + pthread_mutex_lock(&LOCK_thread_count); + thread_count--; + VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */ + pthread_mutex_unlock(&LOCK_thread_count); + free((gptr) arg); + return 0; +} + +#ifdef USE_ONE_SIGNAL_HAND +static sig_handler print_signal_warning(int sig) +{ + printf("Warning: Got signal %d from thread %s\n",sig,my_thread_name()); + fflush(stdout); +#ifdef DONT_REMEMBER_SIGNAL + sigset(sig,print_signal_warning); /* int. thread system calls */ +#endif + if (sig == SIGALRM) + alarm(2); /* reschedule alarm */ +} +#endif + + + +static void *signal_hand(void *arg __attribute__((unused))) +{ + sigset_t set; + int sig,error,err_count=0;; + + my_thread_init(); + pthread_detach_this_thread(); + init_thr_alarm(10); /* Setup alarm handler */ + pthread_mutex_lock(&LOCK_thread_count); /* Required by bsdi */ + VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */ + pthread_mutex_unlock(&LOCK_thread_count); + + sigemptyset(&set); /* Catch all signals */ + sigaddset(&set,SIGINT); + sigaddset(&set,SIGQUIT); + sigaddset(&set,SIGTERM); +#if THR_CLIENT_ALARM != SIGHUP + sigaddset(&set,SIGHUP); +#endif +#ifdef SIGTSTP + sigaddset(&set,SIGTSTP); +#endif +#ifdef USE_ONE_SIGNAL_HAND + sigaddset(&set,THR_SERVER_ALARM); /* For alarms */ + puts("Starting signal and alarm handling thread"); +#else + puts("Starting signal handling thread"); +#endif + printf("server alarm: %d thread alarm: %d\n", + THR_SERVER_ALARM,THR_CLIENT_ALARM); + DBUG_PRINT("info",("Starting signal and alarm handling thread")); + for(;;) + { + while ((error=my_sigwait(&set,&sig)) == EINTR) + printf("sigwait restarted\n"); + if (error) + { + fprintf(stderr,"Got error %d from sigwait\n",error); + if (err_count++ > 5) + exit(1); /* Too many errors in test */ + continue; + } +#ifdef USE_ONE_SIGNAL_HAND + if (sig != THR_SERVER_ALARM) +#endif + printf("Main thread: Got signal %d\n",sig); + switch (sig) { + case SIGINT: + case SIGQUIT: + case SIGTERM: + case SIGHUP: + printf("Aborting nicely\n"); + end_thr_alarm(); + break; +#ifdef SIGTSTP + case SIGTSTP: + printf("Aborting\n"); + exit(1); + return 0; /* Keep some compilers happy */ +#endif +#ifdef USE_ONE_SIGNAL_HAND + case THR_SERVER_ALARM: + process_alarm(sig); + break; +#endif + } + } +} + + +int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) +{ + pthread_t tid; + pthread_attr_t thr_attr; + int i,*param,error; + sigset_t set; + MY_INIT(argv[0]); + + if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#') + DBUG_PUSH(argv[1]+2); + + pthread_mutex_init(&LOCK_thread_count,NULL); + pthread_cond_init(&COND_thread_count,NULL); + + /* Start a alarm handling thread */ + sigemptyset(&set); + sigaddset(&set,SIGINT); + sigaddset(&set,SIGQUIT); + sigaddset(&set,SIGTERM); + sigaddset(&set,SIGHUP); + signal(SIGTERM,SIG_DFL); /* If it's blocked by parent */ +#ifdef SIGTSTP + sigaddset(&set,SIGTSTP); +#endif + sigaddset(&set,THR_SERVER_ALARM); + sigdelset(&set,THR_CLIENT_ALARM); + (void) pthread_sigmask(SIG_SETMASK,&set,NULL); +#ifdef NOT_USED + sigemptyset(&set); + sigaddset(&set,THR_CLIENT_ALARM); + VOID(pthread_sigmask(SIG_UNBLOCK, &set, (sigset_t*) 0)); +#endif + + pthread_attr_init(&thr_attr); + pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); + pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); + pthread_attr_setstacksize(&thr_attr,65536L); + + /* Start signal thread and wait for it to start */ + VOID(pthread_mutex_lock(&LOCK_thread_count)); + pthread_create(&tid,&thr_attr,signal_hand,NULL); + VOID(pthread_cond_wait(&COND_thread_count,&LOCK_thread_count)); + VOID(pthread_mutex_unlock(&LOCK_thread_count)); + DBUG_PRINT("info",("signal thread created")); + + thr_setconcurrency(3); + pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); + printf("Main thread: %s\n",my_thread_name()); + for (i=0 ; i < 2 ; i++) + { + param=(int*) malloc(sizeof(int)); + *param= i; + pthread_mutex_lock(&LOCK_thread_count); + if ((error=pthread_create(&tid,&thr_attr,test_thread,(void*) param))) + { + printf("Can't create thread %d, error: %d\n",i,error); + exit(1); + } + thread_count++; + pthread_mutex_unlock(&LOCK_thread_count); + } + + pthread_attr_destroy(&thr_attr); + pthread_mutex_lock(&LOCK_thread_count); + while (thread_count) + { + VOID(pthread_cond_wait(&COND_thread_count,&LOCK_thread_count)); + if (thread_count == 1) + { + printf("Calling end_thr_alarm. This should cancel the last thread\n"); + end_thr_alarm(); + } + } + pthread_mutex_unlock(&LOCK_thread_count); + printf("Test succeeded\n"); + return 0; +} +#endif /* MAIN */ + +#else /* DONT_USE_THR_ALARM */ + +#ifdef MAIN +int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) +{ + printf("thr_alarm disabled with DONT_USE_THR_ALARM\n"); + exit(1); +} +#endif +#endif + +/***************************************************************************** +** thr_alarm for OS/2 +*****************************************************************************/ + +#elif defined(__OS2__) + +#define INCL_BASE +#define INCL_NOPMAPI +#include <os2.h> + +bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm) +{ + APIRET rc; + if (alarm_aborted) + { + alrm->crono=0; + alrm->event=0; + return 1; + } + if (!(rc = DosCreateEventSem(NULL,(HEV *)&alrm->event,DC_SEM_SHARED,FALSE))) + { + printf("Error creating event semaphore! [%d] \n",rc); + alrm->crono=0; + alrm->event=0; + return 1; + } + if (!(rc = DosAsyncTimer((long) sec*1000L, (HSEM) alrm->event,(HTIMER *) &alrm->crono))) { + printf("Error starting async timer! [%d] \n",rc); + DosCloseEventSem((HEV) alrm->event); + alrm->crono=0; + alrm->event=0; + return 1; + } /* endif */ + + return 1; +} + + +bool thr_got_alarm(thr_alarm_t *alrm) +{ + APIRET rc; + + if (alrm->crono) + { + rc = DosWaitEventSem((HEV) alrm->event, SEM_IMMEDIATE_RETURN); + if (rc == 0) { + DosCloseEventSem((HEV) alrm->event); + alrm->crono = 0; + alrm->event = 0; + } /* endif */ + } + return !alrm->crono || alarm_aborted; +} + + +void thr_end_alarm(thr_alarm_t *alrm) +{ + if (alrm->crono) + { + DosStopTimer((HTIMER) alrm->crono); + DosCloseEventSem((HEV) alrm->event); + alrm->crono = 0; + alrm->event = 0; + } +} + +void end_thr_alarm(void) +{ + DBUG_ENTER("end_thr_alarm"); + alarm_aborted=1; /* No more alarms */ + DBUG_VOID_RETURN; +} + +void init_thr_alarm(uint max_alarm) +{ + DBUG_ENTER("init_thr_alarm"); + alarm_aborted=0; /* Yes, Gimmie alarms */ + DBUG_VOID_RETURN; +} + +#ifdef MAIN +void main() +{ + printf("hello world\n"); +} +#endif + +/***************************************************************************** +** thr_alarm for win95 +*****************************************************************************/ + +#else /* __WIN__ */ + +bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm) +{ + if (alarm_aborted) + { + alrm->crono=0; + return 1; + } + if (!(alrm->crono=SetTimer(NULL,0,(long) sec*1000L, (TIMERPROC) NULL))) + return 1; + return 0; +} + + +bool thr_got_alarm(thr_alarm_t *alrm) +{ + MSG msg; + if (alrm->crono) + { + PeekMessage(&msg,NULL,WM_TIMER,WM_TIMER,PM_REMOVE) ; + if (msg.message == WM_TIMER || alarm_aborted) + { + KillTimer(NULL, alrm->crono); + alrm->crono = 0; + } + } + return !alrm->crono || alarm_aborted; +} + + +void thr_end_alarm(thr_alarm_t *alrm) +{ + if (alrm->crono) + { + KillTimer(NULL, alrm->crono); + alrm->crono = 0; + } +} + +void end_thr_alarm(void) +{ + DBUG_ENTER("end_thr_alarm"); + alarm_aborted=1; /* No more alarms */ + DBUG_VOID_RETURN; +} + +#endif /* __WIN__ */ + +#endif diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c new file mode 100644 index 00000000000..5c0803c6402 --- /dev/null +++ b/mysys/thr_lock.c @@ -0,0 +1,1288 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* +Read and write locks for Posix threads. All tread must acquire +all locks it needs through thr_multi_lock() to avoid dead-locks. +A lock consists of a master lock (THR_LOCK), and lock instances +(THR_LOCK_DATA). +Any thread can have any number of lock instances (read and write:s) on +any lock. All lock instances must be freed. +Locks are prioritized according to: + +The current lock types are: + +TL_READ # Low priority read +TL_READ_HIGH_PRIORITY # High priority read +TL_READ_NO_INSERT # Read without concurrent inserts +TL_WRITE_ALLOW_WRITE # Write lock that allows other writers +TL_WRITE_ALLOW_READ # Write lock, but allow reading +TL_WRITE_CONCURRENT_INSERT + # Insert that can be mixed when selects +TL_WRITE_DELAYED # Used by delayed insert + # Allows lower locks to take over +TL_WRITE_LOW_PRIORITY # Low priority write +TL_WRITE # High priority write +TL_WRITE_ONLY # High priority write + # Abort all new lock request with an error + +Locks are prioritized according to: + +WRITE_ALLOW_WRITE, WRITE_ALLOW_READ, WRITE_CONCURRENT_INSERT, WRITE_DELAYED, +WRITE_LOW_PRIORITY, READ, WRITE, READ_HIGH_PRIORITY and WRITE_ONLY + +Locks in the same privilege level are scheduled in first-in-first-out order. + +To allow concurrent read/writes locks, with 'WRITE_CONCURRENT_INSERT' one +should put a pointer to the following functions in the lock structure: +(If the pointer is zero (default), the function is not called) + +check_status: + Before giving a lock of type TL_WRITE_CONCURRENT_INSERT, + we check if this function exists and returns 0. + If not, then the lock is upgraded to TL_WRITE_LOCK + In MyISAM this is a simple check if the insert can be done + at the end of the datafile. +update_status: + Before a write lock is released, this function is called. + In MyISAM this functions updates the count and length of the datafile +get_status: + When one gets a lock this functions is called. + In MyISAM this stores the number of rows and size of the datafile + for concurrent reads. + +The lock algorithm allows one to have one TL_WRITE_ALLOW_READ, +TL_WRITE_CONCURRENT_INSERT or one TL_WRITE_DELAYED lock at the same time as +multiple read locks. + +*/ + +#if !defined(MAIN) && !defined(DBUG_OFF) && !defined(EXTRA_DEBUG) +#define DBUG_OFF +#endif + +#include "mysys_priv.h" +#include "thr_lock.h" +#include <m_string.h> +#include <errno.h> + +my_bool thr_lock_inited=0; + +#ifdef THREAD + +/* The following constants are only for debug output */ +#define MAX_THREADS 100 +#define MAX_LOCKS 100 + + +static LIST *thread_list; /* List of threads in use */ +ulong max_write_lock_count= ~(ulong) 0L; + +static inline pthread_cond_t *get_cond(void) +{ + return &my_thread_var->suspend; +} + +/* +** For the future (now the thread specific cond is alloced by my_pthread.c) +*/ + +my_bool init_thr_lock() +{ + thr_lock_inited=1; + return 0; +} + +#ifdef EXTRA_DEBUG +static int found_errors=0; + +static int check_lock(struct st_lock_list *list, const char* lock_type, + const char *where, my_bool same_thread) +{ + THR_LOCK_DATA *data,**prev; + uint count=0; + pthread_t first_thread; + LINT_INIT(first_thread); + + prev= &list->data; + if (list->data) + { + enum thr_lock_type last_lock_type=list->data->type; + + if (same_thread && list->data) + first_thread=list->data->thread; + for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next) + { + if (data->type != last_lock_type) + last_lock_type=TL_IGNORE; + if (data->prev != prev) + { + fprintf(stderr, + "Warning: prev link %d didn't point at previous lock at %s: %s\n", + count, lock_type, where); + return 1; + } + if (same_thread && ! pthread_equal(data->thread,first_thread) && + last_lock_type != TL_WRITE_ALLOW_WRITE) + { + fprintf(stderr, + "Warning: Found locks from different threads in %s: %s\n", + lock_type,where); + return 1; + } + prev= &data->next; + } + if (data) + { + fprintf(stderr,"Warning: found too many locks at %s: %s\n", + lock_type,where); + return 1; + } + } + if (prev != list->last) + { + fprintf(stderr,"Warning: last didn't point at last lock at %s: %s\n", + lock_type, where); + return 1; + } + return 0; +} + +static void check_locks(THR_LOCK *lock, const char *where, + my_bool allow_no_locks) +{ + if (!found_errors) + { + if (check_lock(&lock->write,"write",where,1) | + check_lock(&lock->write_wait,"write_wait",where,0) | + check_lock(&lock->read,"read",where,0) | + check_lock(&lock->read_wait,"read_wait",where,0)) + found_errors=1; + + if (!found_errors) + { + uint count=0; + THR_LOCK_DATA *data; + for (data=lock->read.data ; data ; data=data->next) + { + if ((int) data->type == (int) TL_READ_NO_INSERT) + count++; + } + if (count != lock->read_no_write_count) + { + found_errors=1; + fprintf(stderr, + "Warning at '%s': Locks read_no_write_count was %u when it should have been %u\n", where, lock->read_no_write_count,count); + } + + if (!lock->write.data) + { + if (!allow_no_locks && !lock->read.data && + (lock->write_wait.data || lock->read_wait.data)) + { + found_errors=1; + fprintf(stderr, + "Warning at '%s': No locks in use but locks are in wait queue\n", + where); + } + if (!lock->write_wait.data) + { + if (!allow_no_locks && lock->read_wait.data) + { + found_errors=1; + fprintf(stderr, + "Warning at '%s': No write locks and waiting read locks\n", + where); + } + } + else + { + if (!allow_no_locks && + (((lock->write_wait.data->type == TL_WRITE_CONCURRENT_INSERT || + lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE) && + !lock->read_no_write_count) || + lock->write_wait.data->type == TL_WRITE_ALLOW_READ || + (lock->write_wait.data->type == TL_WRITE_DELAYED && + !lock->read.data))) + { + found_errors=1; + fprintf(stderr, + "Warning at '%s': Write lock %d waiting while no exclusive read locks\n",where,(int) lock->write_wait.data->type); + } + } + } + else + { /* Have write lock */ + if (lock->write_wait.data) + { + if (!allow_no_locks && + lock->write.data->type == TL_WRITE_ALLOW_WRITE && + lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE) + { + found_errors=1; + fprintf(stderr, + "Warning at '%s': Found WRITE_ALLOW_WRITE lock waiting for WRITE_ALLOW_WRITE lock\n", + where); + } + } + if (lock->read.data) + { + if ((!pthread_equal(lock->write.data->thread,lock->read.data->thread) && + lock->write.data->type > TL_WRITE_DELAYED) || + ((lock->write.data->type == TL_WRITE_CONCURRENT_INSERT || + lock->write.data->type == TL_WRITE_ALLOW_WRITE) && + lock->read_no_write_count)) + { + found_errors=1; + fprintf(stderr, + "Warning at '%s': Found lock that is write and read locked\n", + where); + } + } + if (lock->read_wait.data) + { + if (!allow_no_locks && lock->write.data->type <= TL_WRITE_DELAYED && + lock->read_wait.data->type <= TL_READ_HIGH_PRIORITY) + { + found_errors=1; + fprintf(stderr, + "Warning at '%s': Found read lock of type %d waiting for write lock of type %d\n", + where, + (int) lock->read_wait.data->type, + (int) lock->write.data->type); + } + } + } + } + if (found_errors) + { + DBUG_PRINT("error",("Found wrong lock")); + } + } +} + +#else /* EXTRA_DEBUG */ +#define check_locks(A,B,C) +#endif + + + /* Initialize a lock */ + +void thr_lock_init(THR_LOCK *lock) +{ + DBUG_ENTER("thr_lock_init"); + bzero((char*) lock,sizeof(*lock)); + VOID(pthread_mutex_init(&lock->mutex,NULL)); + lock->read.last= &lock->read.data; + lock->read_wait.last= &lock->read_wait.data; + lock->write_wait.last= &lock->write_wait.data; + lock->write.last= &lock->write.data; + + pthread_mutex_lock(&THR_LOCK_lock); /* Add to locks in use */ + lock->list.data=(void*) lock; + thread_list=list_add(thread_list,&lock->list); + pthread_mutex_unlock(&THR_LOCK_lock); + DBUG_VOID_RETURN; +} + + +void thr_lock_delete(THR_LOCK *lock) +{ + DBUG_ENTER("thr_lock_delete"); + VOID(pthread_mutex_destroy(&lock->mutex)); + pthread_mutex_lock(&THR_LOCK_lock); + thread_list=list_delete(thread_list,&lock->list); + pthread_mutex_unlock(&THR_LOCK_lock); + DBUG_VOID_RETURN; +} + + /* Initialize a lock instance */ + +void thr_lock_data_init(THR_LOCK *lock,THR_LOCK_DATA *data, void *param) +{ + data->lock=lock; + data->type=TL_UNLOCK; + data->thread=pthread_self(); + data->thread_id=my_thread_id(); /* for debugging */ + data->status_param=param; +} + + +static inline my_bool have_old_read_lock(THR_LOCK_DATA *data,pthread_t thread) +{ + for ( ; data ; data=data->next) + { + if ((pthread_equal(data->thread,thread))) + return 1; /* Already locked by thread */ + } + return 0; +} + +static inline my_bool have_specific_lock(THR_LOCK_DATA *data, + enum thr_lock_type type) +{ + for ( ; data ; data=data->next) + { + if (data->type == type) + return 1; + } + return 0; +} + + +static my_bool wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, + my_bool in_wait_list) +{ + pthread_cond_t *cond=get_cond(); + struct st_my_thread_var *thread_var=my_thread_var; + int result; + + if (!in_wait_list) + { + (*wait->last)=data; /* Wait for lock */ + data->prev= wait->last; + wait->last= &data->next; + } + + /* Set up control struct to allow others to abort locks */ + pthread_mutex_lock(&thread_var->mutex); + thread_var->current_mutex= &data->lock->mutex; + thread_var->current_cond= cond; + pthread_mutex_unlock(&thread_var->mutex); + + data->cond=cond; + do + { + pthread_cond_wait(cond,&data->lock->mutex); + } while (data->cond == cond && !thread_var->abort); + + if (data->cond || data->type == TL_UNLOCK) + { + if (data->cond) /* aborted */ + { + if (((*data->prev)=data->next)) /* remove from wait-list */ + data->next->prev= data->prev; + else + wait->last=data->prev; + } + data->type=TL_UNLOCK; /* No lock */ + result=1; /* Didn't get lock */ + check_locks(data->lock,"failed wait_for_lock",0); + } + else + { + result=0; + if (data->lock->get_status) + (*data->lock->get_status)(data->status_param); + check_locks(data->lock,"got wait_for_lock",0); + } + pthread_mutex_unlock(&data->lock->mutex); + + /* The following must be done after unlock of lock->mutex */ + pthread_mutex_lock(&thread_var->mutex); + thread_var->current_mutex= 0; + thread_var->current_cond= 0; + pthread_mutex_unlock(&thread_var->mutex); + return result; +} + + +int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type) +{ + THR_LOCK *lock=data->lock; + int result=0; + DBUG_ENTER("thr_lock"); + + data->next=0; + data->type=lock_type; + data->thread=pthread_self(); /* Must be reset ! */ + data->thread_id=my_thread_id(); /* Must be reset ! */ + VOID(pthread_mutex_lock(&lock->mutex)); + DBUG_PRINT("lock",("data: %lx thread: %ld lock: %lx type: %d", + data,data->thread_id,lock,(int) lock_type)); + check_locks(lock,(uint) lock_type <= (uint) TL_READ_NO_INSERT ? + "enter read_lock" : "enter write_lock",0); + if ((int) lock_type <= (int) TL_READ_NO_INSERT) + { + /* Request for READ lock */ + if (lock->write.data) + { + /* We can get allow a read lock even if there is already a write lock + one the table in one the following cases: + - This thread alread have a write lock on the table + - The write lock is TL_WRITE_ALLOW_READ or TL_WRITE_DELAYED + and the read lock is TL_READ_HIGH_PRIORITY or TL_READ + - The write lock is TL_WRITE_CONCURRENT_INSERT or TL_WRITE_ALLOW_WRITE + and the read lock is not TL_READ_NO_INSERT + */ + + DBUG_PRINT("lock",("write locked by thread: %ld", + lock->write.data->thread_id)); + if (pthread_equal(data->thread,lock->write.data->thread) || + (lock->write.data->type <= TL_WRITE_DELAYED && + (((int) lock_type <= (int) TL_READ_HIGH_PRIORITY) || + (lock->write.data->type != TL_WRITE_CONCURRENT_INSERT && + lock->write.data->type != TL_WRITE_ALLOW_READ)))) + { /* Already got a write lock */ + (*lock->read.last)=data; /* Add to running FIFO */ + data->prev=lock->read.last; + lock->read.last= &data->next; + if ((int) lock_type == (int) TL_READ_NO_INSERT) + lock->read_no_write_count++; + check_locks(lock,"read lock with old write lock",0); + if (lock->get_status) + (*lock->get_status)(data->status_param); + goto end; + } + if (lock->write.data->type == TL_WRITE_ONLY) + { + /* We are not allowed to get a READ lock in this case */ + data->type=TL_UNLOCK; + result=1; /* Can't wait for this one */ + goto end; + } + } + else if (!lock->write_wait.data || + lock->write_wait.data->type <= TL_WRITE_LOW_PRIORITY || + lock_type == TL_READ_HIGH_PRIORITY || + have_old_read_lock(lock->read.data,data->thread)) + { /* No important write-locks */ + (*lock->read.last)=data; /* Add to running FIFO */ + data->prev=lock->read.last; + lock->read.last= &data->next; + if (lock->get_status) + (*lock->get_status)(data->status_param); + if ((int) lock_type == (int) TL_READ_NO_INSERT) + lock->read_no_write_count++; + check_locks(lock,"read lock with no write locks",0); + goto end; + } + /* Can't get lock yet; Wait for it */ + DBUG_RETURN(wait_for_lock(&lock->read_wait,data,0)); + } + else /* Request for WRITE lock */ + { + if (lock_type == TL_WRITE_DELAYED) + { + if (lock->write.data && lock->write.data->type == TL_WRITE_ONLY) + { + data->type=TL_UNLOCK; + result=1; /* Can't wait for this one */ + goto end; + } + /* + if there is a TL_WRITE_ALLOW_READ lock, we have to wait for a lock + (TL_WRITE_ALLOW_READ is used for ALTER TABLE in MySQL) + */ + if ((!lock->write.data || + lock->write.data->type != TL_WRITE_ALLOW_READ) && + !have_specific_lock(lock->write_wait.data,TL_WRITE_ALLOW_READ) && + (lock->write.data || lock->read.data)) + { + /* Add delayed write lock to write_wait queue, and return at once */ + (*lock->write_wait.last)=data; + data->prev=lock->write_wait.last; + lock->write_wait.last= &data->next; + data->cond=get_cond(); + if (lock->get_status) + (*lock->get_status)(data->status_param); + goto end; + } + } + else if (lock_type == TL_WRITE_CONCURRENT_INSERT && ! lock->check_status) + data->type=lock_type= TL_WRITE; /* not supported */ + + if (lock->write.data) /* If there is a write lock */ + { + if (lock->write.data->type == TL_WRITE_ONLY) + { + /* We are not allowed to get a lock in this case */ + data->type=TL_UNLOCK; + result=1; /* Can't wait for this one */ + goto end; + } + + /* + The following test will not work if the old lock was a + TL_WRITE_ALLOW_WRITE, TL_WRITE_ALLOW_READ or TL_WRITE_DELAYED in + the same thread, but this will never happen within MySQL. + */ + if (pthread_equal(data->thread,lock->write.data->thread) || + (lock_type == TL_WRITE_ALLOW_WRITE && + !lock->write_wait.data && + lock->write.data->type == TL_WRITE_ALLOW_WRITE)) + { + /* We have already got a write lock or all locks are + TL_WRITE_ALLOW_WRITE */ + (*lock->write.last)=data; /* Add to running fifo */ + data->prev=lock->write.last; + lock->write.last= &data->next; + check_locks(lock,"second write lock",0); + if (data->lock->get_status) + (*data->lock->get_status)(data->status_param); + goto end; + } + DBUG_PRINT("lock",("write locked by thread: %ld", + lock->write.data->thread_id)); + } + else + { + if (!lock->write_wait.data) + { /* no scheduled write locks */ + if (lock_type == TL_WRITE_CONCURRENT_INSERT && + (*lock->check_status)(data->status_param)) + data->type=lock_type=TL_WRITE; /* Upgrade lock */ + + if (!lock->read.data || + (lock_type <= TL_WRITE_DELAYED && + ((lock_type != TL_WRITE_CONCURRENT_INSERT && + lock_type != TL_WRITE_ALLOW_WRITE) || + !lock->read_no_write_count))) + { + (*lock->write.last)=data; /* Add as current write lock */ + data->prev=lock->write.last; + lock->write.last= &data->next; + if (data->lock->get_status) + (*data->lock->get_status)(data->status_param); + check_locks(lock,"only write lock",0); + goto end; + } + } + DBUG_PRINT("lock",("write locked by thread: %ld, type: %ld", + lock->read.data->thread_id,data->type)); + } + DBUG_RETURN(wait_for_lock(&lock->write_wait,data,0)); + } +end: + pthread_mutex_unlock(&lock->mutex); + DBUG_RETURN(result); +} + + +static inline void free_all_read_locks(THR_LOCK *lock, + bool using_concurrent_insert) +{ + THR_LOCK_DATA *data=lock->read_wait.data; + + check_locks(lock,"before freeing read locks",1); + + /* move all locks from read_wait list to read list */ + (*lock->read.last)=data; + data->prev=lock->read.last; + lock->read.last=lock->read_wait.last; + + /* Clear read_wait list */ + lock->read_wait.last= &lock->read_wait.data; + + do + { + pthread_cond_t *cond=data->cond; + if ((int) data->type == (int) TL_READ_NO_INSERT) + { + if (using_concurrent_insert) + { + /* + We can't free this lock; + Link lock away from read chain back into read_wait chain + */ + if (((*data->prev)=data->next)) + data->next->prev=data->prev; + else + lock->read.last=data->prev; + *lock->read_wait.last= data; + data->prev= lock->read_wait.last; + lock->read_wait.last= &data->next; + continue; + } + lock->read_no_write_count++; + } + DBUG_PRINT("lock",("giving read lock to thread: %ld", + data->thread_id)); + data->cond=0; /* Mark thread free */ + VOID(pthread_cond_signal(cond)); + } while ((data=data->next)); + *lock->read_wait.last=0; + if (!lock->read_wait.data) + lock->write_lock_count=0; + check_locks(lock,"after giving read locks",0); +} + + /* Unlock lock and free next thread on same lock */ + +void thr_unlock(THR_LOCK_DATA *data) +{ + THR_LOCK *lock=data->lock; + enum thr_lock_type lock_type=data->type; + DBUG_ENTER("thr_unlock"); + DBUG_PRINT("lock",("data: %lx thread: %ld lock: %lx", + data,data->thread_id,lock)); + pthread_mutex_lock(&lock->mutex); + check_locks(lock,"start of release lock",0); + + if (((*data->prev)=data->next)) /* remove from lock-list */ + data->next->prev= data->prev; + else if (lock_type <= TL_READ_NO_INSERT) + lock->read.last=data->prev; + else if (lock_type == TL_WRITE_DELAYED && data->cond) + { + /* This only happens in extreme circumstances when a + write delayed lock that is waiting for a lock */ + lock->write_wait.last=data->prev; /* Put it on wait queue */ + } + else + lock->write.last=data->prev; + if (lock_type >= TL_WRITE_CONCURRENT_INSERT && lock->update_status) + (*lock->update_status)(data->status_param); + if (lock_type == TL_READ_NO_INSERT) + lock->read_no_write_count--; + data->type=TL_UNLOCK; /* Mark unlocked */ + check_locks(lock,"after releasing lock",1); + + if (!lock->write.data) /* If no active read locks */ + { + data=lock->write_wait.data; + if (!lock->read.data) /* If no more locks in use */ + { + /* Release write-locks with TL_WRITE or TL_WRITE_ONLY priority first */ + if (data && + (data->type != TL_WRITE_LOW_PRIORITY || !lock->read_wait.data || + lock->read_wait.data->type == TL_READ)) + { + if (lock->write_lock_count++ > max_write_lock_count) + { + /* Too many write locks in a row; Release all waiting read locks */ + lock->write_lock_count=0; + if (lock->read_wait.data) + { + DBUG_PRINT("info",("Freeing all read_locks because of max_write_lock_count")); + free_all_read_locks(lock,0); + goto end; + } + } + for (;;) + { + if (((*data->prev)=data->next)) /* remove from wait-list */ + data->next->prev= data->prev; + else + lock->write_wait.last=data->prev; + (*lock->write.last)=data; /* Put in execute list */ + data->prev=lock->write.last; + data->next=0; + lock->write.last= &data->next; + if (data->type == TL_WRITE_CONCURRENT_INSERT && + (*lock->check_status)(data->status_param)) + data->type=TL_WRITE; /* Upgrade lock */ + DBUG_PRINT("lock",("giving write lock of type %d to thread: %ld", + data->type,data->thread_id)); + { + pthread_cond_t *cond=data->cond; + data->cond=0; /* Mark thread free */ + VOID(pthread_cond_signal(cond)); /* Start waiting thread */ + } + if (data->type != TL_WRITE_ALLOW_WRITE || + !lock->write_wait.data || + lock->write_wait.data->type != TL_WRITE_ALLOW_WRITE) + break; + data=lock->write_wait.data; /* Free this too */ + } + if (data->type >= TL_WRITE_LOW_PRIORITY) + { + check_locks(lock,"giving write lock",0); + pthread_mutex_unlock(&lock->mutex); + DBUG_VOID_RETURN; + } + /* Release possible read locks together with the write lock */ + } + if (lock->read_wait.data) + free_all_read_locks(lock, + data && + (data->type == TL_WRITE_CONCURRENT_INSERT || + data->type == TL_WRITE_ALLOW_WRITE)); + else + { + DBUG_PRINT("lock",("No locks to free")); + } + } + else if (data && + (lock_type=data->type) <= TL_WRITE_DELAYED && + ((lock_type != TL_WRITE_CONCURRENT_INSERT && + lock_type != TL_WRITE_ALLOW_WRITE) || + !lock->read_no_write_count)) + { + /* + For DELAYED, ALLOW_READ, WRITE_ALLOW_WRITE or CONCURRENT_INSERT locks + start WRITE locks together with the READ locks + */ + if (lock_type == TL_WRITE_CONCURRENT_INSERT && + (*lock->check_status)(data->status_param)) + { + data->type=TL_WRITE; /* Upgrade lock */ + if (lock->read_wait.data) + free_all_read_locks(lock,0); + goto end; + } + do { + pthread_cond_t *cond=data->cond; + if (((*data->prev)=data->next)) /* remove from wait-list */ + data->next->prev= data->prev; + else + lock->write_wait.last=data->prev; + (*lock->write.last)=data; /* Put in execute list */ + data->prev=lock->write.last; + lock->write.last= &data->next; + data->next=0; /* Only one write lock */ + data->cond=0; /* Mark thread free */ + VOID(pthread_cond_signal(cond)); /* Start waiting thread */ + } while (lock_type == TL_WRITE_ALLOW_WRITE && + (data=lock->write_wait.data) && + data->type == TL_WRITE_ALLOW_WRITE); + if (lock->read_wait.data) + free_all_read_locks(lock, + (lock_type == TL_WRITE_CONCURRENT_INSERT || + lock_type == TL_WRITE_ALLOW_WRITE)); + } + else if (lock->read_wait.data) + free_all_read_locks(lock,0); + } +end: + check_locks(lock,"thr_unlock",0); + pthread_mutex_unlock(&lock->mutex); + DBUG_VOID_RETURN; +} + + +/* +** Get all locks in a specific order to avoid dead-locks +** Sort acording to lock position and put write_locks before read_locks if +** lock on same lock. +*/ + + +#define LOCK_CMP(A,B) ((byte*) (A->lock) - (uint) ((A)->type) < (byte*) (B->lock)- (uint) ((B)->type)) + +static void sort_locks(THR_LOCK_DATA **data,uint count) +{ + THR_LOCK_DATA **pos,**end,**prev,*tmp; + + /* Sort locks with insertion sort (fast because almost always few locks) */ + + for (pos=data+1,end=data+count; pos < end ; pos++) + { + tmp= *pos; + if (LOCK_CMP(tmp,pos[-1])) + { + prev=pos; + do { + prev[0]=prev[-1]; + } while (--prev != data && LOCK_CMP(tmp,prev[-1])); + prev[0]=tmp; + } + } +} + + +int thr_multi_lock(THR_LOCK_DATA **data,uint count) +{ + THR_LOCK_DATA **pos,**end; + DBUG_ENTER("thr_multi_lock"); + DBUG_PRINT("lock",("data: %lx count: %d",data,count)); + if (count > 1) + sort_locks(data,count); + /* lock everything */ + for (pos=data,end=data+count; pos < end ; pos++) + { + if (thr_lock(*pos,(*pos)->type)) + { /* Aborted */ + thr_multi_unlock(data,(uint) (pos-data)); + DBUG_RETURN(1); + } +#ifdef MAIN + printf("Thread: %s Got lock: %lx type: %d\n",my_thread_name(), + (long) pos[0]->lock, pos[0]->type); fflush(stdout); +#endif + } + /* + Ensure that all get_locks() have the same status + If we lock the same table multiple times, we must use the same + status_param! + */ +#if !defined(DONT_USE_RW_LOCKS) + if (count > 1) + { + THR_LOCK_DATA *last_lock= end[-1]; + pos=end-1; + do + { + pos--; + if (last_lock->lock == (*pos)->lock && + last_lock->lock->copy_status) + { + if (last_lock->type <= TL_READ_NO_INSERT) + { + THR_LOCK_DATA **read_lock; + /* + If we are locking the same table with read locks we must ensure + that all tables share the status of the last write lock or + the same read lock. + */ + for (; + (*pos)->type <= TL_READ_NO_INSERT && + pos != data && + pos[-1]->lock == (*pos)->lock ; + pos--) ; + + read_lock = pos+1; + do + { + (last_lock->lock->copy_status)((*read_lock)->status_param, + (*pos)->status_param); + } while (*(read_lock++) != last_lock); + last_lock= (*pos); /* Point at last write lock */ + } + else + (*last_lock->lock->copy_status)((*pos)->status_param, + last_lock->status_param); + } + else + last_lock=(*pos); + } while (pos != data); + } +#endif + DBUG_RETURN(0); +} + + /* free all locks */ + +void thr_multi_unlock(THR_LOCK_DATA **data,uint count) +{ + THR_LOCK_DATA **pos,**end; + DBUG_ENTER("thr_multi_unlock"); + DBUG_PRINT("lock",("data: %lx count: %d",data,count)); + + for (pos=data,end=data+count; pos < end ; pos++) + { +#ifdef MAIN + printf("Thread: %s Rel lock: %lx type: %d\n", + my_thread_name(), (long) pos[0]->lock, pos[0]->type); + fflush(stdout); +#endif + if ((*pos)->type != TL_UNLOCK) + thr_unlock(*pos); + else + { + DBUG_PRINT("lock",("Free lock: data: %lx thread: %ld lock: %lx", + *pos,(*pos)->thread_id,(*pos)->lock)); + } + } + DBUG_VOID_RETURN; +} + +/* Abort all threads waiting for a lock. The lock will be upgraded to a + TL_WRITE_ONLY to abort any new accesses to the lock +*/ + +void thr_abort_locks(THR_LOCK *lock) +{ + THR_LOCK_DATA *data; + DBUG_ENTER("thr_abort_locks"); + pthread_mutex_lock(&lock->mutex); + + for (data=lock->read_wait.data; data ; data=data->next) + { + data->type=TL_UNLOCK; /* Mark killed */ + pthread_cond_signal(data->cond); + data->cond=0; /* Removed from list */ + } + for (data=lock->write_wait.data; data ; data=data->next) + { + data->type=TL_UNLOCK; + pthread_cond_signal(data->cond); + data->cond=0; + } + lock->read_wait.last= &lock->read_wait.data; + lock->write_wait.last= &lock->write_wait.data; + lock->read_wait.data=lock->write_wait.data=0; + if (lock->write.data) + lock->write.data->type=TL_WRITE_ONLY; + pthread_mutex_unlock(&lock->mutex); + DBUG_VOID_RETURN; +} + + +/* Upgrade a WRITE_DELAY lock to a WRITE_LOCK */ + +my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data) +{ + THR_LOCK *lock=data->lock; + DBUG_ENTER("thr_upgrade_write_delay_lock"); + + pthread_mutex_lock(&lock->mutex); + if (data->type == TL_UNLOCK || data->type == TL_WRITE) /* Aborted */ + { + pthread_mutex_unlock(&lock->mutex); + DBUG_RETURN(data->type == TL_UNLOCK); + } + check_locks(lock,"before upgrading lock",0); + /* TODO: Upgrade to TL_WRITE_CONCURRENT_INSERT in some cases */ + data->type=TL_WRITE; /* Upgrade lock */ + + /* Check if someone has given us the lock */ + if (!data->cond) + { + if (!lock->read.data) /* No read locks */ + { /* We have the lock */ + if (data->lock->get_status) + (*data->lock->get_status)(data->status_param); + pthread_mutex_unlock(&lock->mutex); + DBUG_RETURN(0); + } + + if (((*data->prev)=data->next)) /* remove from lock-list */ + data->next->prev= data->prev; + else + lock->write.last=data->prev; + + if ((data->next=lock->write_wait.data)) /* Put first in lock_list */ + data->next->prev= &data->next; + else + lock->write_wait.last= &data->next; + data->prev= &lock->write_wait.data; + lock->write_wait.data=data; + check_locks(lock,"upgrading lock",0); + } + DBUG_RETURN(wait_for_lock(&lock->write_wait,data,1)); +} + + +/* downgrade a WRITE lock to a WRITE_DELAY lock if there is pending locks */ + +my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data) +{ + THR_LOCK *lock=data->lock; + DBUG_ENTER("thr_reschedule_write_lock"); + + pthread_mutex_lock(&lock->mutex); + if (!lock->read_wait.data) /* No waiting read locks */ + { + pthread_mutex_unlock(&lock->mutex); + DBUG_RETURN(0); + } + + data->type=TL_WRITE_DELAYED; + if (lock->update_status) + (*lock->update_status)(data->status_param); + if (((*data->prev)=data->next)) /* remove from lock-list */ + data->next->prev= data->prev; + else + lock->write.last=data->prev; + + if ((data->next=lock->write_wait.data)) /* Put first in lock_list */ + data->next->prev= &data->next; + else + lock->write_wait.last= &data->next; + data->prev= &lock->write_wait.data; + data->cond=get_cond(); /* This was zero */ + lock->write_wait.data=data; + free_all_read_locks(lock,0); + + pthread_mutex_unlock(&lock->mutex); + DBUG_RETURN(thr_upgrade_write_delay_lock(data)); +} + + +#include <my_sys.h> + +static void thr_print_lock(const char* name,struct st_lock_list *list) +{ + THR_LOCK_DATA *data,**prev; + uint count=0; + + if (list->data) + { + printf("%-10s: ",name); + prev= &list->data; + for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next) + { + printf("%lx (%lu:%d); ",(ulong) data,data->thread_id,(int) data->type); + if (data->prev != prev) + printf("\nWarning: prev didn't point at previous lock\n"); + prev= &data->next; + } + puts(""); + if (prev != list->last) + printf("Warning: last didn't point at last lock\n"); + } +} + +void thr_print_locks(void) +{ + LIST *list; + uint count=0; + + pthread_mutex_lock(&THR_LOCK_lock); + puts("Current locks:"); + for (list=thread_list ; list && count++ < MAX_THREADS ; list=rest(list)) + { + THR_LOCK *lock=(THR_LOCK*) list->data; + VOID(pthread_mutex_lock(&lock->mutex)); + printf("lock: %lx:",(ulong) lock); + if ((lock->write_wait.data || lock->read_wait.data) && + (! lock->read.data && ! lock->write.data)) + printf(" WARNING: "); + if (lock->write.data) + printf(" write"); + if (lock->write_wait.data) + printf(" write_wait"); + if (lock->read.data) + printf(" read"); + if (lock->read_wait.data) + printf(" read_wait"); + puts(""); + thr_print_lock("write",&lock->write); + thr_print_lock("write_wait",&lock->write_wait); + thr_print_lock("read",&lock->read); + thr_print_lock("read_wait",&lock->read_wait); + VOID(pthread_mutex_unlock(&lock->mutex)); + puts(""); + } + fflush(stdout); + pthread_mutex_unlock(&THR_LOCK_lock); +} + +#ifdef MAIN + +struct st_test { + uint lock_nr; + enum thr_lock_type lock_type; +}; + +THR_LOCK locks[5]; /* 4 locks */ + +struct st_test test_0[] = {{0,TL_READ}}; /* One lock */ +struct st_test test_1[] = {{0,TL_READ},{0,TL_WRITE}}; /* Read and write lock of lock 0 */ +struct st_test test_2[] = {{1,TL_WRITE},{0,TL_READ},{2,TL_READ}}; +struct st_test test_3[] = {{2,TL_WRITE},{1,TL_READ},{0,TL_READ}}; /* Deadlock with test_2 ? */ +struct st_test test_4[] = {{0,TL_WRITE},{0,TL_READ},{0,TL_WRITE},{0,TL_READ}}; +struct st_test test_5[] = {{0,TL_READ},{1,TL_READ},{2,TL_READ},{3,TL_READ}}; /* Many reads */ +struct st_test test_6[] = {{0,TL_WRITE},{1,TL_WRITE},{2,TL_WRITE},{3,TL_WRITE}}; /* Many writes */ +struct st_test test_7[] = {{3,TL_READ}}; +struct st_test test_8[] = {{1,TL_READ_NO_INSERT},{2,TL_READ_NO_INSERT},{3,TL_READ_NO_INSERT}}; /* Should be quick */ +struct st_test test_9[] = {{4,TL_READ_HIGH_PRIORITY}}; +struct st_test test_10[] ={{4,TL_WRITE}}; +struct st_test test_11[] = {{0,TL_WRITE_LOW_PRIORITY},{1,TL_WRITE_LOW_PRIORITY},{2,TL_WRITE_LOW_PRIORITY},{3,TL_WRITE_LOW_PRIORITY}}; /* Many writes */ +struct st_test test_12[] = {{0,TL_WRITE_ALLOW_READ},{1,TL_WRITE_ALLOW_READ},{2,TL_WRITE_ALLOW_READ},{3,TL_WRITE_ALLOW_READ}}; /* Many writes */ +struct st_test test_13[] = {{0,TL_WRITE_CONCURRENT_INSERT},{1,TL_WRITE_CONCURRENT_INSERT},{2,TL_WRITE_CONCURRENT_INSERT},{3,TL_WRITE_CONCURRENT_INSERT}}; +struct st_test test_14[] = {{0,TL_WRITE_CONCURRENT_INSERT},{1,TL_READ}}; +struct st_test test_15[] = {{0,TL_WRITE_ALLOW_WRITE},{1,TL_READ}}; +struct st_test test_16[] = {{0,TL_WRITE_ALLOW_WRITE},{1,TL_WRITE_ALLOW_WRITE}}; + +struct st_test *tests[] = {test_0,test_1,test_2,test_3,test_4,test_5,test_6, + test_7,test_8,test_9,test_10,test_11,test_12, + test_13,test_14,test_15,test_16}; +int lock_counts[]= {sizeof(test_0)/sizeof(struct st_test), + sizeof(test_1)/sizeof(struct st_test), + sizeof(test_2)/sizeof(struct st_test), + sizeof(test_3)/sizeof(struct st_test), + sizeof(test_4)/sizeof(struct st_test), + sizeof(test_5)/sizeof(struct st_test), + sizeof(test_6)/sizeof(struct st_test), + sizeof(test_7)/sizeof(struct st_test), + sizeof(test_8)/sizeof(struct st_test), + sizeof(test_9)/sizeof(struct st_test), + sizeof(test_10)/sizeof(struct st_test), + sizeof(test_11)/sizeof(struct st_test), + sizeof(test_12)/sizeof(struct st_test), + sizeof(test_13)/sizeof(struct st_test), + sizeof(test_14)/sizeof(struct st_test), + sizeof(test_15)/sizeof(struct st_test), + sizeof(test_16)/sizeof(struct st_test) +}; + + +static pthread_cond_t COND_thread_count; +static pthread_mutex_t LOCK_thread_count; +static uint thread_count; +static ulong sum=0; + +#define MAX_LOCK_COUNT 8 + +/* The following functions is for WRITE_CONCURRENT_INSERT */ + +static void test_get_status(void* param __attribute__((unused))) +{ +} + +static void test_copy_status(void* to __attribute__((unused)) , + void *from __attribute__((unused))) +{ +} + +static my_bool test_check_status(void* param __attribute__((unused))) +{ + return 0; +} + + +static void *test_thread(void *arg) +{ + int i,j,param=*((int*) arg); + THR_LOCK_DATA data[MAX_LOCK_COUNT]; + THR_LOCK_DATA *multi_locks[MAX_LOCK_COUNT]; + my_thread_init(); + + printf("Thread %s (%d) started\n",my_thread_name(),param); fflush(stdout); + + for (i=0; i < lock_counts[param] ; i++) + thr_lock_data_init(locks+tests[param][i].lock_nr,data+i,NULL); + for (j=1 ; j < 10 ; j++) /* try locking 10 times */ + { + for (i=0; i < lock_counts[param] ; i++) + { /* Init multi locks */ + multi_locks[i]= &data[i]; + data[i].type= tests[param][i].lock_type; + } + thr_multi_lock(multi_locks,lock_counts[param]); + pthread_mutex_lock(&LOCK_thread_count); + { + int tmp=rand() & 7; /* Do something from 0-2 sec */ + if (tmp == 0) + sleep(1); + else if (tmp == 1) + sleep(2); + else + { + ulong k; + for (k=0 ; k < (ulong) (tmp-2)*100000L ; k++) + sum+=k; + } + } + pthread_mutex_unlock(&LOCK_thread_count); + thr_multi_unlock(multi_locks,lock_counts[param]); + } + + printf("Tread %s (%d) ended\n",my_thread_name(),param); fflush(stdout); + thr_print_locks(); + pthread_mutex_lock(&LOCK_thread_count); + thread_count--; + VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */ + pthread_mutex_unlock(&LOCK_thread_count); + free((gptr) arg); + return 0; +} + + +int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) +{ + pthread_t tid; + pthread_attr_t thr_attr; + int i,*param,error; + MY_INIT(argv[0]); + if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#') + DBUG_PUSH(argv[1]+2); + + printf("Main thread: %s\n",my_thread_name()); + + if ((error=pthread_cond_init(&COND_thread_count,NULL))) + { + fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)", + error,errno); + exit(1); + } + if ((error=pthread_mutex_init(&LOCK_thread_count,NULL))) + { + fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)", + error,errno); + exit(1); + } + + for (i=0 ; i < (int) array_elements(locks) ; i++) + { + thr_lock_init(locks+i); + locks[i].check_status= test_check_status; + locks[i].update_status=test_get_status; + locks[i].copy_status= test_copy_status; + locks[i].get_status= test_get_status; + } + if ((error=pthread_attr_init(&thr_attr))) + { + fprintf(stderr,"Got error: %d from pthread_attr_init (errno: %d)", + error,errno); + exit(1); + } + if ((error=pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED))) + { + fprintf(stderr, + "Got error: %d from pthread_attr_setdetachstate (errno: %d)", + error,errno); + exit(1); + } +#ifndef pthread_attr_setstacksize /* void return value */ + if ((error=pthread_attr_setstacksize(&thr_attr,65536L))) + { + fprintf(stderr,"Got error: %d from pthread_attr_setstacksize (errno: %d)", + error,errno); + exit(1); + } +#endif +#ifdef HAVE_THR_SETCONCURRENCY + VOID(thr_setconcurrency(2)); +#endif + for (i=0 ; i < (int) array_elements(lock_counts) ; i++) + { + param=(int*) malloc(sizeof(int)); + *param=i; + + if ((error=pthread_mutex_lock(&LOCK_thread_count))) + { + fprintf(stderr,"Got error: %d from pthread_mutex_lock (errno: %d)", + error,errno); + exit(1); + } + if ((error=pthread_create(&tid,&thr_attr,test_thread,(void*) param))) + { + fprintf(stderr,"Got error: %d from pthread_create (errno: %d)\n", + error,errno); + pthread_mutex_unlock(&LOCK_thread_count); + exit(1); + } + thread_count++; + pthread_mutex_unlock(&LOCK_thread_count); + } + + pthread_attr_destroy(&thr_attr); + if ((error=pthread_mutex_lock(&LOCK_thread_count))) + fprintf(stderr,"Got error: %d from pthread_mutex_lock\n",error); + while (thread_count) + { + if ((error=pthread_cond_wait(&COND_thread_count,&LOCK_thread_count))) + fprintf(stderr,"Got error: %d from pthread_cond_wait\n",error); + } + if ((error=pthread_mutex_unlock(&LOCK_thread_count))) + fprintf(stderr,"Got error: %d from pthread_mutex_unlock\n",error); + for (i=0 ; i < (int) array_elements(locks) ; i++) + thr_lock_delete(locks+i); +#ifdef EXTRA_DEBUG + if (found_errors) + printf("Got %d warnings\n",found_errors); + else +#endif + printf("Test succeeded\n"); + return 0; +} +#endif + +#endif diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c new file mode 100644 index 00000000000..7eea5be473b --- /dev/null +++ b/mysys/thr_mutex.c @@ -0,0 +1,214 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* This makes a wrapper for mutex handling to make it easier to debug mutex */ + +#include <global.h> +#if defined(HAVE_LINUXTHREADS) && !defined (__USE_UNIX98) +#define __USE_UNIX98 /* To get rw locks under Linux */ +#endif +#include <m_string.h> +#if defined(THREAD) && defined(SAFE_MUTEX) +#undef SAFE_MUTEX /* Avoid safe_mutex redefinitions */ +#include <my_pthread.h> + +#ifndef DO_NOT_REMOVE_THREAD_WRAPPERS +/* Remove wrappers */ +#undef pthread_mutex_init +#undef pthread_mutex_lock +#undef pthread_mutex_unlock +#undef pthread_mutex_destroy +#undef pthread_cond_wait +#undef pthread_cond_timedwait +#ifdef HAVE_NONPOSIX_PTHREAD_MUTEX_INIT +#define pthread_mutex_init(a,b) my_pthread_mutex_init((a),(b)) +#endif +#endif + +int safe_mutex_init(safe_mutex_t *mp, + const pthread_mutexattr_t *attr __attribute__((unused))) +{ + bzero((char*) mp,sizeof(*mp)); +#ifdef HAVE_LINUXTHREADS /* Some extra safety */ + { + pthread_mutexattr_t tmp; + pthread_mutexattr_init(&tmp); + pthread_mutexattr_setkind_np(&tmp,PTHREAD_MUTEX_ERRORCHECK_NP); + pthread_mutex_init(&mp->global,&tmp); + pthread_mutex_init(&mp->mutex, &tmp); + pthread_mutexattr_destroy(&tmp); + } +#else + pthread_mutex_init(&mp->global,NULL); + pthread_mutex_init(&mp->mutex,attr); +#endif + return 0; +} + +int safe_mutex_lock(safe_mutex_t *mp,const char *file, uint line) +{ + int error; + pthread_mutex_lock(&mp->global); + if (mp->count > 0 && pthread_equal(pthread_self(),mp->thread)) + { + fprintf(stderr,"safe_mutex: Trying to lock mutex at %s, line %d, when the mutex was already locked at %s, line %d\n", + file,line,mp->file,mp->line); + abort(); + } + pthread_mutex_unlock(&mp->global); + error=pthread_mutex_lock(&mp->mutex); + if (error || (error=pthread_mutex_lock(&mp->global))) + { + fprintf(stderr,"Got error %d when trying to lock mutex at %s, line %d\n", + error, file, line); + abort(); + } + if (mp->count++) + { + fprintf(stderr,"safe_mutex: Error in thread libray: Got mutex at %s, line %d more than 1 time\n", file,line); + abort(); + } + mp->thread=pthread_self(); + mp->file= (char*) file; + mp->line=line; + pthread_mutex_unlock(&mp->global); + return error; +} + + +int safe_mutex_unlock(safe_mutex_t *mp,const char *file, uint line) +{ + int error; + pthread_mutex_lock(&mp->global); + if (mp->count == 0) + { + fprintf(stderr,"safe_mutex: Trying to unlock mutex that wasn't locked at %s, line %d\n Last used at %s, line: %d\n", + file,line,mp->file ? mp->file : "",mp->line); + abort(); + } + if (!pthread_equal(pthread_self(),mp->thread)) + { + fprintf(stderr,"safe_mutex: Trying to unlock mutex at %s, line %d that was locked by another thread at: %s, line: %d\n", + file,line,mp->file,mp->line); + abort(); + } + mp->count--; + error=pthread_mutex_unlock(&mp->mutex); + if (error) + { + fprintf(stderr,"safe_mutex: Got error: %d when trying to unlock mutex at %s, line %d\n", error, file, line); + abort(); + } + pthread_mutex_unlock(&mp->global); + return error; +} + + +int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp, const char *file, + uint line) +{ + int error; + pthread_mutex_lock(&mp->global); + if (mp->count == 0) + { + fprintf(stderr,"safe_mutex: Trying to cond_wait on a unlocked mutex at %s, line %d\n",file,line); + abort(); + } + if (!pthread_equal(pthread_self(),mp->thread)) + { + fprintf(stderr,"safe_mutex: Trying to cond_wait on a mutex at %s, line %d that was locked by another thread at: %s, line: %d\n", + file,line,mp->file,mp->line); + abort(); + } + + if (mp->count-- != 1) + { + fprintf(stderr,"safe_mutex: Count was %d on locked mutex at %s, line %d\n", + mp->count+1, file, line); + abort(); + } + pthread_mutex_unlock(&mp->global); + error=pthread_cond_wait(cond,&mp->mutex); + pthread_mutex_lock(&mp->global); + if (error) + { + fprintf(stderr,"safe_mutex: Got error: %d when doing a safe_mutex_wait at %s, line %d\n", error, file, line); + abort(); + } + if (mp->count++) + { + fprintf(stderr, + "safe_mutex: Count was %d in thread %lx when locking mutex at %s, line %d\n", + mp->count-1, my_thread_id(), file, line); + abort(); + } + mp->thread=pthread_self(); + mp->file= (char*) file; + mp->line=line; + pthread_mutex_unlock(&mp->global); + return error; +} + + +int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp, + struct timespec *abstime, + const char *file, uint line) +{ + int error; + pthread_mutex_lock(&mp->global); + if (mp->count != 1 || !pthread_equal(pthread_self(),mp->thread)) + { + fprintf(stderr,"safe_mutex: Trying to cond_wait at %s, line %d on a not hold mutex\n",file,line); + abort(); + } + mp->count--; /* Mutex will be released */ + pthread_mutex_unlock(&mp->global); + error=pthread_cond_timedwait(cond,&mp->mutex,abstime); +#ifdef EXTRA_DEBUG + if (error && (error != EINTR && error != ETIMEDOUT)) + { + fprintf(stderr,"safe_mutex: Got error: %d when doing a safe_mutex_timedwait at %s, line %d\n", error, file, line); + } +#endif + pthread_mutex_lock(&mp->global); + if (mp->count++) + { + fprintf(stderr, + "safe_mutex: Count was %d in thread %lx when locking mutex at %s, line %d (error: %d)\n", + mp->count-1, my_thread_id(), file, line, error); + abort(); + } + mp->thread=pthread_self(); + mp->file= (char*) file; + mp->line=line; + pthread_mutex_unlock(&mp->global); + return error; +} + +int safe_mutex_destroy(safe_mutex_t *mp, const char *file, uint line) +{ + if (mp->count != 0) + { + fprintf(stderr,"safe_mutex: Trying to destroy a mutex that was locked at %s, line %d at %s, line %d\n", + mp->file,mp->line, file, line); + abort(); + } + pthread_mutex_destroy(&mp->global); + return pthread_mutex_destroy(&mp->mutex); +} + +#endif /* SAFE_MUTEX */ diff --git a/mysys/thr_rwlock.c b/mysys/thr_rwlock.c new file mode 100644 index 00000000000..fc2eea551da --- /dev/null +++ b/mysys/thr_rwlock.c @@ -0,0 +1,139 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Synchronization - readers / writer thread locks */ + +#include "mysys_priv.h" +#include <my_pthread.h> +#if defined(THREAD) && !defined(HAVE_PTHREAD_RWLOCK_RDLOCK) && !defined(HAVE_RWLOCK_INIT) + +/* + * Source base from Sun Microsystems SPILT, simplified + * for MySQL use -- Joshua Chamas + */ + +/* +* Multithreaded Demo Source +* +* Copyright (C) 1995 by Sun Microsystems, Inc. +* All rights reserved. +* +* This file is a product of SunSoft, Inc. and is provided for +* unrestricted use provided that this legend is included on all +* media and as a part of the software program in whole or part. +* Users may copy, modify or distribute this file at will. +* +* THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING +* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR +* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. +* +* This file is provided with no support and without any obligation on the +* part of SunSoft, Inc. to assist in its use, correction, modification or +* enhancement. +* +* SUNSOFT AND SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT +* TO THE INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS +* FILE OR ANY PART THEREOF. +* +* IN NO EVENT WILL SUNSOFT OR SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY +* LOST REVENUE OR PROFITS OR OTHER SPECIAL, INDIRECT AND CONSEQUENTIAL +* DAMAGES, EVEN IF THEY HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH +* DAMAGES. +* +* SunSoft, Inc. +* 2550 Garcia Avenue +* Mountain View, California 94043 +*/ + +int my_rwlock_init( rw_lock_t *rwp, void *arg __attribute__((unused))) +{ + pthread_condattr_t cond_attr; + + pthread_mutex_init( &rwp->lock, NULL ); + pthread_condattr_init( &cond_attr ); + pthread_cond_init( &rwp->readers, &cond_attr ); + pthread_cond_init( &rwp->writers, &cond_attr ); + pthread_condattr_destroy(&cond_attr); + + rwp->state = 0; + rwp->waiters = 0; + + return( 0 ); +} + +int my_rwlock_destroy( rw_lock_t *rwp ) { + pthread_mutex_destroy( &rwp->lock ); + pthread_cond_destroy( &rwp->readers ); + pthread_cond_destroy( &rwp->writers ); + + return( 0 ); +} + +int my_rw_rdlock( rw_lock_t *rwp ) { + pthread_mutex_lock(&rwp->lock); + + /* active or queued writers */ + while ( ( rwp->state < 0 ) && rwp->waiters ) + pthread_cond_wait( &rwp->readers, &rwp->lock); + + rwp->state++; + pthread_mutex_unlock(&rwp->lock); + + return( 0 ); +} + +int my_rw_wrlock( rw_lock_t *rwp ) { + + pthread_mutex_lock(&rwp->lock); + rwp->waiters++; /* another writer queued */ + + while ( rwp->state ) + pthread_cond_wait( &rwp->writers, &rwp->lock); + + rwp->state = -1; + + if ( ( --rwp->waiters == 0 ) && ( rwp->state >= 0 ) ) + pthread_cond_broadcast( &rwp->readers ); + + pthread_mutex_unlock( &rwp->lock ); + + return( 0 ); +} + +int my_rw_unlock( rw_lock_t *rwp ) { + DBUG_PRINT("rw_unlock", + ("state: %d waiters: %d", rwp->state, rwp->waiters)); + pthread_mutex_lock(&rwp->lock); + + if ( rwp->state == -1 ) { /* writer releasing */ + rwp->state = 0; /* mark as available */ + + if ( rwp->waiters ) /* writers queued */ + pthread_cond_signal( &rwp->writers ); + else + pthread_cond_broadcast( &rwp->readers ); + } else { + if ( --rwp->state == 0 ) /* no more readers */ + pthread_cond_signal( &rwp->writers ); + } + + pthread_mutex_unlock( &rwp->lock ); + + return( 0 ); +} + +#endif diff --git a/mysys/tree.c b/mysys/tree.c new file mode 100644 index 00000000000..259fc5fb9d0 --- /dev/null +++ b/mysys/tree.c @@ -0,0 +1,513 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* + Code for handling red-black (balanced) binary trees. + key in tree is allocated accrding to following: + 1) If free_element function is given to init_tree or size < 0 then tree + will not allocate keys and only a pointer to each key is saved in tree. + key_sizes must be 0 to init and search. + compare and search functions uses and returns key-pointer. + 2) if key_size is given to init_tree then each node will continue the + key and calls to insert_key may increase length of key. + if key_size > sizeof(pointer) and key_size is a multiple of 8 (double + allign) then key will be put on a 8 alligned adress. Else + the key will be on adress (element+1). This is transparent for user + compare and search functions uses a pointer to given key-argument. + 3) If init_tree - keysize is 0 then key_size must be given to tree_insert + and tree_insert will alloc space for key. + compare and search functions uses a pointer to given key-argument. + + The actual key in TREE_ELEMENT is saved as a pointer or after the + TREE_ELEMENT struct. + If one uses only pointers in tree one can use tree_set_pointer() to + change address of data. + Copyright Monty Program KB. + By monty. +*/ + +#include "mysys_priv.h" +#include <m_string.h> +#include <my_tree.h> + +#define BLACK 1 +#define RED 0 +#define DEFAULT_ALLOC_SIZE (8192-MALLOC_OVERHEAD) + +static void delete_tree_element(TREE *,TREE_ELEMENT *); +static int tree_walk_left_root_right(TREE *,TREE_ELEMENT *, + tree_walk_action,void *); +static int tree_walk_right_root_left(TREE *,TREE_ELEMENT *, + tree_walk_action,void *); +static void left_rotate(TREE_ELEMENT **parent,TREE_ELEMENT *leaf); +static void right_rotate(TREE_ELEMENT **parent, TREE_ELEMENT *leaf); +static void rb_insert(TREE *tree,TREE_ELEMENT ***parent, + TREE_ELEMENT *leaf); +static void rb_delete_fixup(TREE *tree,TREE_ELEMENT ***parent); + + + /* The actuall code for handling binary trees */ + +void init_tree(TREE *tree, uint default_alloc_size, int size, + qsort_cmp compare, my_bool with_delete, + void (*free_element) (void *)) +{ + DBUG_ENTER("init_tree"); + DBUG_PRINT("enter",("tree: %lx size: %d",tree,size)); + + if (!default_alloc_size) + default_alloc_size= DEFAULT_ALLOC_SIZE; + bzero((gptr) &tree->null_element,sizeof(tree->null_element)); + tree->root= &tree->null_element; + tree->compare=compare; + tree->size_of_element=size > 0 ? (uint) size : 0; + tree->free=free_element; + tree->elements_in_tree=0; + tree->null_element.colour=BLACK; + tree->null_element.left=tree->null_element.right=0; + if (!free_element && size >= 0 && + ((uint) size <= sizeof(void*) || ((uint) size & (sizeof(void*)-1)))) + { + tree->offset_to_key=sizeof(TREE_ELEMENT); /* Put key after element */ + /* Fix allocation size so that we don't loose any memory */ + default_alloc_size/=(sizeof(TREE_ELEMENT)+size); + if (!default_alloc_size) + default_alloc_size=1; + default_alloc_size*=(sizeof(TREE_ELEMENT)+size); + } + else + { + tree->offset_to_key=0; /* use key through pointer */ + tree->size_of_element+=sizeof(void*); + } + if (!(tree->with_delete=with_delete)) + { + init_alloc_root(&tree->mem_root, default_alloc_size); + tree->mem_root.min_malloc=(sizeof(TREE_ELEMENT)+tree->size_of_element); + } + DBUG_VOID_RETURN; +} + +void delete_tree(TREE *tree) +{ + DBUG_ENTER("delete_tree"); + DBUG_PRINT("enter",("tree: %lx",tree)); + + if (tree->root) /* If initialized */ + { + if (tree->with_delete) + delete_tree_element(tree,tree->root); + else + { + if (tree->free) + delete_tree_element(tree,tree->root); + free_root(&tree->mem_root); + } + } + tree->root= &tree->null_element; + tree->elements_in_tree=0; + + DBUG_VOID_RETURN; +} + +static void delete_tree_element(TREE *tree, TREE_ELEMENT *element) +{ + if (element != &tree->null_element) + { + delete_tree_element(tree,element->left); + delete_tree_element(tree,element->right); + if (tree->free) + (*tree->free)(ELEMENT_KEY(tree,element)); + if (tree->with_delete) + my_free((void*) element,MYF(0)); + } +} + + /* Code for insert, search and delete of elements */ + /* parent[0] = & parent[-1][0]->left || + parent[0] = & parent[-1][0]->right */ + + +TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size) +{ + int cmp; + TREE_ELEMENT *element,***parent; + + parent= tree->parents; + *parent = &tree->root; element= tree->root; + for (;;) + { + if (element == &tree->null_element || + (cmp=(*tree->compare)(ELEMENT_KEY(tree,element),key)) == 0) + break; + if (cmp < 0) + { + *++parent= &element->right; element= element->right; + } + else + { + *++parent = &element->left; element= element->left; + } + } + if (element == &tree->null_element) + { + key_size+=tree->size_of_element; + if (tree->with_delete) + element=(TREE_ELEMENT *) my_malloc(sizeof(TREE_ELEMENT)+key_size, + MYF(MY_WME)); + else + element=(TREE_ELEMENT *) + alloc_root(&tree->mem_root,sizeof(TREE_ELEMENT)+key_size); + if (!element) + return(NULL); + **parent=element; + element->left=element->right= &tree->null_element; + if (!tree->offset_to_key) + { + if (key_size == sizeof(void*)) /* no length, save pointer */ + *((void**) (element+1))=key; + else + { + *((void**) (element+1))= (void*) ((void **) (element+1)+1); + memcpy((byte*) *((void **) (element+1)),key, + (size_t) (key_size-sizeof(void*))); + } + } + else + memcpy((byte*) element+tree->offset_to_key,key,(size_t) key_size); + element->count=1; /* May give warning in purify */ + tree->elements_in_tree++; + rb_insert(tree,parent,element); /* rebalance tree */ + } + else + element->count++; + return element; +} + + +int tree_delete(TREE *tree, void *key) +{ + int cmp,remove_colour; + TREE_ELEMENT *element,***parent, ***org_parent, *nod; + if (!tree->with_delete) + return 1; /* not allowed */ + + parent= tree->parents; + *parent= &tree->root; element= tree->root; + for (;;) + { + if (element == &tree->null_element) + return 1; /* Was not in tree */ + if ((cmp=(*tree->compare)(ELEMENT_KEY(tree,element),key)) == 0) + break; + if (cmp < 0) + { + *++parent= &element->right; element= element->right; + } + else + { + *++parent = &element->left; element= element->left; + } + } + if (element->left == &tree->null_element) + { + (**parent)=element->right; + remove_colour= element->colour; + } + else if (element->right == &tree->null_element) + { + (**parent)=element->left; + remove_colour= element->colour; + } + else + { + org_parent= parent; + *++parent= &element->right; nod= element->right; + while (nod->left != &tree->null_element) + { + *++parent= &nod->left; nod= nod->left; + } + (**parent)=nod->right; /* unlink nod from tree */ + remove_colour= nod->colour; + org_parent[0][0]=nod; /* put y in place of element */ + org_parent[1]= &nod->right; + nod->left=element->left; + nod->right=element->right; + nod->colour=element->colour; + } + if (remove_colour == BLACK) + rb_delete_fixup(tree,parent); + my_free((gptr) element,MYF(0)); + tree->elements_in_tree--; + return 0; +} + + +void *tree_search(TREE *tree, void *key) +{ + int cmp; + TREE_ELEMENT *element=tree->root; + + for (;;) + { + if (element == &tree->null_element) + return (void*) 0; + if ((cmp=(*tree->compare)(ELEMENT_KEY(tree,element),key)) == 0) + return ELEMENT_KEY(tree,element); + if (cmp < 0) + element=element->right; + else + element=element->left; + } +} + + +int tree_walk(TREE *tree, tree_walk_action action, void *argument, TREE_WALK visit) +{ + switch (visit) { + case left_root_right: + return tree_walk_left_root_right(tree,tree->root,action,argument); + case right_root_left: + return tree_walk_right_root_left(tree,tree->root,action,argument); + } + return 0; /* Keep gcc happy */ +} + +static int tree_walk_left_root_right(TREE *tree, TREE_ELEMENT *element, tree_walk_action action, void *argument) +{ + int error; + if (element->left) /* Not null_element */ + { + if ((error=tree_walk_left_root_right(tree,element->left,action, + argument)) == 0 && + (error=(*action)(ELEMENT_KEY(tree,element), + (element_count) element->count, + argument)) == 0) + error=tree_walk_left_root_right(tree,element->right,action,argument); + return error; + } + return 0; +} + +static int tree_walk_right_root_left(TREE *tree, TREE_ELEMENT *element, tree_walk_action action, void *argument) +{ + int error; + if (element->right) /* Not null_element */ + { + if ((error=tree_walk_right_root_left(tree,element->right,action, + argument)) == 0 && + (error=(*action)(ELEMENT_KEY(tree,element), + (element_count) element->count, + argument)) == 0) + error=tree_walk_right_root_left(tree,element->left,action,argument); + return error; + } + return 0; +} + + + /* Functions to fix up the tree after insert and delete */ + +static void left_rotate(TREE_ELEMENT **parent, TREE_ELEMENT *leaf) +{ + TREE_ELEMENT *y; + + y=leaf->right; + leaf->right=y->left; + parent[0]=y; + y->left=leaf; +} + +static void right_rotate(TREE_ELEMENT **parent, TREE_ELEMENT *leaf) +{ + TREE_ELEMENT *x; + + x=leaf->left; + leaf->left=x->right; + parent[0]=x; + x->right=leaf; +} + +static void rb_insert(TREE *tree, TREE_ELEMENT ***parent, TREE_ELEMENT *leaf) +{ + TREE_ELEMENT *y,*par,*par2; + + leaf->colour=RED; + while (leaf != tree->root && (par=parent[-1][0])->colour == RED) + { + if (par == (par2=parent[-2][0])->left) + { + y= par2->right; + if (y->colour == RED) + { + par->colour=BLACK; + y->colour=BLACK; + leaf=par2; + parent-=2; + leaf->colour=RED; /* And the loop continues */ + } + else + { + if (leaf == par->right) + { + left_rotate(parent[-1],par); + par=leaf; /* leaf is now parent to old leaf */ + } + par->colour=BLACK; + par2->colour=RED; + right_rotate(parent[-2],par2); + break; + } + } + else + { + y= par2->left; + if (y->colour == RED) + { + par->colour=BLACK; + y->colour=BLACK; + leaf=par2; + parent-=2; + leaf->colour=RED; /* And the loop continues */ + } + else + { + if (leaf == par->left) + { + right_rotate(parent[-1],par); + par=leaf; + } + par->colour=BLACK; + par2->colour=RED; + left_rotate(parent[-2],par2); + break; + } + } + } + tree->root->colour=BLACK; +} + +static void rb_delete_fixup(TREE *tree, TREE_ELEMENT ***parent) +{ + TREE_ELEMENT *x,*w,*par; + + x= **parent; + while (x != tree->root && x->colour == BLACK) + { + if (x == (par=parent[-1][0])->left) + { + w=par->right; + if (w->colour == RED) + { + w->colour=BLACK; + par->colour=RED; + left_rotate(parent[-1],par); + parent[0]= &w->left; + *++parent= &par->left; + w=par->right; + } + if (w->left->colour == BLACK && w->right->colour == BLACK) + { + w->colour=RED; + x=par; + parent--; + } + else + { + if (w->right->colour == BLACK) + { + w->left->colour=BLACK; + w->colour=RED; + right_rotate(&par->right,w); + w=par->right; + } + w->colour=par->colour; + par->colour=BLACK; + w->right->colour=BLACK; + left_rotate(parent[-1],par); + x=tree->root; + break; + } + } + else + { + w=par->left; + if (w->colour == RED) + { + w->colour=BLACK; + par->colour=RED; + right_rotate(parent[-1],par); + parent[0]= &w->right; + *++parent= &par->right; + w=par->left; + } + if (w->right->colour == BLACK && w->left->colour == BLACK) + { + w->colour=RED; + x=par; + parent--; + } + else + { + if (w->left->colour == BLACK) + { + w->right->colour=BLACK; + w->colour=RED; + left_rotate(&par->left,w); + w=par->left; + } + w->colour=par->colour; + par->colour=BLACK; + w->left->colour=BLACK; + right_rotate(parent[-1],par); + x=tree->root; + break; + } + } + } + x->colour=BLACK; +} + + +#ifdef TESTING_TREES + + /* Test that the proporties for a red-black tree holds */ + +static int test_rb_tree(TREE_ELEMENT *element) +{ + int count_l,count_r; + + if (!element->left) + return 0; /* Found end of tree */ + if (element->colour == RED && + (element->left->colour == RED || element->right->colour == RED)) + { + printf("Wrong tree: Found two red in a row\n"); + return -1; + } + count_l=test_rb_tree(element->left); + count_r=test_rb_tree(element->right); + if (count_l >= 0 && count_r >= 0) + { + if (count_l == count_r) + return count_l+(element->colour == BLACK); + printf("Wrong tree: Incorrect black-count: %d - %d\n",count_l,count_r); + } + return -1; +} + +#endif diff --git a/mysys/typelib.c b/mysys/typelib.c new file mode 100644 index 00000000000..903a7304065 --- /dev/null +++ b/mysys/typelib.c @@ -0,0 +1,106 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Functions to handle typelib */ + +#include "mysys_priv.h" +#include <m_string.h> +#include <m_ctype.h> + +/*************************************************************************** +** Search after a fieldtype. Endspace in x is not compared. +** If part, uniq field is found and full_name == 0 then x is expanded +** to full field. +** full_name has the following bit values: +** If & 1 accept only hole names +** If & 2 don't expand if half field +** If & 4 allow #number# as type +****************************************************************************/ + +int find_type(my_string x, TYPELIB *typelib, uint full_name) +{ + int find,pos,findpos; + reg1 my_string i; + reg2 const char *j; + DBUG_ENTER("find_type"); + DBUG_PRINT("enter",("x: '%s' lib: %lx",x,typelib)); + + if (!typelib->count) + { + DBUG_PRINT("exit",("no count")); + DBUG_RETURN(0); + } + LINT_INIT(findpos); + find=0; + for (pos=0 ; (j=typelib->type_names[pos]) ; pos++) + { + for (i=x ; *i && toupper(*i) == toupper(*j) ; i++, j++) ; + if (! *j) + { + while (*i == ' ') + i++; /* skipp_end_space */ + if (! *i) + DBUG_RETURN(pos+1); + } + if (! *i) + { + find++; + findpos=pos; + } + } + if (find == 0 && (full_name & 4) && x[0] == '#' && strend(x)[-1] == '#' && + (findpos=atoi(x+1)-1) >= 0 && (uint) findpos < typelib->count) + find=1; + else if (find == 0 || ! x[0]) + { + DBUG_PRINT("exit",("Couldn't find type")); + DBUG_RETURN(0); + } + else if (find != 1 || (full_name & 1)) + { + DBUG_PRINT("exit",("Too many possybilities")); + DBUG_RETURN(-1); + } + if (!(full_name & 2)) + (void) strmov(x,typelib->type_names[findpos]); + DBUG_RETURN(findpos+1); +} /* find_type */ + + + /* Get name of type nr 'nr' */ + /* Warning first type is 1, 0 = empty field */ + +void make_type(register my_string to, register uint nr, register TYPELIB *typelib) +{ + DBUG_ENTER("make_type"); + if (!nr) + to[0]=0; + else + (void) strmov(to,get_type(typelib,nr-1)); + DBUG_VOID_RETURN; +} /* make_type */ + + + /* Get type */ + /* Warning first type is 0 */ + +const char *get_type(TYPELIB *typelib, uint nr) +{ + if (nr < (uint) typelib->count && typelib->type_names) + return(typelib->type_names[nr]); + return "?"; +} |