]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Update. cvs/libc-ud-971111
authorUlrich Drepper <drepper@redhat.com>
Wed, 12 Nov 1997 00:06:02 +0000 (00:06 +0000)
committerUlrich Drepper <drepper@redhat.com>
Wed, 12 Nov 1997 00:06:02 +0000 (00:06 +0000)
1997-11-11 21:30  Ulrich Drepper  <drepper@cygnus.com>

* include/sys/stat.h: Define stat, fstat, lstat and *64 variants
as macros so the the library compiles correctly even without
optimization.
* io/fstat.c: Undef fstat.
* io/fstat64.c: Undef fstat64
* io/lstat.c: Undef lstat.
* io/lstat64.c: Undef lstat64
* io/stat.c: Undef stat.
* io/stat64.c: Undef stat64
* io/fts.c: Include <include/sys/stat.h> to get macro definitions.
* io/ftw.c: Likewise.
* io/getdirname.c: Likewise.

* Makefile (install): Run test-installation.pl if possible.

* db2/Makefile: Update from db-2.3.12.
* db2/db.h: Likewise.
* db2/db_int.h: Likewise.
* db2/btree/bt_cursor.c: Likewise.
* db2/btree/bt_delete.c: Likewise.
* db2/btree/bt_open.c: Likewise.
* db2/btree/bt_put.c: Likewise.
* db2/btree/bt_rec.c: Likewise.
* db2/btree/bt_recno.c: Likewise.
* db2/btree/bt_search.c: Likewise.
* db2/btree/bt_split.c: Likewise.
* db2/btree/bt_stat.c: Likewise.
* db2/btree/btree.src: Likewise.
* db2/btree/btree_auto.c: Likewise.
* db2/btree/bt_cursor.c: Likewise.
* db2/btree/bt_delete.c: Likewise.
* db2/btree/bt_open.c: Likewise.
* db2/btree/bt_put.c: Likewise.
* db2/btree/bt_rec.c: Likewise.
* db2/btree/bt_recno.c: Likewise.
* db2/btree/bt_search.c: Likewise.
* db2/btree/bt_split.c: Likewise.
* db2/btree/bt_stat.c: Likewise.
* db2/btree/btree.src: Likewise.
* db2/btree/btree_auto.c: Likewise.
* db2/common/db_appinit.c: Likewise.
* db2/common/db_apprec.c: Likewise.
* db2/common/db_byteorder.c: Likewise.
* db2/common/db_region.c: Likewise.
* db2/db/db.c: Likewise
* db2/db/db.src: Likewise
* db2/db/db_auto.c: Likewise
* db2/db/db_dispatch.c: Likewise
* db2/db/db_dup.c: Likewise
* db2/db/db_overflow.c: Likewise
* db2/db/db_pr.c: Likewise
* db2/db/db_rec.c: Likewise
* db2/db/db_ret.c: Likewise
* db2/db/db_thread.c: Likewise
* db2/db185/db185.c: Likewise.
* db2/hash/hash.c: Likewise.
* db2/hash/hash.src: Likewise.
* db2/hash/hash_auto.c: Likewise.
* db2/hash/hash_dup.c: Likewise.
* db2/hash/hash_page.c: Likewise.
* db2/hash/hash_rec.c: Likewise.
* db2/include/btree_auto.h: Likewise.
* db2/include/btree_ext.h: Likewise.
* db2/include/clib_ext.h: Likewise.
* db2/include/common_ext.h: Likewise.
* db2/include/db.h.src: Likewise.
* db2/include/db_am.h: Likewise.
* db2/include/db_auto.h: Likewise.
* db2/include/db_cxx.h: Likewise.
* db2/include/db_ext.h: Likewise.
* db2/include/db_int.h.src: Likewise.
* db2/include/hash.h: Likewise.
* db2/include/hash_auto.h: Likewise.
* db2/include/hash_ext.h: Likewise.
* db2/include/lock.h: Likewise.
* db2/include/lock_ext.h: Likewise.
* db2/include/log.h: Likewise.
* db2/include/log_ext.h: Likewise.
* db2/include/mp.h: Likewise.
* db2/include/mp_ext.h: Likewise.
* db2/include/mutex_ext.h: Likewise.
* db2/include/os_ext.h: Likewise.
* db2/include/os_func.h: Likewise.
* db2/include/txn.h: Likewise.
* db2/include/txn_ext.h: Likewise.
* db2/lock/lock.c: Likewise.
* db2/lock/lock_deadlock.c: Likewise.
* db2/log/log.c: Likewise.
* db2/log/log_archive.c: Likewise.
* db2/log/log_auto.c: Likewise.
* db2/log/log_findckp.c: Likewise.
* db2/log/log_get.c: Likewise.
* db2/log/log_put.c: Likewise.
* db2/log/log_rec.c: Likewise.
* db2/log/log_register.c: Likewise.
* db2/mp/mp_bh.c: Likewise.
* db2/mp/mp_fget.c: Likewise.
* db2/mp/mp_fopen.c: Likewise.
* db2/mp/mp_fput.c: Likewise.
* db2/mp/mp_fset.c: Likewise.
* db2/mp/mp_open.c: Likewise.
* db2/mp/mp_pr.c: Likewise.
* db2/mp/mp_region.c: Likewise.
* db2/mp/mp_sync.c: Likewise.
* db2/mutex/mutex.c: Likewise.
* db2/os/os_abs.c: Likewise.
* db2/os/os_dir.c: Likewise.
* db2/os/os_fid.c: Likewise.
* db2/os/os_fsync.c: Likewise.
* db2/os/os_func.c: Likewise.
* db2/os/os_map.c: Likewise.
* db2/os/os_oflags.c: Likewise.
* db2/os/os_open.c: Likewise.
* db2/os/os_rpath.c: Likewise.
* db2/os/os_rw.c: Likewise.
* db2/os/os_seek.c: Likewise.
* db2/os/os_sleep.c: Likewise.
* db2/os/os_stat.c: Likewise.
* db2/os/os_unlink.c: Likewise.
* db2/progs/db_deadlock/db_deadlock.c: Likewise.
* db2/progs/db_dump/db_dump.c: Likewise.
* db2/progs/db_load/db_load.c: Likewise.
* db2/progs/db_recover/db_recover.c: Likewise.
* db2/progs/db_stat/db_stat.c: Likewise.
* db2/txn/txn.c: Likewise.
* db2/txn/txn_auto.c: Likewise.
* db2/txn/txn_rec.c: Likewise.
* db2/os/db_os_abs.c: Removed.
* db2/os/db_os_dir.c: Removed.
* db2/os/db_os_fid.c: Removed.
* db2/os/db_os_lseek.c: Removed.
* db2/os/db_os_mmap.c: Removed.
* db2/os/db_os_open.c: Removed.
* db2/os/db_os_rw.c: Removed.
* db2/os/db_os_sleep.c: Removed.
* db2/os/db_os_stat.c: Removed.
* db2/os/db_os_unlink.c: Removed.

* libio/stdio.h (fopen): Add __restrict to parameters.

* manual/process.texi (system): Describe behaviour for NULL argument.

* stdio-common/printf-parse.h: Parse hh modifier.
* stdio-common/vfprintf.c: Handle hh modifier.
* stdio-common/vfscanf.c: Likewise.
* manual/stdio.texi: Describe hh modifier for scanf/printf.

* math/complex.h: Don't define _Imaginary_I, but instead _Complex_I.
gcc does no yet know the `imaginary' keyword.

* math/test-math.c: Add little test for know gcc bug.

* math/tgmath.h: Make complex versions of log10() only available
if __USE_GNU.

* stdlib/test-canon.c: Fix typo.

* sysdeps/generic/setenv.c: Avoid compilation warnings.
Reported by Jim Meyering.

* sysdeps/generic/bits/errno.h: EILSEQ is an ISO C error number.
* sysdeps/mach/hurd/bits/errno.h: Likewise.
* sysdeps/standalone/bits/errno.h: Likewise.
* sysdeps/unix/sysv/linux/bits/errno.h: Likewise.

* sysdeps/i386/i586/memcpy.S: New file.
* sysdeps/i386/i586/mempcpy.S: New file.

* sysdeps/i386/i586/memset.S: Fix typo.

* sysdeps/posix/getcwd.c: Define HAVE_MEMPCPY for _LIBC.  Add casts.

* sysdeps/posix/system.c: Add comment to explain code.

* sysdeps/wordsize-32/inttypes.h: Include <stddef.h> for wchar_t.
Define PTRDIFF_{MIN,MAX}, SIG_ATOMIC_{MIN,MAX}, SIZE_MAX,
WCHAR_{MIN,MAX}, WINT_{MIN,MAX}.
Define wcstoimax, wcstoumax.
* sysdeps/wordsize-64/inttypes.h: Likewise.

* wcsmbs/wchar.h: Define WCHAR_{MIN,MAX} if not already defined.
Declare __wcsto{l,ul,ll,ull}_internal only if not already done.

* time/Makefile (routines): Add strfxtime.
* time/strftime.c: Implement %F and %f format.
* time/strfxtime.c: New file.
* time/time.h: Define new types and symbols from ISO C 9X.

* time/mktime.c: Little comment correction.

1997-11-10  Andreas Jaeger  <aj@arthur.rhein-neckar.de>

* sysdeps/libm-ieee754/s_sincosl.c: Fix typo.

* sysdeps/libm-ieee754/s_tanl.c: Fix typo.

* sysdeps/libm-ieee754/s_floorl.c: Correct typos.

* sysdeps/libm-ieee754/e_remainderl.c: Replace
EXTRACT_LDOUBLE_WORDS by GET_LDOUBLE_WORDS.

* sysdeps/libm-ieee754/e_atan2l.c: Replace EXTRACT_LDOUBLE_WORDS
by GET_LDOUBLE_WORDS.

* sysdeps/libm-ieee754/s_scalbnl.c: Replace ";" by "," for correct
variable declaration.
* sysdeps/libm-ieee754/s_scalblnl.c: Likewise.

* sysdeps/libm-ieee754/s_lrint.c (__lrint): Correct function.

* math/libm-test.c (sqrt_test): Add test for sqrt (0.25).
(asin_test): Add more test.

1997-11-10 23:34  Ulrich Drepper  <drepper@cygnus.com>

* sysdeps/libm-ieee754/e_asin.c: Add braces to make code clearer
and to not confuse the poor compiler.
* sysdeps/libm-ieee754/e_asinf.c: Likewise.
Reported by vertex@cagent.com.

1997-11-09  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

* elf/dl-lookup.c (do_lookup): Don't accept the base version if we
require a specific one.

* libio/oldfreopen.c: Bind old symbols to version GLIBC_2.0.
* libio/oldiofopen.c: Likewise.
* libio/oldstdfiles.c: Likewise.
* libc.map: Export them.

1997-11-10 07:40  H.J. Lu  <hjl@gnu.ai.mit.edu>

* stdlib/exit.c (exit): Handle recursive calls to exit ().

1997-11-09  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

* sysdeps/m68k/fpu/s_llrint.c: Fixed to take double argument
instead of long double.
* sysdeps/m68k/fpu/s_llrintf.c: New file.
* sysdeps/m68k/fpu/s_llrintl.c: New file.

* sysdeps/libm-ieee754/s_llrint.c: Make compilable and fix
overflow condition.
* sysdeps/libm-ieee754/s_llrintf.c: Fix overflow condition.
* sysdeps/libm-ieee754/s_llrintl.c: Likewise.
* sysdeps/libm-ieee754/s_llround.c: Likewise.
* sysdeps/libm-ieee754/s_llroundf.c: Likewise.
* sysdeps/libm-ieee754/s_llroundl.c: Likewise.
* sysdeps/libm-ieee754/s_lrint.c: Likewise.
* sysdeps/libm-ieee754/s_lrintf.c: Likewise.
* sysdeps/libm-ieee754/s_lrintl.c: Likewise.
* sysdeps/libm-ieee754/s_lround.c: Likewise.
* sysdeps/libm-ieee754/s_lroundf.c: Likewise.
* sysdeps/libm-ieee754/s_lroundl.c: Likewise.

* math/libm-test.c: Test all three variants of lrint and llrint.
Fix typos in lround and llround tests.  Add tests for boundary
cases for lrint and llround.

1997-11-08  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

* manual/arith.texi: Misc doc fixes.
* manual/ctype.texi: Likewise.
* manual/pattern.texi: Likewise.
* manual/terminal.texi: Likewise.

1997-11-08  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

* sysdeps/unix/sysv/linux/xstatconv.c: Use struct assignment
instead of memcpy to let the compiler use whatever it regards as
optimal.
* sysdeps/unix/sysv/linux/alpha/xstatconv.c: Likewise.

1997-11-08  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

* sysdeps/unix/sysv/linux/Makefile (sysdep_headers)
[$(subdir)=misc]: Add sys/prctl.h.
* sysdeps/unix/sysv/linux/Dist: Distribute it.

1997-11-08  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

* io/ftwtest-sh: Don't use the unknown which command, instead try
pwd as /bin/pwd and /usr/bin/pwd.

1997-11-08  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

* manual/maint.texi (Tools for Installation): Don't recommend
broken version 3.76.1 of make.
(Porting): Fix wording.

1997-11-06 06:13  H.J. Lu  <hjl@gnu.ai.mit.edu>

* config.make.in (build-pic-default): New, defined with
pic_default.

* configure.in (pic_default): New, set to yes if PIC is
default.

* Makeconfig (CPPFLAGS-.o, CPPFLAGS-.op, CPPFLAGS-.og,
CPPFLAGS-.ob): Add -DPIC if $(build-pic-default) is yes.

1997-11-09 18:15  Ulrich Drepper  <drepper@cygnus.com>

* Makerules (libc.so): Fix typo.

* csu/Makefile (CFLAGS-initfini.s): Correctly fix moving function
definition.  Patch by Zack Weinberg <zack@rabi.phys.columbia.edu>.

* stdlib/strtod.c: Handle numbers like 0.0e10000 correctly which
produce ±0.0.  Reported by Joe Keane <jgk@jgk.org>.

* sysdeps/libm-ieee754/s_ceill.c: Fix typos.
* sysdeps/libm-ieee754/s_llrint.c: Correct code, it never worked.

1997-11-06 07:00  H.J. Lu  <hjl@gnu.ai.mit.edu>

* sysdeps/unix/sysv/i386/i686/time.S: Removed.

1997-11-08 14:07  Thorsten Kukuk  <kukuk@vt.uni-paderborn.de>

* nis/libnsl.map: Add __do_niscall2 for nis_cachemgr.

* nis/nis_call.c: Set UDP resend timeout correct.

* nis/nss_compat/compat-grp.c: Rewritten to make it faster.
* nis/nss_compat/compat-pwd.c: Likewise.
* nis/nss_compat/compat-spwd.c: Likewise.
* nis/ypclnt.c: Fix UDP resend timeout, fix yp_bind/do_ypcall
interaction.

* inet/protocols/routed.h: Include sys/socket.h.
* inet/protocols/talkd.h: Likewise.
* inet/protocols/timed.h: Include rpc/types.h.
* sunrpc/rpc/pmap_clnt.h: Include rpc/clnt.h.

1997-11-06 01:39  Ulrich Drepper  <drepper@cygnus.com>

* Makerules (libc.so): Add missing closing brace.

1997-11-05  Brendan Kehoe  <brendan@lisa.cygnus.com>

* libio.h (__P): Name its arg `p' instead of `params'.
This was added solely to work around problems with
the definition of __P in the Solaris math.h header.

203 files changed:
ChangeLog
Makeconfig
Makefile
Makerules
bits/errno.h
config.make.in
configure
configure.in
csu/Makefile
db2/Makefile
db2/btree/bt_cursor.c
db2/btree/bt_delete.c
db2/btree/bt_open.c
db2/btree/bt_put.c
db2/btree/bt_rec.c
db2/btree/bt_recno.c
db2/btree/bt_search.c
db2/btree/bt_split.c
db2/btree/bt_stat.c
db2/btree/btree.src
db2/btree/btree_auto.c
db2/common/db_appinit.c
db2/common/db_apprec.c
db2/common/db_byteorder.c
db2/common/db_region.c
db2/db.h
db2/db/db.c
db2/db/db.src
db2/db/db_auto.c
db2/db/db_dispatch.c
db2/db/db_dup.c
db2/db/db_overflow.c
db2/db/db_pr.c
db2/db/db_rec.c
db2/db/db_ret.c
db2/db/db_thread.c
db2/db185/db185.c
db2/db_int.h
db2/hash/hash.c
db2/hash/hash.src
db2/hash/hash_auto.c
db2/hash/hash_dup.c
db2/hash/hash_page.c
db2/hash/hash_rec.c
db2/include/btree_auto.h
db2/include/btree_ext.h
db2/include/clib_ext.h
db2/include/common_ext.h
db2/include/db.h.src
db2/include/db_am.h
db2/include/db_auto.h
db2/include/db_cxx.h
db2/include/db_ext.h
db2/include/db_int.h.src
db2/include/hash.h
db2/include/hash_auto.h
db2/include/hash_ext.h
db2/include/lock.h
db2/include/lock_ext.h
db2/include/log.h
db2/include/log_ext.h
db2/include/mp.h
db2/include/mp_ext.h
db2/include/mutex_ext.h
db2/include/os_ext.h
db2/include/os_func.h [new file with mode: 0644]
db2/include/txn.h
db2/include/txn_ext.h
db2/lock/lock.c
db2/lock/lock_deadlock.c
db2/log/log.c
db2/log/log_archive.c
db2/log/log_auto.c
db2/log/log_findckp.c
db2/log/log_get.c
db2/log/log_put.c
db2/log/log_rec.c
db2/log/log_register.c
db2/mp/mp_bh.c
db2/mp/mp_fget.c
db2/mp/mp_fopen.c
db2/mp/mp_fput.c
db2/mp/mp_fset.c
db2/mp/mp_open.c
db2/mp/mp_pr.c
db2/mp/mp_region.c
db2/mp/mp_sync.c
db2/mutex/mutex.c
db2/os/db_os_abs.c [deleted file]
db2/os/db_os_dir.c [deleted file]
db2/os/db_os_lseek.c [deleted file]
db2/os/db_os_mmap.c [deleted file]
db2/os/os_abs.c [new file with mode: 0644]
db2/os/os_dir.c [new file with mode: 0644]
db2/os/os_fid.c [moved from db2/os/db_os_fid.c with 50% similarity]
db2/os/os_fsync.c [new file with mode: 0644]
db2/os/os_func.c [new file with mode: 0644]
db2/os/os_map.c [new file with mode: 0644]
db2/os/os_oflags.c [new file with mode: 0644]
db2/os/os_open.c [moved from db2/os/db_os_open.c with 58% similarity]
db2/os/os_rpath.c [new file with mode: 0644]
db2/os/os_rw.c [moved from db2/os/db_os_rw.c with 85% similarity]
db2/os/os_seek.c [new file with mode: 0644]
db2/os/os_sleep.c [moved from db2/os/db_os_sleep.c with 76% similarity]
db2/os/os_stat.c [moved from db2/os/db_os_stat.c with 72% similarity]
db2/os/os_unlink.c [moved from db2/os/db_os_unlink.c with 76% similarity]
db2/progs/db_deadlock/db_deadlock.c
db2/progs/db_dump/db_dump.c
db2/progs/db_load/db_load.c
db2/progs/db_recover/db_recover.c
db2/progs/db_stat/db_stat.c
db2/txn/txn.c
db2/txn/txn_auto.c
db2/txn/txn_rec.c
include/sys/stat.h
inet/protocols/routed.h
inet/protocols/talkd.h
inet/protocols/timed.h
io/fstat.c
io/fstat64.c
io/fts.c
io/ftw.c
io/ftwtest-sh
io/getdirname.c
io/lstat.c
io/lstat64.c
io/stat.c
io/stat64.c
libio/libio.h
libio/stdio.h
manual/arith.texi
manual/ctype.texi
manual/maint.texi
manual/pattern.texi
manual/process.texi
manual/stdio.texi
manual/terminal.texi
math/complex.h
math/libm-test.c
math/test-math.c
math/tgmath.h
nis/libnsl.map
nis/nis_call.c
nis/nis_callback.c
nis/nss_compat/compat-grp.c
nis/nss_compat/compat-pwd.c
nis/nss_compat/compat-spwd.c
nis/ypclnt.c
stdio-common/printf-parse.h
stdio-common/vfprintf.c
stdio-common/vfscanf.c
stdlib/exit.c
stdlib/strtod.c
stdlib/test-canon.c
sunrpc/rpc/pmap_clnt.h
sysdeps/generic/bits/errno.h
sysdeps/generic/setenv.c
sysdeps/i386/i586/memcpy.S [new file with mode: 0644]
sysdeps/i386/i586/mempcpy.S [new file with mode: 0644]
sysdeps/i386/i586/memset.S
sysdeps/libm-ieee754/e_asin.c
sysdeps/libm-ieee754/e_asinf.c
sysdeps/libm-ieee754/e_atan2l.c
sysdeps/libm-ieee754/e_remainderl.c
sysdeps/libm-ieee754/s_ceill.c
sysdeps/libm-ieee754/s_floorl.c
sysdeps/libm-ieee754/s_llrint.c
sysdeps/libm-ieee754/s_llrintf.c
sysdeps/libm-ieee754/s_llrintl.c
sysdeps/libm-ieee754/s_llround.c
sysdeps/libm-ieee754/s_llroundf.c
sysdeps/libm-ieee754/s_llroundl.c
sysdeps/libm-ieee754/s_lrint.c
sysdeps/libm-ieee754/s_lrintf.c
sysdeps/libm-ieee754/s_lrintl.c
sysdeps/libm-ieee754/s_lround.c
sysdeps/libm-ieee754/s_lroundf.c
sysdeps/libm-ieee754/s_lroundl.c
sysdeps/libm-ieee754/s_scalblnl.c
sysdeps/libm-ieee754/s_scalbnl.c
sysdeps/libm-ieee754/s_sincosl.c
sysdeps/libm-ieee754/s_tanl.c
sysdeps/m68k/fpu/s_llrint.c
sysdeps/m68k/fpu/s_llrintf.c [new file with mode: 0644]
sysdeps/m68k/fpu/s_llrintl.c [new file with mode: 0644]
sysdeps/mach/hurd/bits/errno.h
sysdeps/posix/getcwd.c
sysdeps/posix/system.c
sysdeps/standalone/bits/errno.h
sysdeps/unix/sysv/linux/Dist
sysdeps/unix/sysv/linux/Makefile
sysdeps/unix/sysv/linux/alpha/xstatconv.c
sysdeps/unix/sysv/linux/bits/errno.h
sysdeps/unix/sysv/linux/xstatconv.c
sysdeps/wordsize-32/inttypes.h
sysdeps/wordsize-64/inttypes.h
test-installation.pl [new file with mode: 0644]
time/Makefile
time/mktime.c
time/strftime.c
time/strfxtime.c [moved from sysdeps/unix/sysv/i386/i686/time.S with 54% similarity]
time/time.h
wcsmbs/wchar.h

index f420373b2fba2d4fff516fcdcab12dd9cdc5f016..877ae6c4708ff6a04cd4d2214d9f6c7566375a38 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,350 @@
+1997-11-11 21:30  Ulrich Drepper  <drepper@cygnus.com>
+
+       * include/sys/stat.h: Define stat, fstat, lstat and *64 variants
+       as macros so the the library compiles correctly even without
+       optimization.
+       * io/fstat.c: Undef fstat.
+       * io/fstat64.c: Undef fstat64
+       * io/lstat.c: Undef lstat.
+       * io/lstat64.c: Undef lstat64
+       * io/stat.c: Undef stat.
+       * io/stat64.c: Undef stat64
+       * io/fts.c: Include <include/sys/stat.h> to get macro definitions.
+       * io/ftw.c: Likewise.
+       * io/getdirname.c: Likewise.
+
+       * Makefile (install): Run test-installation.pl if possible.
+
+       * db2/Makefile: Update from db-2.3.12.
+       * db2/db.h: Likewise.
+       * db2/db_int.h: Likewise.
+       * db2/btree/bt_cursor.c: Likewise.
+       * db2/btree/bt_delete.c: Likewise.
+       * db2/btree/bt_open.c: Likewise.
+       * db2/btree/bt_put.c: Likewise.
+       * db2/btree/bt_rec.c: Likewise.
+       * db2/btree/bt_recno.c: Likewise.
+       * db2/btree/bt_search.c: Likewise.
+       * db2/btree/bt_split.c: Likewise.
+       * db2/btree/bt_stat.c: Likewise.
+       * db2/btree/btree.src: Likewise.
+       * db2/btree/btree_auto.c: Likewise.
+       * db2/btree/bt_cursor.c: Likewise.
+       * db2/btree/bt_delete.c: Likewise.
+       * db2/btree/bt_open.c: Likewise.
+       * db2/btree/bt_put.c: Likewise.
+       * db2/btree/bt_rec.c: Likewise.
+       * db2/btree/bt_recno.c: Likewise.
+       * db2/btree/bt_search.c: Likewise.
+       * db2/btree/bt_split.c: Likewise.
+       * db2/btree/bt_stat.c: Likewise.
+       * db2/btree/btree.src: Likewise.
+       * db2/btree/btree_auto.c: Likewise.
+       * db2/common/db_appinit.c: Likewise.
+       * db2/common/db_apprec.c: Likewise.
+       * db2/common/db_byteorder.c: Likewise.
+       * db2/common/db_region.c: Likewise.
+       * db2/db/db.c: Likewise
+       * db2/db/db.src: Likewise
+       * db2/db/db_auto.c: Likewise
+       * db2/db/db_dispatch.c: Likewise
+       * db2/db/db_dup.c: Likewise
+       * db2/db/db_overflow.c: Likewise
+       * db2/db/db_pr.c: Likewise
+       * db2/db/db_rec.c: Likewise
+       * db2/db/db_ret.c: Likewise
+       * db2/db/db_thread.c: Likewise
+       * db2/db185/db185.c: Likewise.
+       * db2/hash/hash.c: Likewise.
+       * db2/hash/hash.src: Likewise.
+       * db2/hash/hash_auto.c: Likewise.
+       * db2/hash/hash_dup.c: Likewise.
+       * db2/hash/hash_page.c: Likewise.
+       * db2/hash/hash_rec.c: Likewise.
+       * db2/include/btree_auto.h: Likewise.
+       * db2/include/btree_ext.h: Likewise.
+       * db2/include/clib_ext.h: Likewise.
+       * db2/include/common_ext.h: Likewise.
+       * db2/include/db.h.src: Likewise.
+       * db2/include/db_am.h: Likewise.
+       * db2/include/db_auto.h: Likewise.
+       * db2/include/db_cxx.h: Likewise.
+       * db2/include/db_ext.h: Likewise.
+       * db2/include/db_int.h.src: Likewise.
+       * db2/include/hash.h: Likewise.
+       * db2/include/hash_auto.h: Likewise.
+       * db2/include/hash_ext.h: Likewise.
+       * db2/include/lock.h: Likewise.
+       * db2/include/lock_ext.h: Likewise.
+       * db2/include/log.h: Likewise.
+       * db2/include/log_ext.h: Likewise.
+       * db2/include/mp.h: Likewise.
+       * db2/include/mp_ext.h: Likewise.
+       * db2/include/mutex_ext.h: Likewise.
+       * db2/include/os_ext.h: Likewise.
+       * db2/include/os_func.h: Likewise.
+       * db2/include/txn.h: Likewise.
+       * db2/include/txn_ext.h: Likewise.
+       * db2/lock/lock.c: Likewise.
+       * db2/lock/lock_deadlock.c: Likewise.
+       * db2/log/log.c: Likewise.
+       * db2/log/log_archive.c: Likewise.
+       * db2/log/log_auto.c: Likewise.
+       * db2/log/log_findckp.c: Likewise.
+       * db2/log/log_get.c: Likewise.
+       * db2/log/log_put.c: Likewise.
+       * db2/log/log_rec.c: Likewise.
+       * db2/log/log_register.c: Likewise.
+       * db2/mp/mp_bh.c: Likewise.
+       * db2/mp/mp_fget.c: Likewise.
+       * db2/mp/mp_fopen.c: Likewise.
+       * db2/mp/mp_fput.c: Likewise.
+       * db2/mp/mp_fset.c: Likewise.
+       * db2/mp/mp_open.c: Likewise.
+       * db2/mp/mp_pr.c: Likewise.
+       * db2/mp/mp_region.c: Likewise.
+       * db2/mp/mp_sync.c: Likewise.
+       * db2/mutex/mutex.c: Likewise.
+       * db2/os/os_abs.c: Likewise.
+       * db2/os/os_dir.c: Likewise.
+       * db2/os/os_fid.c: Likewise.
+       * db2/os/os_fsync.c: Likewise.
+       * db2/os/os_func.c: Likewise.
+       * db2/os/os_map.c: Likewise.
+       * db2/os/os_oflags.c: Likewise.
+       * db2/os/os_open.c: Likewise.
+       * db2/os/os_rpath.c: Likewise.
+       * db2/os/os_rw.c: Likewise.
+       * db2/os/os_seek.c: Likewise.
+       * db2/os/os_sleep.c: Likewise.
+       * db2/os/os_stat.c: Likewise.
+       * db2/os/os_unlink.c: Likewise.
+       * db2/progs/db_deadlock/db_deadlock.c: Likewise.
+       * db2/progs/db_dump/db_dump.c: Likewise.
+       * db2/progs/db_load/db_load.c: Likewise.
+       * db2/progs/db_recover/db_recover.c: Likewise.
+       * db2/progs/db_stat/db_stat.c: Likewise.
+       * db2/txn/txn.c: Likewise.
+       * db2/txn/txn_auto.c: Likewise.
+       * db2/txn/txn_rec.c: Likewise.
+       * db2/os/db_os_abs.c: Removed.
+       * db2/os/db_os_dir.c: Removed.
+       * db2/os/db_os_fid.c: Removed.
+       * db2/os/db_os_lseek.c: Removed.
+       * db2/os/db_os_mmap.c: Removed.
+       * db2/os/db_os_open.c: Removed.
+       * db2/os/db_os_rw.c: Removed.
+       * db2/os/db_os_sleep.c: Removed.
+       * db2/os/db_os_stat.c: Removed.
+       * db2/os/db_os_unlink.c: Removed.
+
+       * libio/stdio.h (fopen): Add __restrict to parameters.
+
+       * manual/process.texi (system): Describe behaviour for NULL argument.
+
+       * stdio-common/printf-parse.h: Parse hh modifier.
+       * stdio-common/vfprintf.c: Handle hh modifier.
+       * stdio-common/vfscanf.c: Likewise.
+       * manual/stdio.texi: Describe hh modifier for scanf/printf.
+
+       * math/complex.h: Don't define _Imaginary_I, but instead _Complex_I.
+       gcc does no yet know the `imaginary' keyword.
+
+       * math/test-math.c: Add little test for know gcc bug.
+
+       * math/tgmath.h: Make complex versions of log10() only available
+       if __USE_GNU.
+
+       * stdlib/test-canon.c: Fix typo.
+
+       * sysdeps/generic/setenv.c: Avoid compilation warnings.
+       Reported by Jim Meyering.
+
+       * sysdeps/generic/bits/errno.h: EILSEQ is an ISO C error number.
+       * sysdeps/mach/hurd/bits/errno.h: Likewise.
+       * sysdeps/standalone/bits/errno.h: Likewise.
+       * sysdeps/unix/sysv/linux/bits/errno.h: Likewise.
+
+       * sysdeps/i386/i586/memcpy.S: New file.
+       * sysdeps/i386/i586/mempcpy.S: New file.
+
+       * sysdeps/i386/i586/memset.S: Fix typo.
+
+       * sysdeps/posix/getcwd.c: Define HAVE_MEMPCPY for _LIBC.  Add casts.
+
+       * sysdeps/posix/system.c: Add comment to explain code.
+
+       * sysdeps/wordsize-32/inttypes.h: Include <stddef.h> for wchar_t.
+       Define PTRDIFF_{MIN,MAX}, SIG_ATOMIC_{MIN,MAX}, SIZE_MAX,
+       WCHAR_{MIN,MAX}, WINT_{MIN,MAX}.
+       Define wcstoimax, wcstoumax.
+       * sysdeps/wordsize-64/inttypes.h: Likewise.
+
+       * wcsmbs/wchar.h: Define WCHAR_{MIN,MAX} if not already defined.
+       Declare __wcsto{l,ul,ll,ull}_internal only if not already done.
+
+       * time/Makefile (routines): Add strfxtime.
+       * time/strftime.c: Implement %F and %f format.
+       * time/strfxtime.c: New file.
+       * time/time.h: Define new types and symbols from ISO C 9X.
+
+       * time/mktime.c: Little comment correction.
+
+1997-11-10  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
+
+       * sysdeps/libm-ieee754/s_sincosl.c: Fix typo.
+
+       * sysdeps/libm-ieee754/s_tanl.c: Fix typo.
+
+       * sysdeps/libm-ieee754/s_floorl.c: Correct typos.
+
+       * sysdeps/libm-ieee754/e_remainderl.c: Replace
+       EXTRACT_LDOUBLE_WORDS by GET_LDOUBLE_WORDS.
+
+       * sysdeps/libm-ieee754/e_atan2l.c: Replace EXTRACT_LDOUBLE_WORDS
+       by GET_LDOUBLE_WORDS.
+
+       * sysdeps/libm-ieee754/s_scalbnl.c: Replace ";" by "," for correct
+       variable declaration.
+       * sysdeps/libm-ieee754/s_scalblnl.c: Likewise.
+
+       * sysdeps/libm-ieee754/s_lrint.c (__lrint): Correct function.
+
+       * math/libm-test.c (sqrt_test): Add test for sqrt (0.25).
+       (asin_test): Add more test.
+
+1997-11-10 23:34  Ulrich Drepper  <drepper@cygnus.com>
+
+       * sysdeps/libm-ieee754/e_asin.c: Add braces to make code clearer
+       and to not confuse the poor compiler.
+       * sysdeps/libm-ieee754/e_asinf.c: Likewise.
+       Reported by vertex@cagent.com.
+
+1997-11-09  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * elf/dl-lookup.c (do_lookup): Don't accept the base version if we
+       require a specific one.
+
+       * libio/oldfreopen.c: Bind old symbols to version GLIBC_2.0.
+       * libio/oldiofopen.c: Likewise.
+       * libio/oldstdfiles.c: Likewise.
+       * libc.map: Export them.
+
+1997-11-10 07:40  H.J. Lu  <hjl@gnu.ai.mit.edu>
+
+       * stdlib/exit.c (exit): Handle recursive calls to exit ().
+
+1997-11-09  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * sysdeps/m68k/fpu/s_llrint.c: Fixed to take double argument
+       instead of long double.
+       * sysdeps/m68k/fpu/s_llrintf.c: New file.
+       * sysdeps/m68k/fpu/s_llrintl.c: New file.
+
+       * sysdeps/libm-ieee754/s_llrint.c: Make compilable and fix
+       overflow condition.
+       * sysdeps/libm-ieee754/s_llrintf.c: Fix overflow condition.
+       * sysdeps/libm-ieee754/s_llrintl.c: Likewise.
+       * sysdeps/libm-ieee754/s_llround.c: Likewise.
+       * sysdeps/libm-ieee754/s_llroundf.c: Likewise.
+       * sysdeps/libm-ieee754/s_llroundl.c: Likewise.
+       * sysdeps/libm-ieee754/s_lrint.c: Likewise.
+       * sysdeps/libm-ieee754/s_lrintf.c: Likewise.
+       * sysdeps/libm-ieee754/s_lrintl.c: Likewise.
+       * sysdeps/libm-ieee754/s_lround.c: Likewise.
+       * sysdeps/libm-ieee754/s_lroundf.c: Likewise.
+       * sysdeps/libm-ieee754/s_lroundl.c: Likewise.
+
+       * math/libm-test.c: Test all three variants of lrint and llrint.
+       Fix typos in lround and llround tests.  Add tests for boundary
+       cases for lrint and llround.
+
+1997-11-08  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * manual/arith.texi: Misc doc fixes.
+       * manual/ctype.texi: Likewise.
+       * manual/pattern.texi: Likewise.
+       * manual/terminal.texi: Likewise.
+
+1997-11-08  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * sysdeps/unix/sysv/linux/xstatconv.c: Use struct assignment
+       instead of memcpy to let the compiler use whatever it regards as
+       optimal.
+       * sysdeps/unix/sysv/linux/alpha/xstatconv.c: Likewise.
+
+1997-11-08  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * sysdeps/unix/sysv/linux/Makefile (sysdep_headers)
+       [$(subdir)=misc]: Add sys/prctl.h.
+       * sysdeps/unix/sysv/linux/Dist: Distribute it.
+
+1997-11-08  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * io/ftwtest-sh: Don't use the unknown which command, instead try
+       pwd as /bin/pwd and /usr/bin/pwd.
+
+1997-11-08  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * manual/maint.texi (Tools for Installation): Don't recommend
+       broken version 3.76.1 of make.
+       (Porting): Fix wording.
+
+1997-11-06 06:13  H.J. Lu  <hjl@gnu.ai.mit.edu>
+
+       * config.make.in (build-pic-default): New, defined with
+       pic_default.
+
+       * configure.in (pic_default): New, set to yes if PIC is
+       default.
+
+       * Makeconfig (CPPFLAGS-.o, CPPFLAGS-.op, CPPFLAGS-.og,
+       CPPFLAGS-.ob): Add -DPIC if $(build-pic-default) is yes.
+
+1997-11-09 18:15  Ulrich Drepper  <drepper@cygnus.com>
+
+       * Makerules (libc.so): Fix typo.
+
+       * csu/Makefile (CFLAGS-initfini.s): Correctly fix moving function
+       definition.  Patch by Zack Weinberg <zack@rabi.phys.columbia.edu>.
+
+       * stdlib/strtod.c: Handle numbers like 0.0e10000 correctly which
+       produce ±0.0.  Reported by Joe Keane <jgk@jgk.org>.
+
+       * sysdeps/libm-ieee754/s_ceill.c: Fix typos.
+       * sysdeps/libm-ieee754/s_llrint.c: Correct code, it never worked.
+
+1997-11-06 07:00  H.J. Lu  <hjl@gnu.ai.mit.edu>
+
+       * sysdeps/unix/sysv/i386/i686/time.S: Removed.
+
+1997-11-08 14:07  Thorsten Kukuk  <kukuk@vt.uni-paderborn.de>
+
+       * nis/libnsl.map: Add __do_niscall2 for nis_cachemgr.
+
+       * nis/nis_call.c: Set UDP resend timeout correct.
+
+       * nis/nss_compat/compat-grp.c: Rewritten to make it faster.
+       * nis/nss_compat/compat-pwd.c: Likewise.
+       * nis/nss_compat/compat-spwd.c: Likewise.
+       * nis/ypclnt.c: Fix UDP resend timeout, fix yp_bind/do_ypcall
+       interaction.
+
+       * inet/protocols/routed.h: Include sys/socket.h.
+       * inet/protocols/talkd.h: Likewise.
+       * inet/protocols/timed.h: Include rpc/types.h.
+       * sunrpc/rpc/pmap_clnt.h: Include rpc/clnt.h.
+
+1997-11-06 01:39  Ulrich Drepper  <drepper@cygnus.com>
+
+       * Makerules (libc.so): Add missing closing brace.
+
+1997-11-05  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * libio.h (__P): Name its arg `p' instead of `params'.
+       This was added solely to work around problems with
+       the definition of __P in the Solaris math.h header.
+
 1997-11-06 00:06  Ulrich Drepper  <drepper@cygnus.com>
 
        * argp/argp-help.c: Optimize a bit by using mempcpy.
index 45e792fbc74d0eaa7636cd626972bed546d72659..2eb1ce19752c2eba0beba04b143ef27edb0eca84 100644 (file)
@@ -529,6 +529,12 @@ LDFLAGS    := -g
 endif
 
 
+# If everything is compiled with -fPIC (implicitly) we must tell this by
+# defining the PIC symbol.
+ifeq (yes,$(build-pic-default))
+pic-default = -DPIC
+endif
+
 # Enable object files for different versions of the library.
 # Various things use $(object-suffixes) to know what all to make.
 # The compilation rules use $(CPPFLAGS-${SUFFIX}) and $(CFLAGS-${SUFFIX})
@@ -537,6 +543,7 @@ libtypes = $(foreach o,$(object-suffixes),$(libtype$o))
 all-object-suffixes := .o .os .op .og .ob
 object-suffixes :=
 ifeq (yes,$(build-static))
+CPPFLAGS-.o = $(pic-default)
 libtype.o := lib%.a
 object-suffixes += .o
 endif
@@ -554,7 +561,7 @@ ifeq (yes,$(build-profile))
 # Under --enable-profile, we will build a static library of profiled objects.
 # The profiled object files are named foo.op.
 object-suffixes += .op
-CPPFLAGS-.op = -DPROF
+CPPFLAGS-.op = -DPROF $(pic-default)
 CFLAGS-.op = -pg
 libtype.op = lib%_p.a
 endif
@@ -563,6 +570,7 @@ ifeq (yes,$(build-omitfp))
 # debugging information using -fomit-frame-pointer, and build an extra
 # library with debugging information.  The debuggable objects are named foo.og.
 object-suffixes += .og
+CPPFLAGS-.og = $(pic-default)
 CFLAGS-.og = -g
 CFLAGS-.o = -g0 -O99 -fomit-frame-pointer -D__USE_STRING_INLINES
 CFLAGS-.os += $(CFLAGS-.o)
@@ -572,7 +580,7 @@ ifeq (yes,$(build-bounded))
 # Under --enable-bounded, we build the library with `-fbounded-pointers -g'
 # to runtime bounds checking.  The bounded-pointer objects are named foo.ob.
 object-suffixes += .ob
-CPPFLAGS-.ob = -DBOUNDED_POINTERS
+CPPFLAGS-.ob = -DBOUNDED_POINTERS $(pic-default)
 CFLAGS-.ob = -g -fbounded-pointers
 libtype.ob = lib%_b.a
 endif
index 22cea63624a0b86dd1b6d9c7e343af4b81280460..0d94985e39eb6da4a19a146911fc995474809d3d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -124,6 +124,13 @@ ifeq (yes,$(build-shared))
 install:
        -test ! -x $(common-objpfx)elf/ldconfig || \
          $(common-objpfx)elf/ldconfig -d $(inst_slibdir) $(inst_libdir)
+ifneq (no,$(PERL))
+ifeq (/usr,$(prefix))
+ifeq (,$(install_root))
+       CC=$(CC) $(PERL) test-installation.pl $(common-objpfx)
+endif
+endif
+endif
 endif
 endif
 
index 2ba27c4bb25e1e7bcde3674988bf47923a4c00c3..b9c89a5a3e217110bb6ed94448f50b2ad48b2434 100644 (file)
--- a/Makerules
+++ b/Makerules
@@ -692,7 +692,7 @@ $(inst_libdir)/libc.so: $(common-objpfx)libc.so$(libc.so-version) \
         echo '   dependencies of $(<F) to find $(rtld-installed-name).  */';\
         echo 'GROUP ( $(slibdir)/libc.so$(libc.so-version)' \
              '$(slibdir)/$(rtld-installed-name)' \
-             '$(libdir)/lib$(libc-name).a' \
+             '$(libdir)/lib$(libc-name).a )' \
              ) > $@.new
        mv -f $@.new $@
 
index 622c2c9de446e501a21a186cfcff8ef924c246b0..d1cb464b41733e3c06fb470435d670e2eadce6f8 100644 (file)
@@ -23,6 +23,7 @@
 #define        __Emath_defined 1
 
 # define EDOM  XXX     <--- fill in what is actually needed
+# define EILSEQ        XXX     <--- fill in what is actually needed
 # define ERANGE        XXX     <--- fill in what is actually needed
 #endif
 
index ae4d898dd2a135336d6e5116d6c27033c302b54e..6fefeaade30b2c18ea92b6e3dc5062434ab3926c 100644 (file)
@@ -39,6 +39,7 @@ gnu-as = @gnu_as@
 gnu-ld = @gnu_ld@
 build-static = @static@
 build-shared = @shared@
+build-pic-default= @pic_default@
 build-profile = @profile@
 build-omitfp = @omitfp@
 build-bounded = @bounded@
index 2ef2feef14ae8805f170f3928696981cfdd12926..c9613d27b1b72f0b56f16de37372bccb2f7bfe4f 100755 (executable)
--- a/configure
+++ b/configure
@@ -2441,6 +2441,27 @@ if test $shared = default; then
   fi
 fi
 
+echo $ac_n "checking whether -fPIC is default""... $ac_c" 1>&6
+echo "configure:2446: checking whether -fPIC is default" >&5
+if eval "test \"`echo '$''{'pic_default'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  pic_default=yes
+cat > conftest.c <<EOF
+#if defined(__PIC__) || defined(__pic__) || defined(PIC) || defined(pic)
+# error PIC is default.
+#endif
+EOF
+if eval "${CC-cc} -S conftest.c 2>&5 1>&5"; then
+  pic_default=no
+fi
+rm -f conftest.*
+fi
+
+echo "$ac_t""$pic_default" 1>&6
+
+
+
 
 
 
@@ -2650,6 +2671,7 @@ s%@gnu_as@%$gnu_as%g
 s%@elf@%$elf%g
 s%@static@%$static%g
 s%@shared@%$shared%g
+s%@pic_default@%$pic_default%g
 s%@profile@%$profile%g
 s%@omitfp@%$omitfp%g
 s%@bounded@%$bounded%g
index 3b3be45c333638223a110cdd7de5f2490a44850f..bdfe63c06a82c97c75f6d38e24b6d59b40357b38 100644 (file)
@@ -971,6 +971,20 @@ if test $shared = default; then
     shared=no
   fi
 fi
+
+AC_CACHE_CHECK([whether -fPIC is default], pic_default,
+[pic_default=yes
+cat > conftest.c <<EOF
+#if defined(__PIC__) || defined(__pic__) || defined(PIC) || defined(pic)
+# error PIC is default.
+#endif
+EOF
+if eval "${CC-cc} -S conftest.c 2>&AC_FD_CC 1>&AC_FD_CC"; then
+  pic_default=no
+fi
+rm -f conftest.*])
+AC_SUBST(pic_default)
+
 AC_SUBST(profile)
 AC_SUBST(omitfp)
 AC_SUBST(bounded)
index bc66f674bc1be6b42c93042e5dd067c1bf8b4831..cb9e6eb6aa4528db4918b6d3b186093525365d05 100644 (file)
@@ -64,7 +64,7 @@ omit-deps += $(crtstuff)
 $(objpfx)crt%.o: $(objpfx)crt%.S $(objpfx)defs.h
        $(compile.S) -g0 $(ASFLAGS-.os) -o $@
 
-CFLAGS-initfini.s = -O0 -g0 -fPIC
+CFLAGS-initfini.s = -g0 -fPIC -fno-inline-functions
 
 $(objpfx)initfini.s: initfini.c
        $(compile.c) -S $(CFLAGS-initfini.s) -finhibit-size-directive \
index e6b35aa51bd840aad9d2ab6b5ddb7136b76f7d31..8e5cea7b178b11363248f5f7408e66a51f982064 100644 (file)
@@ -58,8 +58,8 @@ libdb-routines := bt_close bt_compare bt_conv bt_cursor bt_delete \
        bt_split bt_stat btree_auto db db_appinit db_apprec \
        db_auto \
        db_byteorder db_conv db_dispatch db_dup db_err db_log2 \
-       db_os_abs db_os_dir db_os_fid db_os_lseek db_os_mmap \
-       db_os_open db_os_rw db_os_sleep db_os_stat db_os_unlink \
+       os_abs os_dir os_fid os_fsync os_func os_map os_oflags \
+       os_open os_rpath os_rw os_seek os_sleep os_stat os_unlink \
        db_overflow db_pr db_rec db_region db_ret db_salloc \
        db_shash db_thread hash hash_auto hash_conv hash_debug \
        hash_dup hash_func hash_page hash_rec hash_stat lock \
index a1266bcd3c66f56c64ca9ec78fdff4a7d661aa77..e5f3faeb70e18496e82ac70e2dd42798c889c5f9 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_cursor.c  10.33 (Sleepycat) 9/24/97";
+static const char sccsid[] = "@(#)bt_cursor.c  10.35 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -62,10 +62,10 @@ __bam_cursor(dbp, txn, dbcp)
 
        DEBUG_LWRITE(dbp, txn, "bam_cursor", NULL, NULL, 0);
 
-       if ((dbc = (DBC *)calloc(1, sizeof(DBC))) == NULL)
+       if ((dbc = (DBC *)__db_calloc(1, sizeof(DBC))) == NULL)
                return (ENOMEM);
-       if ((cp = (CURSOR *)calloc(1, sizeof(CURSOR))) == NULL) {
-               free(dbc);
+       if ((cp = (CURSOR *)__db_calloc(1, sizeof(CURSOR))) == NULL) {
+               __db_free(dbc);
                return (ENOMEM);
        }
 
@@ -474,7 +474,7 @@ __bam_c_rget(dbp, cp, key, data, flags)
        __bam_stkrel(dbp);
 
 err:   (void)memp_fput(dbp->mpf, cp->page, 0);
-       free(dbt.data);
+       __db_free(dbt.data);
        return (ret);
 }
 
@@ -1422,7 +1422,7 @@ __bam_c_physdel(dbp, cp, h)
        DB_LOCK lock;
        db_indx_t indx;
        db_pgno_t pgno, next_pgno, prev_pgno;
-       int local, ret;
+       int local, normal, ret;
 
        t = dbp->internal;
        ret = 0;
@@ -1457,51 +1457,65 @@ __bam_c_physdel(dbp, cp, h)
                local = 0;
 
        /*
-        * If we're deleting a duplicate entry, call the common code to do
-        * the work.
+        * If we're deleting a duplicate entry and there are other duplicate
+        * entries remaining, call the common code to do the work and fix up
+        * the parent page as necessary.  Otherwise, do a normal btree delete.
+        *
+        * There are 5 possible cases:
+        *
+        * 1. It's not a duplicate item: do a normal btree delete.
+        * 2. It's a duplicate item:
+        *      2a: We delete an item from a page of duplicates, but there are
+        *          more items on the page.
+        *      2b: We delete the last item from a page of duplicates, deleting
+        *          the last duplicate.
+        *      2c: We delete the last item from a page of duplicates, but there
+        *          is a previous page of duplicates.
+        *      2d: We delete the last item from a page of duplicates, but there
+        *          is a following page of duplicates.
+        *
+        * In the case of:
+        *
+        *  1: There's nothing further to do.
+        * 2a: There's nothing further to do.
+        * 2b: Do the normal btree delete instead of a duplicate delete, as
+        *     that deletes both the duplicate chain and the parent page's
+        *     entry.
+        * 2c: There's nothing further to do.
+        * 2d: Delete the duplicate, and update the parent page's entry.
         */
        if (TYPE(h) == P_DUPLICATE) {
                pgno = PGNO(h);
                prev_pgno = PREV_PGNO(h);
                next_pgno = NEXT_PGNO(h);
-               if ((ret = __db_drem(dbp, &h, indx, __bam_free)) != 0)
-                       goto err;
 
-               /*
-                * There are 4 cases:
-                *
-                * 1. We removed an item on a page, but there are more items
-                *    on the page.
-                * 2. We removed the last item on a page, removing the last
-                *    duplicate.
-                * 3. We removed the last item on a page, but there is a
-                *    following page of duplicates.
-                * 4. We removed the last item on a page, but there is a
-                *    previous page of duplicates.
-                *
-                * In case 1, h != NULL, h->pgno == pgno
-                * In case 2, h == NULL,
-                *    prev_pgno == PGNO_INVALID, next_pgno == PGNO_INVALID
-                * In case 3, h != NULL, next_pgno != PGNO_INVALID
-                * In case 4, h == NULL, prev_pgno != PGNO_INVALID
-                *
-                * In case 1, there's nothing else to do.
-                * In case 2, remove the entry from the parent page.
-                * In case 3 or 4, if the deleted page was the first in a chain
-                *    of duplicate pages, update the parent page's entry.
-                *
-                * Test:
-                *      If there were previous pages of duplicates or we didn't
-                *      empty the current page of duplicates, we don't need to
-                *      touch the parent page.
-                */
-               if (prev_pgno != PGNO_INVALID || (h != NULL && pgno == h->pgno))
-                       goto done;
+               if (NUM_ENT(h) == 1 &&
+                   prev_pgno == PGNO_INVALID && next_pgno == PGNO_INVALID)
+                       normal = 1;
+               else {
+                       normal = 0;
 
-               /*
-                * Release any page we're holding and the lock on the deleted
-                * page.
-                */
+                       /* Delete the duplicate. */
+                       if ((ret = __db_drem(dbp, &h, indx, __bam_free)) != 0)
+                               goto err;
+
+                       /*
+                        * 2a: h != NULL, h->pgno == pgno
+                        * 2b: We don't reach this clause, as the above test
+                        *     was true.
+                        * 2c: h == NULL, prev_pgno != PGNO_INVALID
+                        * 2d: h != NULL, next_pgno != PGNO_INVALID
+                        *
+                        * Test for 2a and 2c: if we didn't empty the current
+                        * page or there was a previous page of duplicates, we
+                        * don't need to touch the parent page.
+                        */
+                       if ((h != NULL && pgno == h->pgno) ||
+                           prev_pgno != PGNO_INVALID)
+                               goto done;
+               }
+
+               /* Release any page we're holding and its lock. */
                if (local) {
                        if (h != NULL)
                                (void)memp_fput(dbp->mpf, h, 0);
@@ -1519,37 +1533,33 @@ __bam_c_physdel(dbp, cp, h)
                }
                local = 1;
 
-               /*
-                * If we deleted the last duplicate, we can fall out and do a
-                * normal btree delete in the context of the parent page.  If
-                * not, we have to update the parent's page.
-                */
+               /* Switch to the parent page's entry. */
                indx = cp->indx;
-               if (next_pgno != PGNO_INVALID) {
-                       /*
-                        * Copy, delete, update and re-insert the parent page's
-                        * entry.
-                        */
-                       bo = *GET_BOVERFLOW(h, indx);
-                       (void)__db_ditem(dbp, h, indx, BOVERFLOW_SIZE);
-                       bo.pgno = next_pgno;
-                       memset(&dbt, 0, sizeof(dbt));
-                       dbt.data = &bo;
-                       dbt.size = BOVERFLOW_SIZE;
-                       (void)__db_pitem(dbp,
-                           h, indx, BOVERFLOW_SIZE, &dbt, NULL);
-
-                       /* Discard the parent page. */
-                       (void)memp_fput(dbp->mpf, h, 0);
-                       (void)__BT_TLPUT(dbp, lock);
-                       local = 0;
+               if (normal)
+                       goto btd;
 
-                       goto done;
-               }
+               /*
+                * Copy, delete, update, add-back the parent page's data entry.
+                *
+                * XXX
+                * This may be a performance/logging problem.  We should add a
+                * log message which simply logs/updates a random set of bytes
+                * on a page, and use it instead of doing a delete/add pair.
+                */
+               indx += O_INDX;
+               bo = *GET_BOVERFLOW(h, indx);
+               (void)__db_ditem(dbp, h, indx, BOVERFLOW_SIZE);
+               bo.pgno = next_pgno;
+               memset(&dbt, 0, sizeof(dbt));
+               dbt.data = &bo;
+               dbt.size = BOVERFLOW_SIZE;
+               (void)__db_pitem(dbp, h, indx, BOVERFLOW_SIZE, &dbt, NULL);
+               (void)memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY);
+               goto done;
        }
 
        /* Otherwise, do a normal btree delete. */
-       if ((ret = __bam_ditem(dbp, h, indx)) != 0)
+btd:   if ((ret = __bam_ditem(dbp, h, indx)) != 0)
                goto err;
        if ((ret = __bam_ditem(dbp, h, indx)) != 0)
                goto err;
@@ -1584,7 +1594,7 @@ __bam_c_physdel(dbp, cp, h)
                }
 
                ret = __bam_dpage(dbp, &dbt);
-               free(dbt.data);
+               __db_free(dbt.data);
        }
 
 err:
index 98929540e4f37bd1e9509495fedfd2cb82543136..9593d0109c42297721c619c0e5fce4b5f25afdca 100644 (file)
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_delete.c  10.21 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)bt_delete.c  10.22 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -266,9 +266,10 @@ __bam_ditem(dbp, h, indx)
                case B_DUPLICATE:
                case B_OVERFLOW:
                        nbytes = BINTERNAL_SIZE(bi->len);
+                       bo = (BOVERFLOW *)bi->data;
                        goto offpage;
                case B_KEYDATA:
-                       nbytes = BKEYDATA_SIZE(bi->len);
+                       nbytes = BINTERNAL_SIZE(bi->len);
                        break;
                default:
                        return (__db_pgfmt(dbp, h->pgno));
@@ -289,7 +290,7 @@ __bam_ditem(dbp, h, indx)
                        if (indx > 0 && h->inp[indx] == h->inp[indx - P_INDX])
                                return (__bam_adjindx(dbp,
                                    h, indx, indx - P_INDX, 0));
-                       if (indx < (u_int32_t)(NUM_ENT(h) - P_INDX) &&
+                       if (indx + P_INDX < (u_int32_t)NUM_ENT(h) &&
                            h->inp[indx] == h->inp[indx + P_INDX])
                                return (__bam_adjindx(dbp,
                                    h, indx, indx + O_INDX, 0));
@@ -301,9 +302,9 @@ __bam_ditem(dbp, h, indx)
                case B_DUPLICATE:
                case B_OVERFLOW:
                        nbytes = BOVERFLOW_SIZE;
+                       bo = GET_BOVERFLOW(h, indx);
 
 offpage:               /* Delete duplicate/offpage chains. */
-                       bo = GET_BOVERFLOW(h, indx);
                        if (B_TYPE(bo->type) == B_DUPLICATE) {
                                if ((ret =
                                    __db_ddup(dbp, bo->pgno, __bam_free)) != 0)
@@ -523,7 +524,7 @@ __bam_dpages(dbp, t)
 
        /*
         * If we deleted the next-to-last item from the root page, the tree
-        * has collapsed a level.  Try and write lock the remaining root + 1
+        * can collapse a level.  Try and write lock the remaining root + 1
         * page and copy it onto the root page.  If we can't get the lock,
         * that's okay, the tree just stays a level deeper than we'd like.
         */
@@ -546,8 +547,8 @@ __bam_dpages(dbp, t)
                        b.data = P_ENTRY(epg->page, 0);
                        b.size = BINTERNAL_SIZE(((BINTERNAL *)b.data)->len);
                        __bam_rsplit_log(dbp->dbenv->lg_info, dbp->txn,
-                          &h->lsn, 0, dbp->log_fileid, h->pgno, &a, &b,
-                          &epg->page->lsn);
+                          &h->lsn, 0, dbp->log_fileid, h->pgno, &a,
+                          RE_NREC(epg->page), &b, &epg->page->lsn);
                }
 
                /*
@@ -565,15 +566,19 @@ __bam_dpages(dbp, t)
                if (TYPE(h) == P_IRECNO ||
                    (TYPE(h) == P_IBTREE && F_ISSET(dbp, DB_BT_RECNUM)))
                        RE_NREC_SET(epg->page, rcnt);
+               (void)memp_fset(dbp->mpf, epg->page, DB_MPOOL_DIRTY);
 
-               /* Free the last page in that level of the btree. */
-               ++t->lstat.bt_freed;
+               /*
+                * Free the last page in that level of the btree and discard
+                * the lock.  (The call to __bam_free discards our reference
+                * to the page.)
+                */
                (void)__bam_free(dbp, h);
+               (void)__BT_TLPUT(dbp, lock);
+               ++t->lstat.bt_freed;
 
                /* Adjust the cursors. */
                __bam_ca_move(dbp, t, h->pgno, PGNO_ROOT);
-
-               (void)__BT_TLPUT(dbp, lock);
        }
 
        /* Release the top page in the subtree. */
index 354888c6c2fb0c502bd49f965f71dbcbeaede178..2361f69a3e389cfc9f3765f24431eca49423178e 100644 (file)
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_open.c    10.20 (Sleepycat) 8/19/97";
+static const char sccsid[] = "@(#)bt_open.c    10.21 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 /*
@@ -95,7 +95,7 @@ __bam_open(dbp, type, dbinfo)
        int ret;
 
        /* Allocate the btree internal structure. */
-       if ((t = (BTREE *)calloc(1, sizeof(BTREE))) == NULL)
+       if ((t = (BTREE *)__db_calloc(1, sizeof(BTREE))) == NULL)
                return (ENOMEM);
 
        t->bt_sp = t->bt_csp = t->bt_stack;
@@ -179,7 +179,7 @@ einval:     ret = EINVAL;
 err:   if (t != NULL) {
                /* If we allocated room for key/data return, discard it. */
                if (t->bt_rkey.data != NULL)
-                       free(t->bt_rkey.data);
+                       __db_free(t->bt_rkey.data);
 
                FREE(t, sizeof(BTREE));
        }
@@ -201,7 +201,7 @@ __bam_bdup(orig, new)
 
        ot = orig->internal;
 
-       if ((t = (BTREE *)calloc(1, sizeof(*t))) == NULL)
+       if ((t = (BTREE *)__db_calloc(1, sizeof(*t))) == NULL)
                return (ENOMEM);
 
        /*
@@ -248,7 +248,7 @@ __bam_keyalloc(t)
         * Recno keys are always the same size, and we don't want to have
         * to check for space on each return.  Allocate it now.
         */
-       if ((t->bt_rkey.data = (void *)malloc(sizeof(db_recno_t))) == NULL)
+       if ((t->bt_rkey.data = (void *)__db_malloc(sizeof(db_recno_t))) == NULL)
                return (ENOMEM);
        t->bt_rkey.ulen = sizeof(db_recno_t);
        return (0);
index af09f76d41ad3a2c91d5a929fa079d695e9fde53..b3d775bb0f2229312672f8277cc61ecd733ddbf6 100644 (file)
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_put.c     10.25 (Sleepycat) 9/17/97";
+static const char sccsid[] = "@(#)bt_put.c     10.31 (Sleepycat) 10/26/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -66,7 +66,10 @@ static const char sccsid[] = "@(#)bt_put.c   10.25 (Sleepycat) 9/17/97";
 static int __bam_fixed __P((BTREE *, DBT *));
 static int __bam_lookup __P((DB *, DBT *, int *));
 static int __bam_ndup __P((DB *, PAGE *, u_int32_t));
-static int __bam_partial __P((DB *, DBT *, PAGE *, u_int32_t));
+static int __bam_ovput __P((DB *, PAGE *, u_int32_t, DBT *));
+static int __bam_partial __P((DB *, DBT *, PAGE *, u_int32_t, u_int32_t));
+static u_int32_t
+          __bam_partsize __P((DB *, DBT *, PAGE *, u_int32_t));
 
 /*
  * __bam_put --
@@ -333,21 +336,6 @@ miss:      ++t->lstat.bt_cache_miss;
 slow:  return (__bam_search(dbp, key, S_INSERT, 1, NULL, exactp));
 }
 
-/*
- * OVPUT --
- *     Copy an overflow item onto a page.
- */
-#undef OVPUT
-#define        OVPUT(h, indx, bo) do {                                         \
-       DBT __hdr;                                                      \
-       memset(&__hdr, 0, sizeof(__hdr));                               \
-       __hdr.data = &bo;                                               \
-       __hdr.size = BOVERFLOW_SIZE;                                    \
-       if ((ret = __db_pitem(dbp,                                      \
-           h, indx, BOVERFLOW_SIZE, &__hdr, NULL)) != 0)               \
-               return (ret);                                           \
-} while (0)
-
 /*
  * __bam_iitem --
  *     Insert an item into the tree.
@@ -365,19 +353,18 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
 {
        BTREE *t;
        BKEYDATA *bk;
-       BOVERFLOW kbo, dbo;
        DBT tdbt;
        PAGE *h;
        db_indx_t indx;
-       u_int32_t have_bytes, need_bytes, needed;
-       int bigkey, bigdata, dcopy, dupadjust, ret;
+       u_int32_t data_size, have_bytes, need_bytes, needed;
+       int bigkey, bigdata, dupadjust, replace, ret;
 
        t = dbp->internal;
        h = *hp;
        indx = *indxp;
 
-       dupadjust = 0;
        bk = NULL;                      /* XXX: Shut the compiler up. */
+       dupadjust = replace = 0;
 
        /*
         * If it's a page of duplicates, call the common code to do the work.
@@ -385,7 +372,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
         * !!!
         * Here's where the hp and indxp are important.  The duplicate code
         * may decide to rework/rearrange the pages and indices we're using,
-        * so the caller must understand that the stack has to change.
+        * so the caller must understand that the page stack may change.
         */
        if (TYPE(h) == P_DUPLICATE) {
                /* Adjust the index for the new item if it's a DB_AFTER op. */
@@ -401,24 +388,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                return (__db_dput(dbp, data, hp, indxp, __bam_new));
        }
 
-       /*
-        * XXX
-        * Handle partial puts.
-        *
-        * This is truly awful from a performance standput.  We don't optimize
-        * for partial puts at all, we delete the record and add it back in,
-        * regardless of size or if we're simply overwriting current data.
-        * The hash access method does this a lot better than we do, and we're
-        * eventually going to have to fix it.
-        */
-       if (F_ISSET(data, DB_DBT_PARTIAL)) {
-               tdbt = *data;
-               if ((ret = __bam_partial(dbp, &tdbt, h, indx)) != 0)
-                       return (ret);
-               data = &tdbt;
-       }
-
-       /* If it's a short fixed-length record, fix it up. */
+       /* Handle fixed-length records: build the real record. */
        if (F_ISSET(dbp, DB_RE_FIXEDLEN) && data->size != t->bt_recno->re_len) {
                tdbt = *data;
                if ((ret = __bam_fixed(t, &tdbt)) != 0)
@@ -427,30 +397,15 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
        }
 
        /*
-        * If the key or data item won't fit on a page, store it in the
-        * overflow pages.
-        *
-        * !!!
-        * From this point on, we have to recover the allocated overflow
-        * pages on error.
+        * Figure out how much space the data will take, including if it's a
+        * partial record.  If either of the key or data items won't fit on
+        * a page, we'll have to store them on overflow pages.
         */
-       bigkey = bigdata = 0;
-       if (LF_ISSET(BI_NEWKEY) && key->size > t->bt_ovflsize) {
-               B_TSET(kbo.type, B_OVERFLOW, 0);
-               kbo.tlen = key->size;
-               if ((ret = __db_poff(dbp, key, &kbo.pgno, __bam_new)) != 0)
-                       goto err;
-               bigkey = 1;
-       }
-       if (data->size > t->bt_ovflsize) {
-               B_TSET(dbo.type, B_OVERFLOW, 0);
-               dbo.tlen = data->size;
-               if ((ret = __db_poff(dbp, data, &dbo.pgno, __bam_new)) != 0)
-                       goto err;
-               bigdata = 1;
-       }
+       bigkey = LF_ISSET(BI_NEWKEY) && key->size > t->bt_ovflsize;
+       data_size = F_ISSET(data, DB_DBT_PARTIAL) ?
+           __bam_partsize(dbp, data, h, indx) : data->size;
+       bigdata = data_size > t->bt_ovflsize;
 
-       dcopy = 0;
        needed = 0;
        if (LF_ISSET(BI_NEWKEY)) {
                /* If BI_NEWKEY is set we're adding a new key and data pair. */
@@ -461,7 +416,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                if (bigdata)
                        needed += BOVERFLOW_PSIZE;
                else
-                       needed += BKEYDATA_PSIZE(data->size);
+                       needed += BKEYDATA_PSIZE(data_size);
        } else {
                /*
                 * We're either overwriting the data item of a key/data pair
@@ -482,16 +437,8 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                if (bigdata)
                        need_bytes += BOVERFLOW_PSIZE;
                else
-                       need_bytes += BKEYDATA_PSIZE(data->size);
+                       need_bytes += BKEYDATA_PSIZE(data_size);
 
-               /*
-                * If we're overwriting a data item, we copy it if it's not a
-                * special record type and it's the same size (including any
-                * alignment) and do a delete/insert otherwise.
-                */
-               if (op == DB_CURRENT && !bigdata &&
-                   B_TYPE(bk->type) == B_KEYDATA && have_bytes == need_bytes)
-                       dcopy = 1;
                if (have_bytes < need_bytes)
                        needed += need_bytes - have_bytes;
        }
@@ -505,9 +452,15 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
         * check in the btree split code, so we don't undo it there!?!?
         */
        if (P_FREESPACE(h) < needed ||
-           (t->bt_maxkey != 0 && NUM_ENT(h) > t->bt_maxkey)) {
-               ret = DB_NEEDSPLIT;
-               goto err;
+           (t->bt_maxkey != 0 && NUM_ENT(h) > t->bt_maxkey))
+               return (DB_NEEDSPLIT);
+
+       /* Handle partial puts: build the real record. */
+       if (F_ISSET(data, DB_DBT_PARTIAL)) {
+               tdbt = *data;
+               if ((ret = __bam_partial(dbp, &tdbt, h, indx, data_size)) != 0)
+                       return (ret);
+               data = &tdbt;
        }
 
        /*
@@ -515,10 +468,10 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
         *
         * 1. Append a new key/data pair.
         * 2. Insert a new key/data pair.
-        * 3. Copy the data item.
-        * 4. Delete/insert the data item.
-        * 5. Append a new data item.
-        * 6. Insert a new data item.
+        * 3. Append a new data item (a new duplicate).
+        * 4. Insert a new data item (a new duplicate).
+        * 5. Overflow item: delete and re-add the data item.
+        * 6. Replace the data item.
         */
        if (LF_ISSET(BI_NEWKEY)) {
                switch (op) {
@@ -533,42 +486,17 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                }
 
                /* Add the key. */
-               if (bigkey)
-                       OVPUT(h, indx, kbo);
-               else {
-                       DBT __data;
-                       memset(&__data, 0, sizeof(__data));
-                       __data.data = key->data;
-                       __data.size = key->size;
+               if (bigkey) {
+                       if ((ret = __bam_ovput(dbp, h, indx, key)) != 0)
+                               return (ret);
+               } else
                        if ((ret = __db_pitem(dbp, h, indx,
-                           BKEYDATA_SIZE(key->size), NULL, &__data)) != 0)
-                               goto err;
-               }
+                           BKEYDATA_SIZE(key->size), NULL, key)) != 0)
+                               return (ret);
                ++indx;
        } else {
                switch (op) {
-               case DB_CURRENT:        /* 3. Copy the data item. */
-                       /*
-                        * If we're not logging and it's possible, overwrite
-                        * the current item.
-                        *
-                        * XXX
-                        * We should add a separate logging message so that
-                        * we can do this anytime it's possible, including
-                        * for partial record puts.
-                        */
-                       if (dcopy && !DB_LOGGING(dbp)) {
-                               bk->len = data->size;
-                               memcpy(bk->data, data->data, data->size);
-                               goto done;
-                       }
-                                       /* 4. Delete/insert the data item. */
-                       if (TYPE(h) == P_LBTREE)
-                               ++indx;
-                       if ((ret = __bam_ditem(dbp, h, indx)) != 0)
-                               goto err;
-                       break;
-               case DB_AFTER:          /* 5. Append a new data item. */
+               case DB_AFTER:          /* 3. Append a new data item. */
                        if (TYPE(h) == P_LBTREE) {
                                /*
                                 * Adjust the cursor and copy in the key for
@@ -576,7 +504,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                                 */
                                if ((ret = __bam_adjindx(dbp,
                                    h, indx + P_INDX, indx, 1)) != 0)
-                                       goto err;
+                                       return (ret);
 
                                indx += 3;
                                dupadjust = 1;
@@ -589,7 +517,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                                *indxp += 1;
                        }
                        break;
-               case DB_BEFORE:         /* 6. Insert a new data item. */
+               case DB_BEFORE:         /* 4. Insert a new data item. */
                        if (TYPE(h) == P_LBTREE) {
                                /*
                                 * Adjust the cursor and copy in the key for
@@ -597,43 +525,62 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
                                 */
                                if ((ret =
                                    __bam_adjindx(dbp, h, indx, indx, 1)) != 0)
-                                       goto err;
+                                       return (ret);
 
                                ++indx;
                                dupadjust = 1;
                        } else
                                __bam_ca_di(dbp, h->pgno, indx, 1);
                        break;
+               case DB_CURRENT:
+                       if (TYPE(h) == P_LBTREE)
+                               ++indx;
+
+                       /*
+                        * 5. Delete/re-add the data item.
+                        *
+                        * If we're dealing with offpage items, we have to 
+                        * delete and then re-add the item.
+                        */
+                       if (bigdata || B_TYPE(bk->type) == B_OVERFLOW) {
+                               if ((ret = __bam_ditem(dbp, h, indx)) != 0)
+                                       return (ret);
+                               break;
+                       }
+
+                       /* 6. Replace the data item. */
+                       replace = 1;
+                       break;
                default:
                        abort();
                }
        }
 
        /* Add the data. */
-       if (bigdata)
-               OVPUT(h, indx, dbo);
-       else {
+       if (bigdata) {
+               if ((ret = __bam_ovput(dbp, h, indx, data)) != 0)
+                       return (ret);
+       } else {
                BKEYDATA __bk;
-               DBT __hdr, __data;
-               memset(&__data, 0, sizeof(__data));
-               __data.data = data->data;
-               __data.size = data->size;
+               DBT __hdr;
 
                if (LF_ISSET(BI_DELETED)) {
                        B_TSET(__bk.type, B_KEYDATA, 1);
-                       __bk.len = __data.size;
+                       __bk.len = data->size;
                        __hdr.data = &__bk;
                        __hdr.size = SSZA(BKEYDATA, data);
                        ret = __db_pitem(dbp, h, indx,
-                           BKEYDATA_SIZE(__data.size), &__hdr, &__data);
-               } else
+                           BKEYDATA_SIZE(data->size), &__hdr, data);
+               } else if (replace)
+                       ret = __bam_ritem(dbp, h, indx, data);
+               else
                        ret = __db_pitem(dbp, h, indx,
-                           BKEYDATA_SIZE(data->size), NULL, &__data);
+                           BKEYDATA_SIZE(data->size), NULL, data);
                if (ret != 0)
-                       goto err;
+                       return (ret);
        }
 
-done:  ++t->lstat.bt_added;
+       ++t->lstat.bt_added;
 
        ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY);
 
@@ -645,21 +592,205 @@ done:    ++t->lstat.bt_added;
        if (dupadjust && P_FREESPACE(h) <= dbp->pgsize / 2) {
                --indx;
                if ((ret = __bam_ndup(dbp, h, indx)) != 0)
-                       goto err;
+                       return (ret);
        }
 
        if (t->bt_recno != NULL)
                F_SET(t->bt_recno, RECNO_MODIFIED);
 
-       if (0) {
-err:           if (bigkey)
-                       (void)__db_doff(dbp, kbo.pgno, __bam_free);
-               if (bigdata)
-                       (void)__db_doff(dbp, dbo.pgno, __bam_free);
-       }
        return (ret);
 }
 
+/*
+ * __bam_partsize --
+ *     Figure out how much space a partial data item is in total.
+ */
+static u_int32_t
+__bam_partsize(dbp, data, h, indx)
+       DB *dbp;
+       DBT *data;
+       PAGE *h;
+       u_int32_t indx;
+{
+       BKEYDATA *bk;
+       u_int32_t nbytes;
+
+       /*
+        * Figure out how much total space we'll need.  If the record doesn't
+        * already exist, it's simply the data we're provided.
+        */
+       if (indx >= NUM_ENT(h))
+               return (data->doff + data->size);
+
+       /*
+        * Otherwise, it's the data provided plus any already existing data
+        * that we're not replacing.
+        */
+       bk = GET_BKEYDATA(h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0));
+       nbytes =
+           B_TYPE(bk->type) == B_OVERFLOW ? ((BOVERFLOW *)bk)->tlen : bk->len;
+
+       /*
+        * There are really two cases here:
+        *
+        * Case 1: We are replacing some bytes that do not exist (i.e., they
+        * are past the end of the record).  In this case the number of bytes
+        * we are replacing is irrelevant and all we care about is how many
+        * bytes we are going to add from offset.  So, the new record length
+        * is going to be the size of the new bytes (size) plus wherever those
+        * new bytes begin (doff).
+        *
+        * Case 2: All the bytes we are replacing exist.  Therefore, the new
+        * size is the oldsize (nbytes) minus the bytes we are replacing (dlen)
+        * plus the bytes we are adding (size).
+        */
+       if (nbytes < data->doff + data->dlen)           /* Case 1 */
+               return (data->doff + data->size);
+
+       return (nbytes + data->size - data->dlen);      /* Case 2 */
+}
+
+/*
+ * OVPUT --
+ *     Copy an overflow item onto a page.
+ */
+#undef OVPUT
+#define        OVPUT(h, indx, bo) do {                                         \
+       DBT __hdr;                                                      \
+       memset(&__hdr, 0, sizeof(__hdr));                               \
+       __hdr.data = &bo;                                               \
+       __hdr.size = BOVERFLOW_SIZE;                                    \
+       if ((ret = __db_pitem(dbp,                                      \
+           h, indx, BOVERFLOW_SIZE, &__hdr, NULL)) != 0)               \
+               return (ret);                                           \
+} while (0)
+
+/*
+ * __bam_ovput --
+ *     Build an overflow item and put it on the page.
+ */
+static int
+__bam_ovput(dbp, h, indx, item)
+       DB *dbp;
+       PAGE *h;
+       u_int32_t indx;
+       DBT *item;
+{
+       BOVERFLOW bo;
+       int ret;
+
+       B_TSET(bo.type, B_OVERFLOW, 0);
+       bo.tlen = item->size;
+       if ((ret = __db_poff(dbp, item, &bo.pgno, __bam_new)) != 0)
+               return (ret);
+
+       OVPUT(h, indx, bo);
+
+       return (0);
+}
+
+/*
+ * __bam_ritem --
+ *     Replace an item on a page.
+ *
+ * PUBLIC: int __bam_ritem __P((DB *, PAGE *, u_int32_t, DBT *));
+ */
+int
+__bam_ritem(dbp, h, indx, data)
+       DB *dbp;
+       PAGE *h;
+       u_int32_t indx;
+       DBT *data;
+{
+       BKEYDATA *bk;
+       DBT orig, repl;
+       db_indx_t lo, ln, min, off, prefix, suffix;
+       int32_t nbytes;
+       int cnt, ret;
+       u_int8_t *p, *t;
+
+       /*
+        * Replace a single item onto a page.  The logic figuring out where
+        * to insert and whether it fits is handled in the caller.  All we do
+        * here is manage the page shuffling.
+        */
+       bk = GET_BKEYDATA(h, indx);
+
+       /* Log the change. */
+       if (DB_LOGGING(dbp)) {
+               /*
+                * We might as well check to see if the two data items share
+                * a common prefix and suffix -- it can save us a lot of log
+                * message if they're large.
+                */
+               min = data->size < bk->len ? data->size : bk->len;
+               for (prefix = 0,
+                   p = bk->data, t = data->data;
+                   prefix < min && *p == *t; ++prefix, ++p, ++t)
+                       ;
+
+               min -= prefix;
+               for (suffix = 0,
+                   p = (u_int8_t *)bk->data + bk->len - 1,
+                   t = (u_int8_t *)data->data + data->size - 1;
+                   suffix < min && *p == *t; ++suffix, --p, --t)
+                       ;
+
+               /* We only log the parts of the keys that have changed. */
+               orig.data = (u_int8_t *)bk->data + prefix;
+               orig.size = bk->len - (prefix + suffix);
+               repl.data = (u_int8_t *)data->data + prefix;
+               repl.size = data->size - (prefix + suffix);
+               if ((ret = __bam_repl_log(dbp->dbenv->lg_info, dbp->txn,
+                   &LSN(h), 0, dbp->log_fileid, PGNO(h), &LSN(h),
+                   (u_int32_t)indx, (u_int32_t)B_DISSET(bk->type),
+                   &orig, &repl, (u_int32_t)prefix, (u_int32_t)suffix)) != 0)
+                       return (ret);
+       }
+
+       /*
+        * Set references to the first in-use byte on the page and the
+        * first byte of the item being replaced.
+        */
+       p = (u_int8_t *)h + HOFFSET(h);
+       t = (u_int8_t *)bk;
+
+       /*
+        * If the entry is growing in size, shift the beginning of the data
+        * part of the page down.  If the entry is shrinking in size, shift
+        * the beginning of the data part of the page up.  Use memmove(3),
+        * the regions overlap.
+        */
+       lo = BKEYDATA_SIZE(bk->len);
+       ln = BKEYDATA_SIZE(data->size);
+       if (lo != ln) {
+               nbytes = lo - ln;               /* Signed difference. */
+               if (p == t)                     /* First index is fast. */
+                       h->inp[indx] += nbytes;
+               else {                          /* Else, shift the page. */
+                       memmove(p + nbytes, p, t - p);
+
+                       /* Adjust the indices' offsets. */
+                       off = h->inp[indx];
+                       for (cnt = 0; cnt < NUM_ENT(h); ++cnt)
+                               if (h->inp[cnt] <= off)
+                                       h->inp[cnt] += nbytes;
+               }
+
+               /* Clean up the page and adjust the item's reference. */
+               HOFFSET(h) += nbytes;
+               t += nbytes;
+       }
+
+       /* Copy the new item onto the page. */
+       bk = (BKEYDATA *)t;
+       B_TSET(bk->type, B_KEYDATA, 0);
+       bk->len = data->size;
+       memcpy(bk->data, data->data, data->size);
+
+       return (0);
+}
+
 /*
  * __bam_ndup --
  *     Check to see if the duplicate set at indx should have its own page.
@@ -766,16 +897,21 @@ __bam_fixed(t, dbt)
        rp = t->bt_recno;
 
        /*
-        * If using fixed-length records, and the record is long, return
-        * EINVAL.  If it's short, pad it out.  Use the record data return
-        * memory, it's only short-term.
+        * If database contains fixed-length records, and the record is long,
+        * return EINVAL.
         */
        if (dbt->size > rp->re_len)
                return (EINVAL);
+
+       /*
+        * The caller checked to see if it was just right, so we know it's
+        * short.  Pad it out.  We use the record data return memory, it's
+        * only a short-term use.
+        */
        if (t->bt_rdata.ulen < rp->re_len) {
                t->bt_rdata.data = t->bt_rdata.data == NULL ?
-                   (void *)malloc(rp->re_len) :
-                   (void *)realloc(t->bt_rdata.data, rp->re_len);
+                   (void *)__db_malloc(rp->re_len) :
+                   (void *)__db_realloc(t->bt_rdata.data, rp->re_len);
                if (t->bt_rdata.data == NULL) {
                        t->bt_rdata.ulen = 0;
                        return (ENOMEM);
@@ -786,12 +922,16 @@ __bam_fixed(t, dbt)
        memset((u_int8_t *)t->bt_rdata.data + dbt->size,
            rp->re_pad, rp->re_len - dbt->size);
 
-       /* Set the DBT to reference our new record. */
+       /*
+        * Clean up our flags and other information just in case, and
+        * change the caller's DBT to reference our created record.
+        */
        t->bt_rdata.size = rp->re_len;
        t->bt_rdata.dlen = 0;
        t->bt_rdata.doff = 0;
        t->bt_rdata.flags = 0;
        *dbt = t->bt_rdata;
+
        return (0);
 }
 
@@ -800,47 +940,28 @@ __bam_fixed(t, dbt)
  *     Build the real record for a partial put.
  */
 static int
-__bam_partial(dbp, dbt, h, indx)
+__bam_partial(dbp, dbt, h, indx, nbytes)
        DB *dbp;
        DBT *dbt;
        PAGE *h;
-       u_int32_t indx;
+       u_int32_t indx, nbytes;
 {
        BTREE *t;
        BKEYDATA *bk, tbk;
        BOVERFLOW *bo;
        DBT copy;
-       u_int32_t len, nbytes, tlen;
+       u_int32_t len, tlen;
        int ret;
        u_int8_t *p;
 
        bo = NULL;                      /* XXX: Shut the compiler up. */
        t = dbp->internal;
 
-       /*
-        * Figure out how much total space we'll need.  Worst case is where
-        * the record is 0 bytes long, in which case doff causes the record
-        * to extend, and the put data is appended to it.
-        */
-       if (indx < NUM_ENT(h)) {
-               bk = GET_BKEYDATA(h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0));
-               if (B_TYPE(bk->type) == B_OVERFLOW) {
-                       bo = (BOVERFLOW *)bk;
-                       nbytes = bo->tlen;
-               } else
-                       nbytes = bk->len;
-       } else {
-               bk = &tbk;
-               B_TSET(bk->type, B_KEYDATA, 0);
-               nbytes = bk->len = 0;
-       }
-       nbytes += dbt->doff + dbt->size + dbt->dlen;
-
-       /* Allocate the space. */
+       /* We use the record data return memory, it's only a short-term use. */
        if (t->bt_rdata.ulen < nbytes) {
                t->bt_rdata.data = t->bt_rdata.data == NULL ?
-                   (void *)malloc(nbytes) :
-                   (void *)realloc(t->bt_rdata.data, nbytes);
+                   (void *)__db_malloc(nbytes) :
+                   (void *)__db_realloc(t->bt_rdata.data, nbytes);
                if (t->bt_rdata.data == NULL) {
                        t->bt_rdata.ulen = 0;
                        return (ENOMEM);
@@ -848,6 +969,16 @@ __bam_partial(dbp, dbt, h, indx)
                t->bt_rdata.ulen = nbytes;
        }
 
+       /* Find the current record. */
+       if (indx < NUM_ENT(h)) {
+               bk = GET_BKEYDATA(h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0));
+               bo = (BOVERFLOW *)bk;
+       } else {
+               bk = &tbk;
+               B_TSET(bk->type, B_KEYDATA, 0);
+               bk->len = 0;
+       }
+
        /* We use nul bytes for extending the record, get it over with. */
        memset(t->bt_rdata.data, 0, nbytes);
 
index 9aeb395f27ebb12925f7458869880c3ab784b271..c0b7c8ae4cad23bf978f7defb9d720704eb85d37 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_rec.c     10.14 (Sleepycat) 9/6/97";
+static const char sccsid[] = "@(#)bt_rec.c     10.17 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -298,8 +298,8 @@ __bam_split_recover(logp, dbtp, lsnp, redo, info)
                        goto done;
 
                /* Allocate and initialize new left/right child pages. */
-               if ((_lp = (PAGE *)malloc(file_dbp->pgsize)) == NULL ||
-                   (_rp = (PAGE *)malloc(file_dbp->pgsize)) == NULL) {
+               if ((_lp = (PAGE *)__db_malloc(file_dbp->pgsize)) == NULL ||
+                   (_rp = (PAGE *)__db_malloc(file_dbp->pgsize)) == NULL) {
                        ret = ENOMEM;
                        __db_err(file_dbp->dbenv, "%s", strerror(ret));
                        goto out;
@@ -490,9 +490,9 @@ out:        /* Free any pages that weren't dirtied. */
 
        /* Free any allocated space. */
        if (_lp != NULL)
-               free(_lp);
+               __db_free(_lp);
        if (_rp != NULL)
-               free(_rp);
+               __db_free(_rp);
 
        REC_CLOSE;
 }
@@ -541,7 +541,8 @@ __bam_rsplit_recover(logp, dbtp, lsnp, redo, info)
        } else if (cmp_n == 0 && !redo) {
                /* Need to undo update described. */
                P_INIT(pagep, file_dbp->pgsize, PGNO_ROOT,
-                   PGNO_INVALID, PGNO_INVALID, pagep->level + 1, TYPE(pagep));
+                   argp->nrec, PGNO_INVALID, pagep->level + 1,
+                   file_dbp->type == DB_BTREE ? P_IBTREE : P_IRECNO);
                if ((ret = __db_pitem(file_dbp, pagep, 0,
                    argp->rootent.size, &argp->rootent, NULL)) != 0)
                        goto out;
@@ -764,3 +765,106 @@ __bam_cdel_recover(logp, dbtp, lsnp, redo, info)
 
 out:   REC_CLOSE;
 }
+
+/*
+ * __bam_repl_recover --
+ *     Recovery function for page item replacement.
+ *
+ * PUBLIC: int __bam_repl_recover
+ * PUBLIC:   __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
+ */
+int
+__bam_repl_recover(logp, dbtp, lsnp, redo, info)
+       DB_LOG *logp;
+       DBT *dbtp;
+       DB_LSN *lsnp;
+       int redo;
+       void *info;
+{
+       __bam_repl_args *argp;
+       BKEYDATA *bk;
+       DB *file_dbp, *mdbp;
+       DBT dbt;
+       DB_MPOOLFILE *mpf;
+       PAGE *pagep;
+       int cmp_n, cmp_p, modified, ret;
+       u_int8_t *p;
+
+       REC_PRINT(__bam_repl_print);
+       REC_INTRO(__bam_repl_read);
+
+       if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+               (void)__db_pgerr(file_dbp, argp->pgno);
+               pagep = NULL;
+               goto out;
+       }
+       bk = GET_BKEYDATA(pagep, argp->indx);
+
+       modified = 0;
+       cmp_n = log_compare(lsnp, &LSN(pagep));
+       cmp_p = log_compare(&LSN(pagep), &argp->lsn);
+       if (cmp_p == 0 && redo) {
+               /*
+                * Need to redo update described.
+                *
+                * Re-build the replacement item.
+                */
+               memset(&dbt, 0, sizeof(dbt));
+               dbt.size = argp->prefix + argp->suffix + argp->repl.size;
+               if ((dbt.data = __db_malloc(dbt.size)) == NULL) {
+                       ret = ENOMEM;
+                       goto err;
+               }
+               p = dbt.data;
+               memcpy(p, bk->data, argp->prefix);
+               p += argp->prefix;
+               memcpy(p, argp->repl.data, argp->repl.size);
+               p += argp->repl.size;
+               memcpy(p, bk->data + (bk->len - argp->suffix), argp->suffix);
+
+               ret = __bam_ritem(file_dbp, pagep, argp->indx, &dbt);
+               __db_free(dbt.data);
+               if (ret != 0)
+                       goto err;
+
+               LSN(pagep) = *lsnp;
+               modified = 1;
+       } else if (cmp_n == 0 && !redo) {
+               /*
+                * Need to undo update described.
+                *
+                * Re-build the original item.
+                */
+               memset(&dbt, 0, sizeof(dbt));
+               dbt.size = argp->prefix + argp->suffix + argp->orig.size;
+               if ((dbt.data = __db_malloc(dbt.size)) == NULL) {
+                       ret = ENOMEM;
+                       goto err;
+               }
+               p = dbt.data;
+               memcpy(p, bk->data, argp->prefix);
+               p += argp->prefix;
+               memcpy(p, argp->orig.data, argp->orig.size);
+               p += argp->orig.size;
+               memcpy(p, bk->data + (bk->len - argp->suffix), argp->suffix);
+
+               ret = __bam_ritem(file_dbp, pagep, argp->indx, &dbt);
+               __db_free(dbt.data);
+               if (ret != 0)
+                       goto err;
+
+               /* Reset the deleted flag, if necessary. */
+               if (argp->isdeleted)
+                       B_DSET(GET_BKEYDATA(pagep, argp->indx)->type);
+
+               LSN(pagep) = argp->lsn;
+               modified = 1;
+       }
+       if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) == 0)
+               *lsnp = argp->prev_lsn;
+
+       if (0) {
+err:           (void)memp_fput(mpf, pagep, 0);
+       }
+out:   REC_CLOSE;
+}
index f7c5cffdc60711069e14c7e4375db57395862f6c..5e1cbc426cb488f3ddc9fcc9e9b6c1ab13ddc742 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_recno.c   10.19 (Sleepycat) 9/20/97";
+static const char sccsid[] = "@(#)bt_recno.c   10.22 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -75,7 +75,7 @@ __ram_open(dbp, type, dbinfo)
        ret = 0;
 
        /* Allocate and initialize the private RECNO structure. */
-       if ((rp = (RECNO *)calloc(1, sizeof(*rp))) == NULL)
+       if ((rp = (RECNO *)__db_calloc(1, sizeof(*rp))) == NULL)
                return (ENOMEM);
 
        if (dbinfo != NULL) {
@@ -140,7 +140,7 @@ __ram_open(dbp, type, dbinfo)
 
 err:   /* If we mmap'd a source file, discard it. */
        if (rp->re_smap != NULL)
-               (void)__db_munmap(rp->re_smap, rp->re_msize);
+               (void)__db_unmap(rp->re_smap, rp->re_msize);
 
        /* If we opened a source file, discard it. */
        if (rp->re_fd != -1)
@@ -151,7 +151,7 @@ err:        /* If we mmap'd a source file, discard it. */
        /* If we allocated room for key/data return, discard it. */
        t = dbp->internal;
        if (t != NULL && t->bt_rkey.data != NULL)
-               free(t->bt_rkey.data);
+               __db_free(t->bt_rkey.data);
 
        FREE(rp, sizeof(*rp));
 
@@ -175,10 +175,10 @@ __ram_cursor(dbp, txn, dbcp)
 
        DEBUG_LWRITE(dbp, txn, "ram_cursor", NULL, NULL, 0);
 
-       if ((dbc = (DBC *)calloc(1, sizeof(DBC))) == NULL)
+       if ((dbc = (DBC *)__db_calloc(1, sizeof(DBC))) == NULL)
                return (ENOMEM);
-       if ((cp = (RCURSOR *)calloc(1, sizeof(RCURSOR))) == NULL) {
-               free(dbc);
+       if ((cp = (RCURSOR *)__db_calloc(1, sizeof(RCURSOR))) == NULL) {
+               __db_free(dbc);
                return (ENOMEM);
        }
 
@@ -359,7 +359,7 @@ __ram_close(argdbp)
 
        /* Close any underlying mmap region. */
        if (rp->re_smap != NULL)
-               (void)__db_munmap(rp->re_smap, rp->re_msize);
+               (void)__db_unmap(rp->re_smap, rp->re_msize);
 
        /* Close any backing source file descriptor. */
        if (rp->re_fd != -1)
@@ -814,8 +814,8 @@ __ram_update(dbp, recno, can_create)
        if (F_ISSET(dbp, DB_RE_FIXEDLEN)) {
                if (t->bt_rdata.ulen < rp->re_len) {
                        t->bt_rdata.data = t->bt_rdata.data == NULL ?
-                           (void *)malloc(rp->re_len) :
-                           (void *)realloc(t->bt_rdata.data, rp->re_len);
+                           (void *)__db_malloc(rp->re_len) :
+                           (void *)__db_realloc(t->bt_rdata.data, rp->re_len);
                        if (t->bt_rdata.data == NULL) {
                                t->bt_rdata.ulen = 0;
                                return (ENOMEM);
@@ -853,7 +853,7 @@ __ram_source(dbp, rp, fname)
 
        oflags = F_ISSET(dbp, DB_AM_RDONLY) ? DB_RDONLY : 0;
        if ((ret =
-           __db_fdopen(rp->re_source, oflags, oflags, 0, &rp->re_fd)) != 0) {
+           __db_open(rp->re_source, oflags, oflags, 0, &rp->re_fd)) != 0) {
                __db_err(dbp->dbenv, "%s: %s", rp->re_source, strerror(ret));
                goto err;
        }
@@ -866,15 +866,16 @@ __ram_source(dbp, rp, fname)
         * compiler will perpetrate, doing the comparison in a portable way is
         * flatly impossible.  Hope that mmap fails if the file is too large.
         */
-       if ((ret =
-           __db_stat(dbp->dbenv, rp->re_source, rp->re_fd, &size, NULL)) != 0)
+       if ((ret = __db_ioinfo(rp->re_source, rp->re_fd, &size, NULL)) != 0) {
+               __db_err(dbp->dbenv, "%s: %s", rp->re_source, strerror(ret));
                goto err;
+       }
        if (size == 0) {
                F_SET(rp, RECNO_EOF);
                return (0);
        }
 
-       if ((ret = __db_mmap(rp->re_fd, (size_t)size, 1, 1, &rp->re_smap)) != 0)
+       if ((ret = __db_map(rp->re_fd, (size_t)size, 1, 1, &rp->re_smap)) != 0)
                goto err;
        rp->re_cmap = rp->re_smap;
        rp->re_emap = (u_int8_t *)rp->re_smap + (rp->re_msize = size);
@@ -940,7 +941,7 @@ __ram_writeback(dbp)
         * open will fail.
         */
        if (rp->re_smap != NULL) {
-               (void)__db_munmap(rp->re_smap, rp->re_msize);
+               (void)__db_unmap(rp->re_smap, rp->re_msize);
                rp->re_smap = NULL;
        }
 
@@ -951,7 +952,7 @@ __ram_writeback(dbp)
        }
 
        /* Open the file, truncating it. */
-       if ((ret = __db_fdopen(rp->re_source,
+       if ((ret = __db_open(rp->re_source,
            DB_SEQUENTIAL | DB_TRUNCATE,
            DB_SEQUENTIAL | DB_TRUNCATE, 0, &fd)) != 0) {
                __db_err(dbp->dbenv, "%s: %s", rp->re_source, strerror(ret));
@@ -974,7 +975,7 @@ __ram_writeback(dbp)
         */
        delim = rp->re_delim;
        if (F_ISSET(dbp, DB_RE_FIXEDLEN)) {
-               if ((pad = malloc(rp->re_len)) == NULL) {
+               if ((pad = (u_int8_t *)__db_malloc(rp->re_len)) == NULL) {
                        ret = ENOMEM;
                        goto err;
                }
@@ -1051,8 +1052,8 @@ __ram_fmap(dbp, top)
        rp = t->bt_recno;
        if (t->bt_rdata.ulen < rp->re_len) {
                t->bt_rdata.data = t->bt_rdata.data == NULL ?
-                   (void *)malloc(rp->re_len) :
-                   (void *)realloc(t->bt_rdata.data, rp->re_len);
+                   (void *)__db_malloc(rp->re_len) :
+                   (void *)__db_realloc(t->bt_rdata.data, rp->re_len);
                if (t->bt_rdata.data == NULL) {
                        t->bt_rdata.ulen = 0;
                        return (ENOMEM);
index fa3e018313b356fd51ba4043de5b5e8868c1c4e6..a21a8208bc93cf9e1717fe70e44475fcbc56d82f 100644 (file)
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_search.c  10.7 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)bt_search.c  10.8 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -323,7 +323,7 @@ __bam_stkgrow(t)
 
        entries = t->bt_esp - t->bt_sp;
 
-       if ((p = (EPG *)calloc(entries * 2, sizeof(EPG))) == NULL)
+       if ((p = (EPG *)__db_calloc(entries * 2, sizeof(EPG))) == NULL)
                return (ENOMEM);
        memcpy(p, t->bt_sp, entries * sizeof(EPG));
        if (t->bt_sp != t->bt_stack)
index 25cfacc4d0bf075577196d373297f0890987bacc..bc09131b00421b3333eadb49969fbc8a60b80743 100644 (file)
@@ -44,7 +44,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_split.c   10.14 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)bt_split.c   10.17 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -255,7 +255,7 @@ __bam_page(dbp, pp, cp)
            cp->page->level, TYPE(cp->page));
 
        /* Create new left page for the split. */
-       if ((lp = (PAGE *)malloc(dbp->pgsize)) == NULL) {
+       if ((lp = (PAGE *)__db_malloc(dbp->pgsize)) == NULL) {
                ret = ENOMEM;
                goto err;
        }
@@ -389,6 +389,9 @@ __bam_broot(dbp, rootp, lp, rp)
        P_INIT(rootp, dbp->pgsize,
            PGNO_ROOT, PGNO_INVALID, PGNO_INVALID, lp->level + 1, P_IBTREE);
 
+       memset(&data, 0, sizeof(data));
+       memset(&hdr, 0, sizeof(hdr));
+
        /*
         * The btree comparison code guarantees that the left-most key on any
         * level of the tree is never used, so it doesn't need to be filled in.
@@ -399,15 +402,12 @@ __bam_broot(dbp, rootp, lp, rp)
        if (F_ISSET(dbp, DB_BT_RECNUM)) {
                bi.nrecs = __bam_total(lp);
                RE_NREC_SET(rootp, bi.nrecs);
-       }
-       memset(&hdr, 0, sizeof(hdr));
+       } else
+               bi.nrecs = 0;
        hdr.data = &bi;
        hdr.size = SSZA(BINTERNAL, data);
-       memset(&data, 0, sizeof(data));
-       data.data = (char *)"";
-       data.size = 0;
        if ((ret =
-           __db_pitem(dbp, rootp, 0, BINTERNAL_SIZE(0), &hdr, &data)) != 0)
+           __db_pitem(dbp, rootp, 0, BINTERNAL_SIZE(0), &hdr, NULL)) != 0)
                return (ret);
 
        switch (TYPE(rp)) {
@@ -431,9 +431,10 @@ __bam_broot(dbp, rootp, lp, rp)
                        return (ret);
 
                /* Increment the overflow ref count. */
-               if (B_TYPE(child_bi->type) == B_OVERFLOW && (ret =
-                   __db_ioff(dbp, ((BOVERFLOW *)(child_bi->data))->pgno)) != 0)
-                       return (ret);
+               if (B_TYPE(child_bi->type) == B_OVERFLOW)
+                       if ((ret = __db_ovref(dbp,
+                           ((BOVERFLOW *)(child_bi->data))->pgno, 1)) != 0)
+                               return (ret);
                break;
        case P_LBTREE:
                /* Copy the first key of the child page onto the root page. */
@@ -473,9 +474,10 @@ __bam_broot(dbp, rootp, lp, rp)
                                return (ret);
 
                        /* Increment the overflow ref count. */
-                       if (B_TYPE(child_bk->type) == B_OVERFLOW && (ret =
-                           __db_ioff(dbp, ((BOVERFLOW *)child_bk)->pgno)) != 0)
-                               return (ret);
+                       if (B_TYPE(child_bk->type) == B_OVERFLOW)
+                               if ((ret = __db_ovref(dbp,
+                                   ((BOVERFLOW *)child_bk)->pgno, 1)) != 0)
+                                       return (ret);
                        break;
                default:
                        return (__db_pgfmt(dbp, rp->pgno));
@@ -604,9 +606,10 @@ __bam_pinsert(dbp, parent, lchild, rchild)
                        return (ret);
 
                /* Increment the overflow ref count. */
-               if (B_TYPE(child_bi->type) == B_OVERFLOW && (ret =
-                   __db_ioff(dbp, ((BOVERFLOW *)(child_bi->data))->pgno)) != 0)
-                       return (ret);
+               if (B_TYPE(child_bi->type) == B_OVERFLOW)
+                       if ((ret = __db_ovref(dbp,
+                           ((BOVERFLOW *)(child_bi->data))->pgno, 1)) != 0)
+                               return (ret);
                break;
        case P_LBTREE:
                child_bk = GET_BKEYDATA(rchild, 0);
@@ -673,9 +676,10 @@ noprefix:                  nksize = child_bk->len;
                                return (ret);
 
                        /* Increment the overflow ref count. */
-                       if (B_TYPE(child_bk->type) == B_OVERFLOW && (ret =
-                           __db_ioff(dbp, ((BOVERFLOW *)child_bk)->pgno)) != 0)
-                               return (ret);
+                       if (B_TYPE(child_bk->type) == B_OVERFLOW)
+                               if ((ret = __db_ovref(dbp,
+                                   ((BOVERFLOW *)child_bk)->pgno, 1)) != 0)
+                                       return (ret);
                        break;
                default:
                        return (__db_pgfmt(dbp, rchild->pgno));
index ab3bc4c431006a72171ba7de61748a1d4619348f..e88b5dac2d4bf196101f521e50b48c4ad5ec54ac 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_stat.c    10.12 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)bt_stat.c    10.14 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -61,7 +61,7 @@ __bam_stat(argdbp, spp, db_malloc, flags)
 
        /* Allocate and clear the structure. */
        if ((sp = db_malloc == NULL ?
-           (DB_BTREE_STAT *)malloc(sizeof(*sp)) :
+           (DB_BTREE_STAT *)__db_malloc(sizeof(*sp)) :
            (DB_BTREE_STAT *)db_malloc(sizeof(*sp))) == NULL) {
                ret = ENOMEM;
                goto err;
@@ -100,14 +100,13 @@ __bam_stat(argdbp, spp, db_malloc, flags)
        if (F_ISSET(meta, BTM_RENUMBER))
                sp->bt_flags |= DB_RENUMBER;
 
-       /*
-        * Get the maxkey, minkey, re_len and re_pad fields from the
-        * metadata.
-        */
+       /* Get the remaining metadata fields. */
        sp->bt_minkey = meta->minkey;
        sp->bt_maxkey = meta->maxkey;
        sp->bt_re_len = meta->re_len;
        sp->bt_re_pad = meta->re_pad;
+       sp->bt_magic = meta->magic;
+       sp->bt_version = meta->version;
 
        /* Get the page size from the DB. */
        sp->bt_pagesize = dbp->pgsize;
index 7c8c4b125f4209afc282cebd4926d8105c9f8caf..6145696d28d9aea405b084a96e295710d349a98b 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)btree.src    10.4 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)btree.src    10.6 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 PREFIX bam
@@ -75,6 +75,7 @@ END
  *
  * pgno:       the page number of the page copied over the root.
  * pgdbt:      the page being copied on the root page.
+ * nrec:       the tree's record count.
  * rootent:    last entry on the root page.
  * rootlsn:    the root page's original lsn.
  */
@@ -82,6 +83,7 @@ BEGIN rsplit
 ARG    fileid          u_int32_t       lu
 ARG    pgno            db_pgno_t       lu
 DBT    pgdbt           DBT             s
+ARG    nrec            db_pgno_t       lu
 DBT    rootent         DBT             s
 POINTER rootlsn                DB_LSN *        lu
 END
@@ -135,3 +137,24 @@ ARG        pgno            db_pgno_t       lu
 POINTER        lsn             DB_LSN *        lu
 ARG    indx            u_int32_t       lu
 END
+
+/*
+ * BTREE-repl: used to log the replacement of an item.
+ *
+ * pgno:       the page modified.
+ * lsn:                the page's original lsn.
+ * orig:       the original data.
+ * new:                the replacement data.
+ * duplicate:  the prefix of the replacement that matches the original.
+ */
+BEGIN repl
+ARG    fileid          u_int32_t       lu
+ARG    pgno            db_pgno_t       lu
+POINTER        lsn             DB_LSN *        lu
+ARG    indx            u_int32_t       lu
+ARG    isdeleted       u_int32_t       lu
+DBT    orig            DBT             s
+DBT    repl            DBT             s
+ARG    prefix          u_int32_t       lu
+ARG    suffix          u_int32_t       lu
+END
index 353ee7bc27877247530c50ca3d493283658595b2..45232bbc41c31c496594e3f86983494bcdf93f4f 100644 (file)
@@ -57,7 +57,7 @@ int __bam_pg_alloc_log(logp, txnid, ret_lsnp, flags,
            + sizeof(pgno)
            + sizeof(ptype)
            + sizeof(next);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -92,7 +92,7 @@ int __bam_pg_alloc_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -137,7 +137,7 @@ __bam_pg_alloc_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tptype: %lu\n", (u_long)argp->ptype);
        printf("\tnext: %lu\n", (u_long)argp->next);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -152,7 +152,7 @@ __bam_pg_alloc_read(recbuf, argpp)
        __bam_pg_alloc_args *argp;
        u_int8_t *bp;
 
-       argp = (__bam_pg_alloc_args *)malloc(sizeof(__bam_pg_alloc_args) +
+       argp = (__bam_pg_alloc_args *)__db_malloc(sizeof(__bam_pg_alloc_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -219,7 +219,7 @@ int __bam_pg_free_log(logp, txnid, ret_lsnp, flags,
            + sizeof(*meta_lsn)
            + sizeof(u_int32_t) + (header == NULL ? 0 : header->size)
            + sizeof(next);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -257,7 +257,7 @@ int __bam_pg_free_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -308,7 +308,7 @@ __bam_pg_free_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\n");
        printf("\tnext: %lu\n", (u_long)argp->next);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -323,7 +323,7 @@ __bam_pg_free_read(recbuf, argpp)
        __bam_pg_free_args *argp;
        u_int8_t *bp;
 
-       argp = (__bam_pg_free_args *)malloc(sizeof(__bam_pg_free_args) +
+       argp = (__bam_pg_free_args *)__db_malloc(sizeof(__bam_pg_free_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -400,7 +400,7 @@ int __bam_split_log(logp, txnid, ret_lsnp, flags,
            + sizeof(npgno)
            + sizeof(*nlsn)
            + sizeof(u_int32_t) + (pg == NULL ? 0 : pg->size);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -452,7 +452,7 @@ int __bam_split_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -509,7 +509,7 @@ __bam_split_print(notused1, dbtp, lsnp, notused3, notused4)
        }
        printf("\n");
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -524,7 +524,7 @@ __bam_split_read(recbuf, argpp)
        __bam_split_args *argp;
        u_int8_t *bp;
 
-       argp = (__bam_split_args *)malloc(sizeof(__bam_split_args) +
+       argp = (__bam_split_args *)__db_malloc(sizeof(__bam_split_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -563,11 +563,11 @@ __bam_split_read(recbuf, argpp)
 /*
  * PUBLIC: int __bam_rsplit_log
  * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
- * PUBLIC:     u_int32_t, db_pgno_t, DBT *, DBT *,
- * PUBLIC:     DB_LSN *));
+ * PUBLIC:     u_int32_t, db_pgno_t, DBT *, db_pgno_t,
+ * PUBLIC:     DBT *, DB_LSN *));
  */
 int __bam_rsplit_log(logp, txnid, ret_lsnp, flags,
-       fileid, pgno, pgdbt, rootent, rootlsn)
+       fileid, pgno, pgdbt, nrec, rootent, rootlsn)
        DB_LOG *logp;
        DB_TXN *txnid;
        DB_LSN *ret_lsnp;
@@ -575,6 +575,7 @@ int __bam_rsplit_log(logp, txnid, ret_lsnp, flags,
        u_int32_t fileid;
        db_pgno_t pgno;
        DBT *pgdbt;
+       db_pgno_t nrec;
        DBT *rootent;
        DB_LSN * rootlsn;
 {
@@ -597,9 +598,10 @@ int __bam_rsplit_log(logp, txnid, ret_lsnp, flags,
            + sizeof(fileid)
            + sizeof(pgno)
            + sizeof(u_int32_t) + (pgdbt == NULL ? 0 : pgdbt->size)
+           + sizeof(nrec)
            + sizeof(u_int32_t) + (rootent == NULL ? 0 : rootent->size)
            + sizeof(*rootlsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -623,6 +625,8 @@ int __bam_rsplit_log(logp, txnid, ret_lsnp, flags,
                memcpy(bp, pgdbt->data, pgdbt->size);
                bp += pgdbt->size;
        }
+       memcpy(bp, &nrec, sizeof(nrec));
+       bp += sizeof(nrec);
        if (rootent == NULL) {
                zero = 0;
                memcpy(bp, &zero, sizeof(u_int32_t));
@@ -645,7 +649,7 @@ int __bam_rsplit_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -692,6 +696,7 @@ __bam_rsplit_print(notused1, dbtp, lsnp, notused3, notused4)
                        printf("%#x ", c);
        }
        printf("\n");
+       printf("\tnrec: %lu\n", (u_long)argp->nrec);
        printf("\trootent: ");
        for (i = 0; i < argp->rootent.size; i++) {
                c = ((char *)argp->rootent.data)[i];
@@ -704,7 +709,7 @@ __bam_rsplit_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\trootlsn: [%lu][%lu]\n",
            (u_long)argp->rootlsn.file, (u_long)argp->rootlsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -719,7 +724,7 @@ __bam_rsplit_read(recbuf, argpp)
        __bam_rsplit_args *argp;
        u_int8_t *bp;
 
-       argp = (__bam_rsplit_args *)malloc(sizeof(__bam_rsplit_args) +
+       argp = (__bam_rsplit_args *)__db_malloc(sizeof(__bam_rsplit_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -739,6 +744,8 @@ __bam_rsplit_read(recbuf, argpp)
        bp += sizeof(u_int32_t);
        argp->pgdbt.data = bp;
        bp += argp->pgdbt.size;
+       memcpy(&argp->nrec, bp, sizeof(argp->nrec));
+       bp += sizeof(argp->nrec);
        memcpy(&argp->rootent.size, bp, sizeof(u_int32_t));
        bp += sizeof(u_int32_t);
        argp->rootent.data = bp;
@@ -789,7 +796,7 @@ int __bam_adj_log(logp, txnid, ret_lsnp, flags,
            + sizeof(indx)
            + sizeof(indx_copy)
            + sizeof(is_insert);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -821,7 +828,7 @@ int __bam_adj_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -865,7 +872,7 @@ __bam_adj_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tindx_copy: %lu\n", (u_long)argp->indx_copy);
        printf("\tis_insert: %lu\n", (u_long)argp->is_insert);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -880,7 +887,7 @@ __bam_adj_read(recbuf, argpp)
        __bam_adj_args *argp;
        u_int8_t *bp;
 
-       argp = (__bam_adj_args *)malloc(sizeof(__bam_adj_args) +
+       argp = (__bam_adj_args *)__db_malloc(sizeof(__bam_adj_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -948,7 +955,7 @@ int __bam_cadjust_log(logp, txnid, ret_lsnp, flags,
            + sizeof(indx)
            + sizeof(adjust)
            + sizeof(total);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -980,7 +987,7 @@ int __bam_cadjust_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -1024,7 +1031,7 @@ __bam_cadjust_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tadjust: %ld\n", (long)argp->adjust);
        printf("\ttotal: %ld\n", (long)argp->total);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -1039,7 +1046,7 @@ __bam_cadjust_read(recbuf, argpp)
        __bam_cadjust_args *argp;
        u_int8_t *bp;
 
-       argp = (__bam_cadjust_args *)malloc(sizeof(__bam_cadjust_args) +
+       argp = (__bam_cadjust_args *)__db_malloc(sizeof(__bam_cadjust_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -1102,7 +1109,7 @@ int __bam_cdel_log(logp, txnid, ret_lsnp, flags,
            + sizeof(pgno)
            + sizeof(*lsn)
            + sizeof(indx);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -1130,7 +1137,7 @@ int __bam_cdel_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -1172,7 +1179,7 @@ __bam_cdel_print(notused1, dbtp, lsnp, notused3, notused4)
            (u_long)argp->lsn.file, (u_long)argp->lsn.offset);
        printf("\tindx: %lu\n", (u_long)argp->indx);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -1187,7 +1194,7 @@ __bam_cdel_read(recbuf, argpp)
        __bam_cdel_args *argp;
        u_int8_t *bp;
 
-       argp = (__bam_cdel_args *)malloc(sizeof(__bam_cdel_args) +
+       argp = (__bam_cdel_args *)__db_malloc(sizeof(__bam_cdel_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -1211,6 +1218,225 @@ __bam_cdel_read(recbuf, argpp)
        return (0);
 }
 
+/*
+ * PUBLIC: int __bam_repl_log
+ * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
+ * PUBLIC:     u_int32_t, db_pgno_t, DB_LSN *, u_int32_t,
+ * PUBLIC:     u_int32_t, DBT *, DBT *, u_int32_t,
+ * PUBLIC:     u_int32_t));
+ */
+int __bam_repl_log(logp, txnid, ret_lsnp, flags,
+       fileid, pgno, lsn, indx, isdeleted, orig,
+       repl, prefix, suffix)
+       DB_LOG *logp;
+       DB_TXN *txnid;
+       DB_LSN *ret_lsnp;
+       u_int32_t flags;
+       u_int32_t fileid;
+       db_pgno_t pgno;
+       DB_LSN * lsn;
+       u_int32_t indx;
+       u_int32_t isdeleted;
+       DBT *orig;
+       DBT *repl;
+       u_int32_t prefix;
+       u_int32_t suffix;
+{
+       DBT logrec;
+       DB_LSN *lsnp, null_lsn;
+       u_int32_t zero;
+       u_int32_t rectype, txn_num;
+       int ret;
+       u_int8_t *bp;
+
+       rectype = DB_bam_repl;
+       txn_num = txnid == NULL ? 0 : txnid->txnid;
+       if (txnid == NULL) {
+               null_lsn.file = 0;
+               null_lsn.offset = 0;
+               lsnp = &null_lsn;
+       } else
+               lsnp = &txnid->last_lsn;
+       logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
+           + sizeof(fileid)
+           + sizeof(pgno)
+           + sizeof(*lsn)
+           + sizeof(indx)
+           + sizeof(isdeleted)
+           + sizeof(u_int32_t) + (orig == NULL ? 0 : orig->size)
+           + sizeof(u_int32_t) + (repl == NULL ? 0 : repl->size)
+           + sizeof(prefix)
+           + sizeof(suffix);
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
+               return (ENOMEM);
+
+       bp = logrec.data;
+       memcpy(bp, &rectype, sizeof(rectype));
+       bp += sizeof(rectype);
+       memcpy(bp, &txn_num, sizeof(txn_num));
+       bp += sizeof(txn_num);
+       memcpy(bp, lsnp, sizeof(DB_LSN));
+       bp += sizeof(DB_LSN);
+       memcpy(bp, &fileid, sizeof(fileid));
+       bp += sizeof(fileid);
+       memcpy(bp, &pgno, sizeof(pgno));
+       bp += sizeof(pgno);
+       if (lsn != NULL)
+               memcpy(bp, lsn, sizeof(*lsn));
+       else
+               memset(bp, 0, sizeof(*lsn));
+       bp += sizeof(*lsn);
+       memcpy(bp, &indx, sizeof(indx));
+       bp += sizeof(indx);
+       memcpy(bp, &isdeleted, sizeof(isdeleted));
+       bp += sizeof(isdeleted);
+       if (orig == NULL) {
+               zero = 0;
+               memcpy(bp, &zero, sizeof(u_int32_t));
+               bp += sizeof(u_int32_t);
+       } else {
+               memcpy(bp, &orig->size, sizeof(orig->size));
+               bp += sizeof(orig->size);
+               memcpy(bp, orig->data, orig->size);
+               bp += orig->size;
+       }
+       if (repl == NULL) {
+               zero = 0;
+               memcpy(bp, &zero, sizeof(u_int32_t));
+               bp += sizeof(u_int32_t);
+       } else {
+               memcpy(bp, &repl->size, sizeof(repl->size));
+               bp += sizeof(repl->size);
+               memcpy(bp, repl->data, repl->size);
+               bp += repl->size;
+       }
+       memcpy(bp, &prefix, sizeof(prefix));
+       bp += sizeof(prefix);
+       memcpy(bp, &suffix, sizeof(suffix));
+       bp += sizeof(suffix);
+#ifdef DEBUG
+       if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
+               fprintf(stderr, "Error in log record length");
+#endif
+       ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
+       if (txnid != NULL)
+               txnid->last_lsn = *ret_lsnp;
+       __db_free(logrec.data);
+       return (ret);
+}
+
+/*
+ * PUBLIC: int __bam_repl_print
+ * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
+ */
+
+int
+__bam_repl_print(notused1, dbtp, lsnp, notused3, notused4)
+       DB_LOG *notused1;
+       DBT *dbtp;
+       DB_LSN *lsnp;
+       int notused3;
+       void *notused4;
+{
+       __bam_repl_args *argp;
+       u_int32_t i;
+       int c, ret;
+
+       i = 0;
+       c = 0;
+       notused1 = NULL;
+       notused3 = 0;
+       notused4 = NULL;
+
+       if ((ret = __bam_repl_read(dbtp->data, &argp)) != 0)
+               return (ret);
+       printf("[%lu][%lu]bam_repl: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
+           (u_long)lsnp->file,
+           (u_long)lsnp->offset,
+           (u_long)argp->type,
+           (u_long)argp->txnid->txnid,
+           (u_long)argp->prev_lsn.file,
+           (u_long)argp->prev_lsn.offset);
+       printf("\tfileid: %lu\n", (u_long)argp->fileid);
+       printf("\tpgno: %lu\n", (u_long)argp->pgno);
+       printf("\tlsn: [%lu][%lu]\n",
+           (u_long)argp->lsn.file, (u_long)argp->lsn.offset);
+       printf("\tindx: %lu\n", (u_long)argp->indx);
+       printf("\tisdeleted: %lu\n", (u_long)argp->isdeleted);
+       printf("\torig: ");
+       for (i = 0; i < argp->orig.size; i++) {
+               c = ((char *)argp->orig.data)[i];
+               if (isprint(c) || c == 0xa)
+                       putchar(c);
+               else
+                       printf("%#x ", c);
+       }
+       printf("\n");
+       printf("\trepl: ");
+       for (i = 0; i < argp->repl.size; i++) {
+               c = ((char *)argp->repl.data)[i];
+               if (isprint(c) || c == 0xa)
+                       putchar(c);
+               else
+                       printf("%#x ", c);
+       }
+       printf("\n");
+       printf("\tprefix: %lu\n", (u_long)argp->prefix);
+       printf("\tsuffix: %lu\n", (u_long)argp->suffix);
+       printf("\n");
+       __db_free(argp);
+       return (0);
+}
+
+/*
+ * PUBLIC: int __bam_repl_read __P((void *, __bam_repl_args **));
+ */
+int
+__bam_repl_read(recbuf, argpp)
+       void *recbuf;
+       __bam_repl_args **argpp;
+{
+       __bam_repl_args *argp;
+       u_int8_t *bp;
+
+       argp = (__bam_repl_args *)__db_malloc(sizeof(__bam_repl_args) +
+           sizeof(DB_TXN));
+       if (argp == NULL)
+               return (ENOMEM);
+       argp->txnid = (DB_TXN *)&argp[1];
+       bp = recbuf;
+       memcpy(&argp->type, bp, sizeof(argp->type));
+       bp += sizeof(argp->type);
+       memcpy(&argp->txnid->txnid,  bp, sizeof(argp->txnid->txnid));
+       bp += sizeof(argp->txnid->txnid);
+       memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN));
+       bp += sizeof(DB_LSN);
+       memcpy(&argp->fileid, bp, sizeof(argp->fileid));
+       bp += sizeof(argp->fileid);
+       memcpy(&argp->pgno, bp, sizeof(argp->pgno));
+       bp += sizeof(argp->pgno);
+       memcpy(&argp->lsn, bp,  sizeof(argp->lsn));
+       bp += sizeof(argp->lsn);
+       memcpy(&argp->indx, bp, sizeof(argp->indx));
+       bp += sizeof(argp->indx);
+       memcpy(&argp->isdeleted, bp, sizeof(argp->isdeleted));
+       bp += sizeof(argp->isdeleted);
+       memcpy(&argp->orig.size, bp, sizeof(u_int32_t));
+       bp += sizeof(u_int32_t);
+       argp->orig.data = bp;
+       bp += argp->orig.size;
+       memcpy(&argp->repl.size, bp, sizeof(u_int32_t));
+       bp += sizeof(u_int32_t);
+       argp->repl.data = bp;
+       bp += argp->repl.size;
+       memcpy(&argp->prefix, bp, sizeof(argp->prefix));
+       bp += sizeof(argp->prefix);
+       memcpy(&argp->suffix, bp, sizeof(argp->suffix));
+       bp += sizeof(argp->suffix);
+       *argpp = argp;
+       return (0);
+}
+
 /*
  * PUBLIC: int __bam_init_print __P((DB_ENV *));
  */
@@ -1241,6 +1467,9 @@ __bam_init_print(dbenv)
        if ((ret = __db_add_recovery(dbenv,
            __bam_cdel_print, DB_bam_cdel)) != 0)
                return (ret);
+       if ((ret = __db_add_recovery(dbenv,
+           __bam_repl_print, DB_bam_repl)) != 0)
+               return (ret);
        return (0);
 }
 
@@ -1274,6 +1503,9 @@ __bam_init_recover(dbenv)
        if ((ret = __db_add_recovery(dbenv,
            __bam_cdel_recover, DB_bam_cdel)) != 0)
                return (ret);
+       if ((ret = __db_add_recovery(dbenv,
+           __bam_repl_recover, DB_bam_repl)) != 0)
+               return (ret);
        return (0);
 }
 
index 51d9262859b4cf8118377c47e36485219b506d71..74ba9ff42641c54da7264631e1c2aeff57b9cae4 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_appinit.c 10.33 (Sleepycat) 8/28/97";
+static const char sccsid[] = "@(#)db_appinit.c 10.36 (Sleepycat) 10/28/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -93,6 +93,10 @@ db_appinit(db_home, db_config, dbenv, flags)
            LF_ISSET(RECOVERY_FLAGS) != RECOVERY_FLAGS)
                return (__db_ferr(dbenv, "db_appinit", 1));
 
+       /* Convert the db_appinit(3) flags. */
+       if (LF_ISSET(DB_THREAD))
+               F_SET(dbenv, DB_ENV_THREAD);
+
        fp = NULL;
 
        /* Set the database home. */
@@ -126,7 +130,7 @@ db_appinit(db_home, db_config, dbenv, flags)
                goto err;
 
        /* Indicate that the path names have been set. */
-       F_SET(dbenv, DB_APP_INIT);
+       F_SET(dbenv, DB_ENV_APPINIT);
 
        /*
         * If we are doing recovery, remove all the regions.
@@ -300,7 +304,8 @@ __db_appname(dbenv, appname, dir, file, fdp, namep)
         * return.
         */
        if (file != NULL && __db_abspath(file))
-               return ((*namep = (char *)strdup(file)) == NULL ? ENOMEM : 0);
+               return ((*namep =
+                   (char *)__db_strdup(file)) == NULL ? ENOMEM : 0);
        if (dir != NULL && __db_abspath(dir)) {
                a = dir;
                goto done;
@@ -335,7 +340,7 @@ __db_appname(dbenv, appname, dir, file, fdp, namep)
         */
 retry: switch (appname) {
        case DB_APP_NONE:
-               if (dbenv == NULL || !F_ISSET(dbenv, DB_APP_INIT)) {
+               if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT)) {
                        if (dir == NULL)
                                goto tmp;
                        a = dir;
@@ -355,7 +360,7 @@ retry:      switch (appname) {
                        tmp_create = 1;
                        goto tmp;
                }
-               if (dbenv == NULL || !F_ISSET(dbenv, DB_APP_INIT))
+               if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT))
                        a = PATH_DOT;
                else {
                        a = dbenv->db_home;
@@ -367,7 +372,7 @@ retry:      switch (appname) {
                }
                break;
        case DB_APP_LOG:
-               if (dbenv == NULL || !F_ISSET(dbenv, DB_APP_INIT)) {
+               if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT)) {
                        if (dir == NULL)
                                goto tmp;
                        a = dir;
@@ -385,7 +390,7 @@ retry:      switch (appname) {
                }
 
                tmp_create = 1;
-               if (dbenv == NULL || !F_ISSET(dbenv, DB_APP_INIT))
+               if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT))
                        goto tmp;
                else {
                        a = dbenv->db_home;
@@ -396,7 +401,7 @@ retry:      switch (appname) {
 
        /* Reference a file from the appropriate temporary directory. */
        if (0) {
-tmp:           if (dbenv == NULL || !F_ISSET(dbenv, DB_APP_INIT)) {
+tmp:           if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT)) {
                        memset(&etmp, 0, sizeof(etmp));
                        if ((ret = __db_tmp_dir(&etmp, DB_USE_ENVIRON)) != 0)
                                return (ret);
@@ -412,7 +417,7 @@ done:       len =
            (c == NULL ? 0 : strlen(c) + 1) +
            (file == NULL ? 0 : strlen(file) + 1);
 
-       if ((start = (char *)malloc(len)) == NULL) {
+       if ((start = (char *)__db_malloc(len)) == NULL) {
                __db_err(dbenv, "%s", strerror(ENOMEM));
                if (tmp_free)
                        FREES(etmp.db_tmp_dir);
@@ -484,7 +489,7 @@ __db_home(dbenv, db_home, flags)
        if (p == NULL)
                return (0);
 
-       if ((dbenv->db_home = (char *)strdup(p)) == NULL) {
+       if ((dbenv->db_home = (char *)__db_strdup(p)) == NULL) {
                __db_err(dbenv, "%s", strerror(ENOMEM));
                return (ENOMEM);
        }
@@ -509,7 +514,7 @@ __db_parse(dbenv, s)
         * We need to strdup the argument in case the caller passed us
         * static data.
         */
-       if ((local_s = (char *)strdup(s)) == NULL)
+       if ((local_s = (char *)__db_strdup(s)) == NULL)
                return (ENOMEM);
 
        tp = local_s;
@@ -526,14 +531,15 @@ illegal:  ret = EINVAL;
 #define        DATA_INIT_CNT   20                      /* Start with 20 data slots. */
        if (!strcmp(name, "DB_DATA_DIR")) {
                if (dbenv->db_data_dir == NULL) {
-                       if ((dbenv->db_data_dir = (char **)calloc(DATA_INIT_CNT,
+                       if ((dbenv->db_data_dir =
+                           (char **)__db_calloc(DATA_INIT_CNT,
                            sizeof(char **))) == NULL)
                                goto nomem;
                        dbenv->data_cnt = DATA_INIT_CNT;
                } else if (dbenv->data_next == dbenv->data_cnt - 1) {
                        dbenv->data_cnt *= 2;
                        if ((dbenv->db_data_dir =
-                           (char **)realloc(dbenv->db_data_dir,
+                           (char **)__db_realloc(dbenv->db_data_dir,
                            dbenv->data_cnt * sizeof(char **))) == NULL)
                                goto nomem;
                }
@@ -549,7 +555,7 @@ illegal:    ret = EINVAL;
        } else
                goto err;
 
-       if ((*p = (char *)strdup(value)) == NULL) {
+       if ((*p = (char *)__db_strdup(value)) == NULL) {
 nomem:         ret = ENOMEM;
                __db_err(dbenv, "%s", strerror(ENOMEM));
        }
@@ -623,7 +629,7 @@ __db_tmp_dir(dbenv, flags)
                if (!Special2FSSpec(kTemporaryFolderType,
                    kOnSystemDisk, 0, &spec)) {
                        p = FSp2FullPath(&spec);
-                       sTempFolder = malloc(strlen(p) + 1);
+                       sTempFolder = __db_malloc(strlen(p) + 1);
                        strcpy(sTempFolder, p);
                        p = sTempFolder;
                }
@@ -639,7 +645,7 @@ __db_tmp_dir(dbenv, flags)
        if (p == NULL)
                return (0);
 
-       if ((dbenv->db_tmp_dir = (char *)strdup(p)) == NULL) {
+       if ((dbenv->db_tmp_dir = (char *)__db_strdup(p)) == NULL) {
                __db_err(dbenv, "%s", strerror(ENOMEM));
                return (ENOMEM);
        }
@@ -722,7 +728,7 @@ __db_tmp_open(dbenv, dir, fdp)
                (void)sigprocmask(SIG_BLOCK, &set, &oset);
 #endif
 #define        DB_TEMPOPEN     DB_CREATE | DB_EXCL | DB_TEMPORARY
-               if ((ret = __db_fdopen(buf,
+               if ((ret = __db_open(buf,
                    DB_TEMPOPEN, DB_TEMPOPEN, S_IRUSR | S_IWUSR, fdp)) == 0) {
 #ifdef HAVE_SIGFILLSET
                        (void)sigprocmask(SIG_SETMASK, &oset, NULL);
index 2e946737317cf9e377e8c19cc24a7ba3ad0446bd..ac0176d70f3600fda1797d04df2236aa1b327bae 100644 (file)
@@ -11,7 +11,7 @@
 static const char copyright[] =
 "@(#) Copyright (c) 1997\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_apprec.c  10.16 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)db_apprec.c  10.18 (Sleepycat) 9/30/97";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -31,12 +31,6 @@ static const char sccsid[] = "@(#)db_apprec.c        10.16 (Sleepycat) 8/27/97";
 #include "txn.h"
 #include "common_ext.h"
 
-#define        FREE_DBT(L, D) {                                                \
-       if (F_ISSET((L), DB_AM_THREAD) && (D).data != NULL)             \
-               free((D).data);                                         \
-               (D).data = NULL;                                        \
-       }                                                               \
-
 /*
  * __db_apprec --
  *     Perform recovery.
@@ -52,13 +46,22 @@ __db_apprec(dbenv, flags)
        DB_LOG *lp;
        DB_LSN ckp_lsn, first_lsn, lsn, tmp_lsn;
        time_t now;
-       int first_flag, ret;
+       int first_flag, is_thread, ret;
        void *txninfo;
 
+       lp = dbenv->lg_info;
+
        /* Initialize the transaction list. */
        if ((ret = __db_txnlist_init(&txninfo)) != 0)
                return (ret);
 
+       /*
+        * Save the state of the thread flag -- we don't need it on at the
+        * moment because we're single-threaded until recovery is complete.
+        */
+       is_thread = F_ISSET(lp, DB_AM_THREAD);
+       F_CLR(lp, DB_AM_THREAD);
+
        /*
         * Read forward through the log, opening the appropriate files so that
         * we can call recovery routines.  In general, we start at the last
@@ -66,20 +69,18 @@ __db_apprec(dbenv, flags)
         * recovery, we begin at the first LSN that appears in any log file
         * (log_get figures this out for us when we pass it the DB_FIRST flag).
         */
-       lp = dbenv->lg_info;
        if (LF_ISSET(DB_RECOVER_FATAL))
                first_flag = DB_FIRST;
        else {
-               if ((ret = __log_findckp(lp, &lsn)) == DB_NOTFOUND)
+               if ((ret = __log_findckp(lp, &lsn)) == DB_NOTFOUND) {
+                       F_SET(lp, is_thread);
                        return (0);
+               }
                first_flag = DB_SET;
        }
 
        /* If we're a threaded application, we have to allocate space. */
        memset(&data, 0, sizeof(data));
-       if (F_ISSET(lp, DB_AM_THREAD))
-               F_SET(&data, DB_DBT_MALLOC);
-
        if ((ret = log_get(lp, &lsn, &data, first_flag)) != 0) {
                __db_err(dbenv, "Failure: unable to get log record");
                if (first_flag == DB_SET)
@@ -93,7 +94,6 @@ __db_apprec(dbenv, flags)
        first_lsn = lsn;
        for (;;) {
                ret = __db_dispatch(lp, &data, &lsn, TXN_OPENFILES, txninfo);
-               FREE_DBT(lp, data);
                if (ret != 0 && ret != DB_TXN_CKP)
                        goto msgerr;
                if ((ret =
@@ -103,7 +103,6 @@ __db_apprec(dbenv, flags)
                        break;
                }
        }
-       FREE_DBT(lp, data);
 
        /*
         * Initialize the ckp_lsn to 0,0.  If we never find a valid
@@ -116,7 +115,6 @@ __db_apprec(dbenv, flags)
                tmp_lsn = lsn;
                ret = __db_dispatch(lp,
                    &data, &lsn, TXN_BACKWARD_ROLL, txninfo);
-               FREE_DBT(lp, data);
                if (ret == DB_TXN_CKP) {
                        if (IS_ZERO_LSN(ckp_lsn))
                                ckp_lsn = tmp_lsn;
@@ -124,20 +122,17 @@ __db_apprec(dbenv, flags)
                } else if (ret != 0)
                        goto msgerr;
        }
-       FREE_DBT(lp, data);
        if (ret != 0 && ret != DB_NOTFOUND)
                goto err;
 
        for (ret = log_get(lp, &lsn, &data, DB_NEXT);
            ret == 0; ret = log_get(lp, &lsn, &data, DB_NEXT)) {
                ret = __db_dispatch(lp, &data, &lsn, TXN_FORWARD_ROLL, txninfo);
-               FREE_DBT(lp, data);
                if (ret == DB_TXN_CKP)
                        ret = 0;
                else if (ret != 0)
                        goto msgerr;
        }
-       FREE_DBT(lp, data);
        if (ret != DB_NOTFOUND)
                goto err;
 
@@ -165,11 +160,12 @@ __db_apprec(dbenv, flags)
                    (u_long)dbenv->tx_info->region->last_ckp.offset);
        }
 
+       F_SET(lp, is_thread);
        return (0);
 
 msgerr:        __db_err(dbenv, "Recovery function for LSN %lu %lu failed",
            (u_long)lsn.file, (u_long)lsn.offset);
 
-err:   FREE_DBT(lp, data);
+err:   F_SET(lp, is_thread);
        return (ret);
 }
index a8d771545509af51c709fd0b56e9121e0c0c6819..e4861320733bbe3c1dcb7a151ed5f6e26307fde2 100644 (file)
@@ -8,20 +8,20 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_byteorder.c       10.3 (Sleepycat) 6/21/97";
+static const char sccsid[] = "@(#)db_byteorder.c       10.4 (Sleepycat) 9/4/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <errno.h>
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#if BYTE_ORDER == BIG_ENDIAN
+#define        WORDS_BIGENDIAN 1
+#endif
 #endif
 
-#ifdef HAVE_ENDIAN_H
-# include <endian.h>
-# if BYTE_ORDER == BIG_ENDIAN
-#  define WORDS_BIGENDIAN 1
-# endif
+#include <errno.h>
 #endif
 
 #include "db_int.h"
index 86d79a8148e6310ff1a4d7fbd82adeca3a43dff0..3e8cd2dc66c656da3f66442e1c5b69e06de2eaf4 100644 (file)
@@ -43,7 +43,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_region.c  10.13 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)db_region.c  10.15 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -114,7 +114,7 @@ __db_rcreate(dbenv, appname, path, file, mode, size, fdp, retp)
         * attempts to create the region will return failure in one of the
         * attempts.
         */
-       if (fd == -1 && (ret = __db_fdopen(name,
+       if (fd == -1 && (ret = __db_open(name,
            DB_CREATE | DB_EXCL, DB_CREATE | DB_EXCL, mode, &fd)) != 0) {
                if (ret != EEXIST)
                        __db_err(dbenv,
@@ -131,6 +131,42 @@ __db_rcreate(dbenv, appname, path, file, mode, size, fdp, retp)
        if ((ret = __db_rmap(dbenv, fd, size, &rp)) != 0)
                goto err;
 
+       /* Initialize the region. */
+       if ((ret = __db_rinit(dbenv, rp, fd, size, 1)) != 0)
+               goto err;
+
+       if (name != NULL)
+               FREES(name);
+
+       *(void **)retp = rp;
+       return (0);
+
+err:   if (fd != -1) {
+               if (rp != NULL)
+                       (void)__db_unmap(rp, rp->size);
+               (void)__db_unlink(name);
+               (void)__db_close(fd);
+       }
+       if (name != NULL)
+               FREES(name);
+       return (ret);
+}
+
+/*
+ * __db_rinit --
+ *     Initialize the region.
+ *
+ * PUBLIC: int __db_rinit __P((DB_ENV *, RLAYOUT *, int, size_t, int));
+ */
+int
+__db_rinit(dbenv, rp, fd, size, lock_region)
+       DB_ENV *dbenv;
+       RLAYOUT *rp;
+       size_t size;
+       int fd, lock_region;
+{
+       int ret;
+
        /*
         * Initialize the common information.
         *
@@ -141,9 +177,12 @@ __db_rcreate(dbenv, appname, path, file, mode, size, fdp, retp)
         * file permissions games, but we can't because WNT filesystems won't
         * open a file mode 0.
         *
-        * So, the process that's creating the region always acquires the lock
-        * before the setting the version number.  Any process joining always
-        * checks the version number before attempting to acquire the lock.
+        * If the lock_region flag is set, the process creating the region
+        * acquires the lock before the setting the version number.  Any
+        * process joining the region checks the version number before
+        * attempting to acquire the lock.  (The lock_region flag may not be
+        * set -- the mpool code sometimes malloc's private regions but still
+        * needs to initialize them, specifically, the mutex for threads.)
         *
         * We have to check the version number first, because if the version
         * number has not been written, it's possible that the mutex has not
@@ -151,30 +190,16 @@ __db_rcreate(dbenv, appname, path, file, mode, size, fdp, retp)
         * random behavior.  If the version number isn't there (the file size
         * is too small) or it's 0, we know that the region is being created.
         */
-       (void)__db_mutex_init(&rp->lock, MUTEX_LOCK_OFFSET(rp, &rp->lock));
-       (void)__db_mutex_lock(&rp->lock,
-           fd, dbenv == NULL ? NULL : dbenv->db_yield);
+       __db_mutex_init(&rp->lock, MUTEX_LOCK_OFFSET(rp, &rp->lock));
+       if (lock_region && (ret = __db_mutex_lock(&rp->lock, fd)) != 0)
+               return (ret);
 
        rp->refcnt = 1;
        rp->size = size;
        rp->flags = 0;
        db_version(&rp->majver, &rp->minver, &rp->patch);
 
-       if (name != NULL)
-               FREES(name);
-
-       *(void **)retp = rp;
        return (0);
-
-err:   if (fd != -1) {
-               if (rp != NULL)
-                       (void)__db_munmap(rp, rp->size);
-               (void)__db_unlink(name);
-               (void)__db_close(fd);
-       }
-       if (name != NULL)
-               FREES(name);
-       return (ret);
 }
 
 /*
@@ -205,7 +230,7 @@ __db_ropen(dbenv, appname, path, file, flags, fdp, retp)
                return (ret);
 
        /* Open the file. */
-       if ((ret = __db_fdopen(name, flags, DB_MUTEXDEBUG, 0, &fd)) != 0) {
+       if ((ret = __db_open(name, flags, DB_MUTEXDEBUG, 0, &fd)) != 0) {
                __db_err(dbenv, "region open: %s: %s", name, strerror(ret));
                goto err2;
        }
@@ -225,8 +250,10 @@ __db_ropen(dbenv, appname, path, file, flags, fdp, retp)
         * flatly impossible.  Hope that mmap fails if the file is too large.
         *
         */
-       if ((ret = __db_stat(dbenv, name, fd, &size1, NULL)) != 0)
+       if ((ret = __db_ioinfo(name, fd, &size1, NULL)) != 0) {
+               __db_err(dbenv, "%s: %s", name, strerror(ret));
                goto err2;
+       }
 
        /* Check to make sure the first block has been written. */
        if ((size_t)size1 < sizeof(RLAYOUT)) {
@@ -249,16 +276,17 @@ __db_ropen(dbenv, appname, path, file, flags, fdp, retp)
 
        /* Get the region lock. */
        if (!LF_ISSET(DB_MUTEXDEBUG))
-               (void)__db_mutex_lock(&rp->lock,
-                   fd, dbenv == NULL ? NULL : dbenv->db_yield);
+               (void)__db_mutex_lock(&rp->lock, fd);
 
        /*
         * The file may have been half-written if we were descheduled between
         * getting the size of the file and checking the major version.  Check
         * to make sure we got the entire file.
         */
-       if ((ret = __db_stat(dbenv, name, fd, &size2, NULL)) != 0)
+       if ((ret = __db_ioinfo(name, fd, &size2, NULL)) != 0) {
+               __db_err(dbenv, "%s: %s", name, strerror(ret));
                goto err1;
+       }
        if (size1 != size2) {
                ret = EAGAIN;
                goto err1;
@@ -285,7 +313,7 @@ __db_ropen(dbenv, appname, path, file, flags, fdp, retp)
 err1:  if (!LF_ISSET(DB_MUTEXDEBUG))
                (void)__db_mutex_unlock(&rp->lock, fd);
 err2:  if (rp != NULL)
-               (void)__db_munmap(rp, rp->size);
+               (void)__db_unmap(rp, rp->size);
        if (fd != -1)
                (void)__db_close(fd);
        FREES(name);
@@ -312,8 +340,7 @@ __db_rclose(dbenv, fd, ptr)
        fail = NULL;
 
        /* Get the lock. */
-       if ((ret = __db_mutex_lock(&rp->lock,
-           fd, dbenv == NULL ? NULL : dbenv->db_yield)) != 0) {
+       if ((ret = __db_mutex_lock(&rp->lock, fd)) != 0) {
                fail = "lock get";
                goto err;
        }
@@ -328,7 +355,7 @@ __db_rclose(dbenv, fd, ptr)
        }
 
        /* Discard the region. */
-       if ((t_ret = __db_munmap(ptr, rp->size)) != 0 && fail == NULL) {
+       if ((t_ret = __db_unmap(ptr, rp->size)) != 0 && fail == NULL) {
                ret = t_ret;
                fail = "munmap";
        }
@@ -392,8 +419,7 @@ __db_runlink(dbenv, appname, path, file, force)
        /* Open and lock the region. */
        if ((ret = __db_ropen(dbenv, appname, path, file, 0, &fd, &rp)) != 0)
                goto err1;
-       (void)__db_mutex_lock(&rp->lock,
-           fd, dbenv == NULL ? NULL : dbenv->db_yield);
+       (void)__db_mutex_lock(&rp->lock, fd);
 
        /* If the region is currently being deleted, fail. */
        if (F_ISSET(rp, DB_R_DELETED)) {
@@ -434,8 +460,7 @@ __db_runlink(dbenv, appname, path, file, force)
        /* Not a clue.  Try to clear the DB_R_DELETED flag. */
        if ((ret = __db_ropen(dbenv, appname, path, file, 0, &fd, &rp)) != 0)
                goto err1;
-       (void)__db_mutex_lock(&rp->lock,
-           fd, dbenv == NULL ? NULL : dbenv->db_yield);
+       (void)__db_mutex_lock(&rp->lock, fd);
        F_CLR(rp, DB_R_DELETED);
        /* FALLTHROUGH */
 
@@ -472,7 +497,7 @@ __db_rgrow(dbenv, fd, incr)
        char buf[__DB_VMPAGESIZE];
 
        /* Seek to the end of the region. */
-       if ((ret = __db_lseek(fd, 0, 0, 0, SEEK_END)) != 0)
+       if ((ret = __db_seek(fd, 0, 0, 0, SEEK_END)) != 0)
                goto err;
 
        /* Write nuls to the new bytes. */
@@ -500,7 +525,7 @@ __db_rgrow(dbenv, fd, incr)
        incr -= incr % __DB_VMPAGESIZE;
 
        /* Write the last page, not the page after the last. */
-       if ((ret = __db_lseek(fd, 0, 0, incr - __DB_VMPAGESIZE, SEEK_CUR)) != 0)
+       if ((ret = __db_seek(fd, 0, 0, incr - __DB_VMPAGESIZE, SEEK_CUR)) != 0)
                goto err;
        if ((ret = __db_write(fd, buf, sizeof(buf), &nw)) != 0)
                goto err;
@@ -531,7 +556,7 @@ __db_rremap(dbenv, ptr, oldsize, newsize, fd, retp)
 {
        int ret;
 
-       if ((ret = __db_munmap(ptr, oldsize)) != 0) {
+       if ((ret = __db_unmap(ptr, oldsize)) != 0) {
                __db_err(dbenv, "region remap: munmap: %s", strerror(ret));
                return (ret);
        }
@@ -553,7 +578,7 @@ __db_rmap(dbenv, fd, size, retp)
        RLAYOUT *rp;
        int ret;
 
-       if ((ret = __db_mmap(fd, size, 0, 0, &rp)) != 0) {
+       if ((ret = __db_map(fd, size, 0, 0, (void **)&rp)) != 0) {
                __db_err(dbenv, "region map: mmap %s", strerror(ret));
                return (ret);
        }
index 6911002ed54018edf450ef24106e4cad9f9e5214..fb2d6bb3dabf5aae0ac1872a522af0023ad83187 100644 (file)
--- a/db2/db.h
+++ b/db2/db.h
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db.h.src    10.77 (Sleepycat) 9/24/97
+ *     @(#)db.h.src    10.91 (Sleepycat) 11/3/97
  */
 
 #ifndef _DB_H_
  * XXX
  * Handle function prototypes and the keyword "const".  This steps on name
  * space that DB doesn't control, but all of the other solutions are worse.
+ *
+ * XXX
+ * While Microsoft's compiler is ANSI C compliant, it doesn't have _STDC_
+ * defined by default, you specify a command line flag or #pragma to turn
+ * it on.  Don't do that, however, because some of Microsoft's own header
+ * files won't compile.
  */
 #undef __P
-#if defined(__STDC__) || defined(__cplusplus)
+#if defined(__STDC__) || defined(__cplusplus) || defined(_MSC_VER)
 #define        __P(protos)     protos          /* ANSI C prototypes */
 #else
 #define        const
@@ -67,8 +73,8 @@
 
 #define        DB_VERSION_MAJOR        2
 #define        DB_VERSION_MINOR        3
-#define        DB_VERSION_PATCH        10
-#define        DB_VERSION_STRING       "Sleepycat Software: DB 2.3.10: (9/24/97)"
+#define        DB_VERSION_PATCH        12
+#define        DB_VERSION_STRING       "Sleepycat Software: DB 2.3.12: (11/3/97)"
 
 typedef        u_int32_t       db_pgno_t;      /* Page number type. */
 typedef        u_int16_t       db_indx_t;      /* Page offset type. */
@@ -93,6 +99,7 @@ struct __db_lockregion;       typedef struct __db_lockregion DB_LOCKREGION;
 struct __db_lockreq;   typedef struct __db_lockreq DB_LOCKREQ;
 struct __db_locktab;   typedef struct __db_locktab DB_LOCKTAB;
 struct __db_log;       typedef struct __db_log DB_LOG;
+struct __db_log_stat;  typedef struct __db_log_stat DB_LOG_STAT;
 struct __db_lsn;       typedef struct __db_lsn DB_LSN;
 struct __db_mpool;     typedef struct __db_mpool DB_MPOOL;
 struct __db_mpool_fstat;typedef struct __db_mpool_fstat DB_MPOOL_FSTAT;
@@ -121,6 +128,31 @@ struct __db_dbt {
        u_int32_t flags;
 };
 
+/*
+ * DB configuration.  There are a set of functions which the application
+ * can replace with its own versions.
+ */
+#define        DB_FUNC_CALLOC   1              /* ANSI C calloc. */
+#define        DB_FUNC_CLOSE    2              /* POSIX 1003.1 close. */
+#define        DB_FUNC_DIRFREE  3              /* DB: free directory list. */
+#define        DB_FUNC_DIRLIST  4              /* DB: create directory list. */
+#define        DB_FUNC_EXISTS   5              /* DB: return if file exists. */
+#define        DB_FUNC_FREE     6              /* ANSI C free. */
+#define        DB_FUNC_FSYNC    7              /* POSIX 1003.1 fsync. */
+#define        DB_FUNC_IOINFO   8              /* DB: return file I/O information. */
+#define        DB_FUNC_MALLOC   9              /* ANSI C malloc. */
+#define        DB_FUNC_MAP     10              /* DB: map file into shared memory. */
+#define        DB_FUNC_OPEN    11              /* POSIX 1003.1 open. */
+#define        DB_FUNC_READ    12              /* POSIX 1003.1 read. */
+#define        DB_FUNC_REALLOC 13              /* ANSI C realloc. */
+#define        DB_FUNC_SEEK    14              /* POSIX 1003.1 lseek. */
+#define        DB_FUNC_SLEEP   15              /* DB: sleep secs/usecs. */
+#define        DB_FUNC_STRDUP  16              /* ANSI C strdup. */
+#define        DB_FUNC_UNLINK  17              /* POSIX 1003.1 unlink. */
+#define        DB_FUNC_UNMAP   18              /* DB: unmap shared memory file. */
+#define        DB_FUNC_WRITE   19              /* POSIX 1003.1 write. */
+#define        DB_FUNC_YIELD   20              /* DB: yield thread to scheduler. */
+
 /*
  * Database configuration and initialization.
  */
@@ -134,21 +166,20 @@ struct __db_dbt {
 /*
  * Flags understood by db_appinit(3).
  *
- * DB_APP_INIT and DB_MUTEXDEBUG are internal only, and not documented.
+ * DB_MUTEXDEBUG is internal only, and not documented.
  */
 /*                             0x00007    COMMON MASK. */
-#define        DB_APP_INIT             0x00008 /* Appinit called, paths initialized. */
-#define        DB_INIT_LOCK            0x00010 /* Initialize locking. */
-#define        DB_INIT_LOG             0x00020 /* Initialize logging. */
-#define        DB_INIT_MPOOL           0x00040 /* Initialize mpool. */
-#define        DB_INIT_TXN             0x00080 /* Initialize transactions. */
-#define        DB_MPOOL_PRIVATE        0x00100 /* Mpool: private memory pool. */
-#define        DB_MUTEXDEBUG           0x00200 /* Do not get/set mutexes in regions. */
-#define        DB_RECOVER              0x00400 /* Run normal recovery. */
-#define        DB_RECOVER_FATAL        0x00800 /* Run catastrophic recovery. */
-#define        DB_TXN_NOSYNC           0x01000 /* Do not sync log on commit. */
-#define        DB_USE_ENVIRON          0x02000 /* Use the environment. */
-#define        DB_USE_ENVIRON_ROOT     0x04000 /* Use the environment if root. */
+#define        DB_INIT_LOCK            0x00008 /* Initialize locking. */
+#define        DB_INIT_LOG             0x00010 /* Initialize logging. */
+#define        DB_INIT_MPOOL           0x00020 /* Initialize mpool. */
+#define        DB_INIT_TXN             0x00040 /* Initialize transactions. */
+#define        DB_MPOOL_PRIVATE        0x00080 /* Mpool: private memory pool. */
+#define        DB_MUTEXDEBUG           0x00100 /* Do not get/set mutexes in regions. */
+#define        DB_RECOVER              0x00200 /* Run normal recovery. */
+#define        DB_RECOVER_FATAL        0x00400 /* Run catastrophic recovery. */
+#define        DB_TXN_NOSYNC           0x00800 /* Do not sync log on commit. */
+#define        DB_USE_ENVIRON          0x01000 /* Use the environment. */
+#define        DB_USE_ENVIRON_ROOT     0x02000 /* Use the environment if root. */
 
 /* CURRENTLY UNUSED LOCK FLAGS. */
 #define        DB_TXN_LOCK_2PL         0x00000 /* Two-phase locking. */
@@ -209,7 +240,6 @@ struct __db_env {
        int              lk_modes;      /* Number of lock modes in table. */
        unsigned int     lk_max;        /* Maximum number of locks. */
        u_int32_t        lk_detect;     /* Deadlock detect on every conflict. */
-       int (*db_yield) __P((void));    /* Yield function for threads. */
 
        /* Logging. */
        DB_LOG          *lg_info;       /* Return from log_open(). */
@@ -226,6 +256,9 @@ struct __db_env {
        int (*tx_recover)               /* Dispatch function for recovery. */
            __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 
+#define        DB_ENV_APPINIT          0x01    /* Paths initialized by db_appinit(). */
+#define        DB_ENV_STANDALONE       0x02    /* Test: freestanding environment. */
+#define        DB_ENV_THREAD           0x04    /* DB_ENV is multi-threaded. */
        u_int32_t        flags;         /* Flags. */
 };
 
@@ -301,7 +334,7 @@ struct __db_info {
 #define        DB_CURRENT      0x000010        /* c_get(), c_put(), log_get() */
 #define        DB_FIRST        0x000020        /* c_get(), log_get() */
 #define        DB_FLUSH        0x000040        /* log_put() */
-#define        DB_GET_RECNO    0x000080        /* c_get() */
+#define        DB_GET_RECNO    0x000080        /* get(), c_get() */
 #define        DB_KEYFIRST     0x000100        /* c_put() */
 #define        DB_KEYLAST      0x000200        /* c_put() */
 #define        DB_LAST         0x000400        /* c_get(), log_get() */
@@ -312,7 +345,7 @@ struct __db_info {
 #define        DB_RECORDCOUNT  0x008000        /* stat() */
 #define        DB_SET          0x010000        /* c_get(), log_get() */
 #define        DB_SET_RANGE    0x020000        /* c_get() */
-#define        DB_SET_RECNO    0x040000        /* get(), c_get() */
+#define        DB_SET_RECNO    0x040000        /* c_get() */
 
 /* DB (user visible) error return codes. */
 #define        DB_INCOMPLETE           ( -1)   /* Sync didn't finish. */
@@ -472,6 +505,8 @@ struct __db_bt_stat {
        u_int32_t bt_get;               /* Items retrieved. */
        u_int32_t bt_cache_hit;         /* Hits in fast-insert code. */
        u_int32_t bt_cache_miss;        /* Misses in fast-insert code. */
+       u_int32_t bt_magic;             /* Magic number. */
+       u_int32_t bt_version;           /* Version number. */
 };
 
 #if defined(__cplusplus)
@@ -479,6 +514,7 @@ extern "C" {
 #endif
 int   db_appinit __P((const char *, char * const *, DB_ENV *, int));
 int   db_appexit __P((DB_ENV *));
+int   db_jump_set __P((void *, int));
 int   db_open __P((const char *, DBTYPE, int, int, DB_ENV *, DB_INFO *, DB **));
 char *db_version __P((int *, int *, int *));
 #if defined(__cplusplus)
@@ -576,6 +612,22 @@ struct __db_lsn {
        u_int32_t       offset;         /* File offset. */
 };
 
+/* Log statistics structure. */
+struct __db_log_stat {
+       u_int32_t st_magic;             /* Log file magic number. */
+       u_int32_t st_version;           /* Log file version number. */
+       int st_mode;                    /* Log file mode. */
+       u_int32_t st_lg_max;            /* Maximum log file size. */
+       u_int32_t st_w_bytes;           /* Bytes to log. */
+       u_int32_t st_w_mbytes;          /* Megabytes to log. */
+       u_int32_t st_wc_bytes;          /* Bytes to log since checkpoint. */
+       u_int32_t st_wc_mbytes;         /* Megabytes to log since checkpoint. */
+       u_int32_t st_wcount;            /* Total syncs to the log. */
+       u_int32_t st_scount;            /* Total writes to the log. */
+       u_int32_t st_region_wait;       /* Region lock granted after wait. */
+       u_int32_t st_region_nowait;     /* Region lock granted without wait. */
+};
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -588,6 +640,7 @@ int  log_get __P((DB_LOG *, DB_LSN *, DBT *, int));
 int     log_open __P((const char *, int, int, DB_ENV *, DB_LOG **));
 int     log_put __P((DB_LOG *, DB_LSN *, const DBT *, int));
 int     log_register __P((DB_LOG *, DB *, const char *, DBTYPE, u_int32_t *));
+int     log_stat __P((DB_LOG *, DB_LOG_STAT **, void *(*)(size_t)));
 int     log_unlink __P((const char *, int, DB_ENV *));
 int     log_unregister __P((DB_LOG *, u_int32_t));
 #if defined(__cplusplus)
@@ -610,30 +663,35 @@ int        log_unregister __P((DB_LOG *, u_int32_t));
 /* Mpool statistics structure. */
 struct __db_mpool_stat {
        size_t st_cachesize;            /* Cache size. */
-       unsigned long st_cache_hit;     /* Pages found in the cache. */
-       unsigned long st_cache_miss;    /* Pages not found in the cache. */
-       unsigned long st_map;           /* Pages from mapped files. */
-       unsigned long st_page_create;   /* Pages created in the cache. */
-       unsigned long st_page_in;       /* Pages read in. */
-       unsigned long st_page_out;      /* Pages written out. */
-       unsigned long st_ro_evict;      /* Read-only pages evicted. */
-       unsigned long st_rw_evict;      /* Read-write pages evicted. */
-       unsigned long st_hash_buckets;  /* Number of hash buckets. */
-       unsigned long st_hash_searches; /* Total hash chain searches. */
-       unsigned long st_hash_longest;  /* Longest hash chain searched. */
-       unsigned long st_hash_examined; /* Total hash entries searched. */
+       u_int32_t st_cache_hit;         /* Pages found in the cache. */
+       u_int32_t st_cache_miss;        /* Pages not found in the cache. */
+       u_int32_t st_map;               /* Pages from mapped files. */
+       u_int32_t st_page_create;       /* Pages created in the cache. */
+       u_int32_t st_page_in;           /* Pages read in. */
+       u_int32_t st_page_out;          /* Pages written out. */
+       u_int32_t st_ro_evict;          /* Clean pages forced from the cache. */
+       u_int32_t st_rw_evict;          /* Dirty pages forced from the cache. */
+       u_int32_t st_hash_buckets;      /* Number of hash buckets. */
+       u_int32_t st_hash_searches;     /* Total hash chain searches. */
+       u_int32_t st_hash_longest;      /* Longest hash chain searched. */
+       u_int32_t st_hash_examined;     /* Total hash entries searched. */
+       u_int32_t st_page_clean;        /* Clean pages. */
+       u_int32_t st_page_dirty;        /* Dirty pages. */
+       u_int32_t st_page_trickle;      /* Pages written by memp_trickle. */
+       u_int32_t st_region_wait;       /* Region lock granted after wait. */
+       u_int32_t st_region_nowait;     /* Region lock granted without wait. */
 };
 
 /* Mpool file statistics structure. */
 struct __db_mpool_fstat {
        char *file_name;                /* File name. */
        size_t st_pagesize;             /* Page size. */
-       unsigned long st_cache_hit;     /* Pages found in the cache. */
-       unsigned long st_cache_miss;    /* Pages not found in the cache. */
-       unsigned long st_map;           /* Pages from mapped files. */
-       unsigned long st_page_create;   /* Pages created in the cache. */
-       unsigned long st_page_in;       /* Pages read in. */
-       unsigned long st_page_out;      /* Pages written out. */
+       u_int32_t st_cache_hit;         /* Pages found in the cache. */
+       u_int32_t st_cache_miss;        /* Pages not found in the cache. */
+       u_int32_t st_map;               /* Pages from mapped files. */
+       u_int32_t st_page_create;       /* Pages created in the cache. */
+       u_int32_t st_page_in;           /* Pages read in. */
+       u_int32_t st_page_out;          /* Pages written out. */
 };
 
 #if defined(__cplusplus)
@@ -654,6 +712,7 @@ int memp_register __P((DB_MPOOL *, int,
 int    memp_stat __P((DB_MPOOL *,
            DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, void *(*)(size_t)));
 int    memp_sync __P((DB_MPOOL *, DB_LSN *));
+int    memp_trickle __P((DB_MPOOL *, int, int *));
 int    memp_unlink __P((const char *, int, DB_ENV *));
 #if defined(__cplusplus)
 };
index 9ebe73cf6e8cf54101649c96bb4f729d5d638d9d..50b14eba7c1ea9bfec1f228008fbeae22d0e5350 100644 (file)
@@ -44,7 +44,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db.c 10.41 (Sleepycat) 9/23/97";
+static const char sccsid[] = "@(#)db.c 10.44 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -125,13 +125,19 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
        if ((ret = __db_fchk(dbenv, "db_open", flags, OKFLAGS)) != 0)
                return (ret);
 
+       if (dbenv != NULL &&
+           LF_ISSET(DB_THREAD) && !F_ISSET(dbenv, DB_ENV_THREAD)) {
+               __db_err(dbenv, "environment not created using DB_THREAD");
+               return (EINVAL);
+       }
+
        /* Initialize for error return. */
        fd = -1;
        need_fileid = 1;
        real_name = NULL;
 
        /* Allocate the DB structure, reference the DB_ENV structure. */
-       if ((dbp = (DB *)calloc(1, sizeof(DB))) == NULL) {
+       if ((dbp = (DB *)__db_calloc(1, sizeof(DB))) == NULL) {
                __db_err(dbenv, "%s", strerror(ENOMEM));
                return (ENOMEM);
        }
@@ -239,7 +245,7 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
                 */
                retry_cnt = 0;
 open_retry:    if (LF_ISSET(DB_CREATE)) {
-                       if ((ret = __db_fdopen(real_name, flags | DB_EXCL,
+                       if ((ret = __db_open(real_name, flags | DB_EXCL,
                            OKFLAGS | DB_EXCL, mode, &fd)) != 0)
                                if (ret == EEXIST) {
                                        LF_CLR(DB_CREATE);
@@ -250,7 +256,7 @@ open_retry: if (LF_ISSET(DB_CREATE)) {
                                        goto err;
                                }
                } else
-                       if ((ret = __db_fdopen(real_name,
+                       if ((ret = __db_open(real_name,
                            flags, OKFLAGS, mode, &fd)) != 0) {
                                __db_err(dbenv, "%s: %s", fname, strerror(ret));
                                goto err;
@@ -264,8 +270,11 @@ open_retry:        if (LF_ISSET(DB_CREATE)) {
                 */
                if (dbp->pgsize == 0) {
                        if ((ret =
-                           __db_stat(dbenv, real_name, fd, NULL, &io)) != 0)
+                           __db_ioinfo(real_name, fd, NULL, &io)) != 0) {
+                               __db_err(dbenv,
+                                   "%s: %s", real_name, strerror(ret));
                                goto err;
+                       }
                        if (io < 512)
                                io = 512;
                        if (io > 16 * 1024)
@@ -477,7 +486,7 @@ empty:      /*
 
                if (dbenv == NULL) {
                        if ((dbp->mp_dbenv =
-                           (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) {
+                           (DB_ENV *)__db_calloc(sizeof(DB_ENV), 1)) == NULL) {
                                ret = ENOMEM;
                                goto err;
                        }
@@ -491,9 +500,9 @@ empty:      /*
                        restore = 1;
                }
                envp->mp_size = cachesize;
-               F_SET(envp, DB_MPOOL_PRIVATE);
-               if ((ret = memp_open(NULL,
-                   DB_CREATE, S_IRUSR | S_IWUSR, envp, &dbp->mp)) != 0)
+               if ((ret = memp_open(NULL, DB_CREATE | DB_MPOOL_PRIVATE |
+                   (F_ISSET(dbp, DB_AM_THREAD) ? DB_THREAD : 0),
+                   S_IRUSR | S_IWUSR, envp, &dbp->mp)) != 0)
                        goto err;
                if (restore)
                        *dbenv = t_dbenv;
@@ -725,7 +734,8 @@ db_close(dbp, flags)
        }
 
        /* Sync the memory pool. */
-       if ((t_ret = memp_fsync(dbp->mpf)) != 0 && ret == 0)
+       if ((t_ret = memp_fsync(dbp->mpf)) != 0 &&
+           t_ret != DB_INCOMPLETE && ret == 0)
                ret = t_ret;
 
        /* Close the memory pool file. */
index a3e2f7b75c0ccf553da1ecefc447fa371d870f44..07d98123ac610fd85fb30ec3b8f4e364bace5e15 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1996, 1997
  *     Sleepycat Software.  All rights reserved.
- *     @(#)db.src      10.3 (Sleepycat) 8/18/97
+ *     @(#)db.src      10.4 (Sleepycat) 11/2/97
  */
 #include "config.h"
 
@@ -81,15 +81,17 @@ POINTER     nextlsn         DB_LSN *        lu
 END
 
 /*
- * ovref -- Handles increment of overflow page reference count.
+ * ovref -- Handles increment/decrement of overflow page reference count.
  *
  * fileid:     identifies the file being modified.
- * pgno:       page number being incremented.
- * lsn         the page's original lsn.
+ * pgno:       page number whose ref count is being incremented/decremented.
+ * adjust:     the adjustment being made.
+ * lsn:                the page's original lsn.
  */
 BEGIN ovref
 ARG    fileid          u_int32_t       lu
 ARG    pgno            db_pgno_t       lu
+ARG    adjust          int32_t         ld
 POINTER        lsn             DB_LSN *        lu
 END
 
index 6922504383d2c50d870ad8cdeb17fcbe1a6ef613..d40d964542bda2f13e52fe5f7b158cc51aeacda5 100644 (file)
@@ -62,7 +62,7 @@ int __db_addrem_log(logp, txnid, ret_lsnp, flags,
            + sizeof(u_int32_t) + (hdr == NULL ? 0 : hdr->size)
            + sizeof(u_int32_t) + (dbt == NULL ? 0 : dbt->size)
            + sizeof(*pagelsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -114,7 +114,7 @@ int __db_addrem_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -176,7 +176,7 @@ __db_addrem_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tpagelsn: [%lu][%lu]\n",
            (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -191,7 +191,7 @@ __db_addrem_read(recbuf, argpp)
        __db_addrem_args *argp;
        u_int8_t *bp;
 
-       argp = (__db_addrem_args *)malloc(sizeof(__db_addrem_args) +
+       argp = (__db_addrem_args *)__db_malloc(sizeof(__db_addrem_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -266,7 +266,7 @@ int __db_split_log(logp, txnid, ret_lsnp, flags,
            + sizeof(pgno)
            + sizeof(u_int32_t) + (pageimage == NULL ? 0 : pageimage->size)
            + sizeof(*pagelsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -304,7 +304,7 @@ int __db_split_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -355,7 +355,7 @@ __db_split_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tpagelsn: [%lu][%lu]\n",
            (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -370,7 +370,7 @@ __db_split_read(recbuf, argpp)
        __db_split_args *argp;
        u_int8_t *bp;
 
-       argp = (__db_split_args *)malloc(sizeof(__db_split_args) +
+       argp = (__db_split_args *)__db_malloc(sizeof(__db_split_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -447,7 +447,7 @@ int __db_big_log(logp, txnid, ret_lsnp, flags,
            + sizeof(*pagelsn)
            + sizeof(*prevlsn)
            + sizeof(*nextlsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -499,7 +499,7 @@ int __db_big_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -556,7 +556,7 @@ __db_big_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tnextlsn: [%lu][%lu]\n",
            (u_long)argp->nextlsn.file, (u_long)argp->nextlsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -571,7 +571,7 @@ __db_big_read(recbuf, argpp)
        __db_big_args *argp;
        u_int8_t *bp;
 
-       argp = (__db_big_args *)malloc(sizeof(__db_big_args) +
+       argp = (__db_big_args *)__db_malloc(sizeof(__db_big_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -610,16 +610,17 @@ __db_big_read(recbuf, argpp)
 /*
  * PUBLIC: int __db_ovref_log
  * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
- * PUBLIC:     u_int32_t, db_pgno_t, DB_LSN *));
+ * PUBLIC:     u_int32_t, db_pgno_t, int32_t, DB_LSN *));
  */
 int __db_ovref_log(logp, txnid, ret_lsnp, flags,
-       fileid, pgno, lsn)
+       fileid, pgno, adjust, lsn)
        DB_LOG *logp;
        DB_TXN *txnid;
        DB_LSN *ret_lsnp;
        u_int32_t flags;
        u_int32_t fileid;
        db_pgno_t pgno;
+       int32_t adjust;
        DB_LSN * lsn;
 {
        DBT logrec;
@@ -639,8 +640,9 @@ int __db_ovref_log(logp, txnid, ret_lsnp, flags,
        logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
            + sizeof(fileid)
            + sizeof(pgno)
+           + sizeof(adjust)
            + sizeof(*lsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -654,6 +656,8 @@ int __db_ovref_log(logp, txnid, ret_lsnp, flags,
        bp += sizeof(fileid);
        memcpy(bp, &pgno, sizeof(pgno));
        bp += sizeof(pgno);
+       memcpy(bp, &adjust, sizeof(adjust));
+       bp += sizeof(adjust);
        if (lsn != NULL)
                memcpy(bp, lsn, sizeof(*lsn));
        else
@@ -666,7 +670,7 @@ int __db_ovref_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -704,10 +708,11 @@ __db_ovref_print(notused1, dbtp, lsnp, notused3, notused4)
            (u_long)argp->prev_lsn.offset);
        printf("\tfileid: %lu\n", (u_long)argp->fileid);
        printf("\tpgno: %lu\n", (u_long)argp->pgno);
+       printf("\tadjust: %ld\n", (long)argp->adjust);
        printf("\tlsn: [%lu][%lu]\n",
            (u_long)argp->lsn.file, (u_long)argp->lsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -722,7 +727,7 @@ __db_ovref_read(recbuf, argpp)
        __db_ovref_args *argp;
        u_int8_t *bp;
 
-       argp = (__db_ovref_args *)malloc(sizeof(__db_ovref_args) +
+       argp = (__db_ovref_args *)__db_malloc(sizeof(__db_ovref_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -738,6 +743,8 @@ __db_ovref_read(recbuf, argpp)
        bp += sizeof(argp->fileid);
        memcpy(&argp->pgno, bp, sizeof(argp->pgno));
        bp += sizeof(argp->pgno);
+       memcpy(&argp->adjust, bp, sizeof(argp->adjust));
+       bp += sizeof(argp->adjust);
        memcpy(&argp->lsn, bp,  sizeof(argp->lsn));
        bp += sizeof(argp->lsn);
        *argpp = argp;
@@ -787,7 +794,7 @@ int __db_relink_log(logp, txnid, ret_lsnp, flags,
            + sizeof(*lsn_prev)
            + sizeof(next)
            + sizeof(*lsn_next);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -827,7 +834,7 @@ int __db_relink_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -874,7 +881,7 @@ __db_relink_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tlsn_next: [%lu][%lu]\n",
            (u_long)argp->lsn_next.file, (u_long)argp->lsn_next.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -889,7 +896,7 @@ __db_relink_read(recbuf, argpp)
        __db_relink_args *argp;
        u_int8_t *bp;
 
-       argp = (__db_relink_args *)malloc(sizeof(__db_relink_args) +
+       argp = (__db_relink_args *)__db_malloc(sizeof(__db_relink_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -957,7 +964,7 @@ int __db_addpage_log(logp, txnid, ret_lsnp, flags,
            + sizeof(*lsn)
            + sizeof(nextpgno)
            + sizeof(*nextlsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -990,7 +997,7 @@ int __db_addpage_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -1034,7 +1041,7 @@ __db_addpage_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tnextlsn: [%lu][%lu]\n",
            (u_long)argp->nextlsn.file, (u_long)argp->nextlsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -1049,7 +1056,7 @@ __db_addpage_read(recbuf, argpp)
        __db_addpage_args *argp;
        u_int8_t *bp;
 
-       argp = (__db_addpage_args *)malloc(sizeof(__db_addpage_args) +
+       argp = (__db_addpage_args *)__db_malloc(sizeof(__db_addpage_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -1114,7 +1121,7 @@ int __db_debug_log(logp, txnid, ret_lsnp, flags,
            + sizeof(u_int32_t) + (key == NULL ? 0 : key->size)
            + sizeof(u_int32_t) + (data == NULL ? 0 : data->size)
            + sizeof(arg_flags);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -1165,7 +1172,7 @@ int __db_debug_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -1231,7 +1238,7 @@ __db_debug_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\n");
        printf("\targ_flags: %lu\n", (u_long)argp->arg_flags);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -1246,7 +1253,7 @@ __db_debug_read(recbuf, argpp)
        __db_debug_args *argp;
        u_int8_t *bp;
 
-       argp = (__db_debug_args *)malloc(sizeof(__db_debug_args) +
+       argp = (__db_debug_args *)__db_malloc(sizeof(__db_debug_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -1303,7 +1310,7 @@ int __db_noop_log(logp, txnid, ret_lsnp, flags)
        } else
                lsnp = &txnid->last_lsn;
        logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -1320,7 +1327,7 @@ int __db_noop_log(logp, txnid, ret_lsnp, flags)
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -1357,7 +1364,7 @@ __db_noop_print(notused1, dbtp, lsnp, notused3, notused4)
            (u_long)argp->prev_lsn.file,
            (u_long)argp->prev_lsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -1372,7 +1379,7 @@ __db_noop_read(recbuf, argpp)
        __db_noop_args *argp;
        u_int8_t *bp;
 
-       argp = (__db_noop_args *)malloc(sizeof(__db_noop_args) +
+       argp = (__db_noop_args *)__db_malloc(sizeof(__db_noop_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
index 3d7b162d75a9676727c52487eaa31a14535eb91c..a4bcdb7628b58d8a49819ed8da324001a7c86160 100644 (file)
@@ -43,7 +43,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_dispatch.c        10.5 (Sleepycat) 7/2/97";
+static const char sccsid[] = "@(#)db_dispatch.c        10.6 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -155,12 +155,12 @@ __db_add_recovery(dbenv, func, ndx)
        if (ndx >= dispatch_size) {
                if (dispatch_table == NULL)
                        dispatch_table = (int (**)
-                           __P((DB_LOG *, DBT *, DB_LSN *, int, void *)))
-                           malloc(DB_user_BEGIN * sizeof(dispatch_table[0]));
+                        __P((DB_LOG *, DBT *, DB_LSN *, int, void *)))
+                        __db_malloc(DB_user_BEGIN * sizeof(dispatch_table[0]));
                else
                        dispatch_table = (int (**)
                            __P((DB_LOG *, DBT *, DB_LSN *, int, void *)))
-                           realloc(dispatch_table, (DB_user_BEGIN +
+                           __db_realloc(dispatch_table, (DB_user_BEGIN +
                            dispatch_size) * sizeof(dispatch_table[0]));
                if (dispatch_table == NULL) {
                        __db_err(dbenv, "%s", strerror(ENOMEM));
@@ -187,8 +187,8 @@ __db_txnlist_init(retp)
 {
        __db_txnhead *headp;
 
-       if ((headp =
-           (struct __db_txnhead *)malloc(sizeof(struct __db_txnhead))) == NULL)
+       if ((headp = (struct __db_txnhead *)
+           __db_malloc(sizeof(struct __db_txnhead))) == NULL)
                return (ENOMEM);
 
        LIST_INIT(&headp->head);
@@ -212,7 +212,7 @@ __db_txnlist_add(listp, txnid)
        __db_txnhead *hp;
        __db_txnlist *elp;
 
-       if ((elp = (__db_txnlist *)malloc(sizeof(__db_txnlist))) == NULL)
+       if ((elp = (__db_txnlist *)__db_malloc(sizeof(__db_txnlist))) == NULL)
                return (ENOMEM);
 
        elp->txnid = txnid;
index 66c6c2616a1e5c27f6278ad6db390390e82e9d77..faeefa0744a1196f9400f5238e34f597910a7097 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_dup.c     10.9 (Sleepycat) 9/3/97";
+static const char sccsid[] = "@(#)db_dup.c     10.10 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -217,7 +217,7 @@ __db_dsplit(dbp, hp, indxp, size, newfunc)
        indx = *indxp;
 
        /* Create a temporary page to do compaction onto. */
-       if ((tp = (PAGE *)malloc(dbp->pgsize)) == NULL)
+       if ((tp = (PAGE *)__db_malloc(dbp->pgsize)) == NULL)
                return (ENOMEM);
 #ifdef DEBUG
        memset(tp, 0xff, dbp->pgsize);
index 2340e9e3581fde62ef4d67a172e2303de8abb322..8c6619f228f58d88c459ca714ba37eb1c7f0ceee 100644 (file)
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_overflow.c        10.4 (Sleepycat) 7/2/97";
+static const char sccsid[] = "@(#)db_overflow.c        10.7 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -121,14 +121,14 @@ __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
                }
        } else if (F_ISSET(dbt, DB_DBT_MALLOC)) {
                dbt->data = dbp->db_malloc == NULL ?
-                   (void *)malloc(needed + 1) :
+                   (void *)__db_malloc(needed + 1) :
                    (void *)dbp->db_malloc(needed + 1);
                if (dbt->data == NULL)
                        return (ENOMEM);
        } else if (*bpsz == 0 || *bpsz < needed) {
                *bpp = (*bpp == NULL ?
-                   (void *)malloc(needed + 1) :
-                   (void *)realloc(*bpp, needed + 1));
+                   (void *)__db_malloc(needed + 1) :
+                   (void *)__db_realloc(*bpp, needed + 1));
                if (*bpp == NULL)
                        return (ENOMEM);
                *bpsz = needed + 1;
@@ -256,15 +256,16 @@ __db_poff(dbp, dbt, pgnop, newfunc)
 }
 
 /*
- * __db_ioff --
- *     Increment the reference count on an overflow page.
+ * __db_ovref --
+ *     Increment/decrement the reference count on an overflow page.
  *
- * PUBLIC: int __db_ioff __P((DB *, db_pgno_t));
+ * PUBLIC: int __db_ovref __P((DB *, db_pgno_t, int));
  */
 int
-__db_ioff(dbp, pgno)
+__db_ovref(dbp, pgno, adjust)
        DB *dbp;
        db_pgno_t pgno;
+       int adjust;
 {
        PAGE *h;
        int ret;
@@ -274,10 +275,12 @@ __db_ioff(dbp, pgno)
                return (ret);
        }
 
-       ++OV_REF(h);
-       if (DB_LOGGING(dbp) && (ret = __db_ovref_log(dbp->dbenv->lg_info,
-           dbp->txn, &LSN(h), 0, dbp->log_fileid, h->pgno, &LSN(h))) != 0)
-               return (ret);
+       if (DB_LOGGING(dbp))
+               if ((ret = __db_ovref_log(dbp->dbenv->lg_info, dbp->txn,
+                   &LSN(h), 0, dbp->log_fileid, h->pgno, (int32_t)adjust,
+                   &LSN(h))) != 0)
+                       return (ret);
+       OV_REF(h) += adjust;
 
        (void)memp_fput(dbp->mpf, h, DB_MPOOL_DIRTY);
        return (0);
@@ -311,9 +314,8 @@ __db_doff(dbp, pgno, freefunc)
                 * one key/data item, decrement the reference count and return.
                 */
                if (TYPE(pagep) == P_OVERFLOW && OV_REF(pagep) > 1) {
-                       --OV_REF(pagep);
-                       (void)memp_fput(dbp->mpf, pagep, DB_MPOOL_DIRTY);
-                       return (0);
+                       (void)memp_fput(dbp->mpf, pagep, 0);
+                       return (__db_ovref(dbp, pgno, -1));
                }
 
                if (DB_LOGGING(dbp)) {
index 09d8057da4ca58c5f306a43469e644cf70f2e1ce..6b6171a13ca0b7a514cec57311c28488dc7d2a84 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_pr.c      10.17 (Sleepycat) 9/15/97";
+static const char sccsid[] = "@(#)db_pr.c      10.19 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -183,7 +183,6 @@ __db_prbtree(dbp)
        };
        BTMETA *mp;
        BTREE *t;
-       DB_LOCK lock;
        EPG *epg;
        FILE *fp;
        RECNO *rp;
@@ -195,8 +194,6 @@ __db_prbtree(dbp)
 
        (void)fprintf(fp, "%s\nOn-page metadata:\n", DB_LINE);
        i = PGNO_METADATA;
-       if ((ret = __bam_lget(dbp, 0, PGNO_METADATA, DB_LOCK_READ, &lock)) != 0)
-               return (ret);
 
        if ((ret = __bam_pget(dbp, (PAGE **)&mp, &i, 0)) != 0)
                return (ret);
@@ -211,7 +208,6 @@ __db_prbtree(dbp)
        __db_prflags(mp->flags, mfn);
        (void)fprintf(fp, "\n");
        (void)memp_fput(dbp->mpf, mp, 0);
-       (void)__bam_lput(dbp, lock);
 
        (void)fprintf(fp, "%s\nDB_INFO:\n", DB_LINE);
        (void)fprintf(fp, "bt_maxkey: %lu bt_minkey: %lu\n",
@@ -416,7 +412,8 @@ __db_prpage(h, all)
            (TYPE(h) == P_LRECNO && h->pgno == PGNO_ROOT))
                fprintf(fp, " total records: %4lu", (u_long)RE_NREC(h));
        fprintf(fp, "\n");
-       if (TYPE(h) == P_LBTREE || TYPE(h) == P_LRECNO)
+       if (TYPE(h) == P_LBTREE || TYPE(h) == P_LRECNO ||
+           TYPE(h) == P_DUPLICATE || TYPE(h) == P_OVERFLOW)
                fprintf(fp, "    prev: %4lu next: %4lu",
                    (u_long)PREV_PGNO(h), (u_long)NEXT_PGNO(h));
        if (TYPE(h) == P_IBTREE || TYPE(h) == P_LBTREE)
index 900b0ed579586c1bab512d365bc5d36608a129cd..2c9ca9abe0ab2e5a0dccd8de3c124bc888200900 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_rec.c     10.8 (Sleepycat) 8/22/97";
+static const char sccsid[] = "@(#)db_rec.c     10.10 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -330,7 +330,7 @@ out:        REC_CLOSE;
 
 /*
  * __db_ovref_recover --
- *     Recovery function for __db_ioff().
+ *     Recovery function for __db_ovref().
  *
  * PUBLIC: int __db_ovref_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
@@ -357,22 +357,21 @@ __db_ovref_recover(logp, dbtp, lsnp, redo, info)
        }
 
        modified = 0;
-       if (log_compare(lsnp, &argp->lsn) == 0 && redo) {
+       if (log_compare(&LSN(pagep), &argp->lsn) == 0 && redo) {
                /* Need to redo update described. */
-               ++OV_REF(pagep);
+               OV_REF(pagep) += argp->adjust;
 
                pagep->lsn = *lsnp;
                modified = 1;
        } else if (log_compare(lsnp, &LSN(pagep)) == 0 && !redo) {
                /* Need to undo update described. */
-               --OV_REF(pagep);
+               OV_REF(pagep) -= argp->adjust;
 
                pagep->lsn = argp->lsn;
                modified = 1;
        }
-       ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0);
-
-       *lsnp = argp->prev_lsn;
+       if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) == 0)
+               *lsnp = argp->prev_lsn;
 
 out:   REC_CLOSE;
 }
@@ -413,7 +412,7 @@ __db_relink_recover(logp, dbtp, lsnp, redo, info)
                goto next;
        }
        modified = 0;
-       if (log_compare(lsnp, &argp->lsn) == 0 && redo) {
+       if (log_compare(&LSN(pagep), &argp->lsn) == 0 && redo) {
                /* Redo the relink. */
                pagep->lsn = *lsnp;
                modified = 1;
@@ -438,7 +437,7 @@ next:       if ((ret = memp_fget(mpf, &argp->next, 0, &pagep)) != 0) {
                goto prev;
        }
        modified = 0;
-       if (log_compare(lsnp, &argp->lsn_next) == 0 && redo) {
+       if (log_compare(&LSN(pagep), &argp->lsn_next) == 0 && redo) {
                /* Redo the relink. */
                pagep->prev_pgno = argp->prev;
 
@@ -464,7 +463,7 @@ prev:       if ((ret = memp_fget(mpf, &argp->prev, 0, &pagep)) != 0) {
                goto done;
        }
        modified = 0;
-       if (log_compare(lsnp, &argp->lsn_prev) == 0 && redo) {
+       if (log_compare(&LSN(pagep), &argp->lsn_prev) == 0 && redo) {
                /* Redo the relink. */
                pagep->next_pgno = argp->next;
 
index ee2bc82f8798c36ae28ed256c6b652609137fe0f..bcec308b951a94b34bf85cdd6eff1e7e80695daa 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_ret.c     10.7 (Sleepycat) 9/15/97";
+static const char sccsid[] = "@(#)db_ret.c     10.8 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -122,7 +122,7 @@ __db_retcopy(dbt, data, len, memp, memsize, db_malloc)
         */
        if (F_ISSET(dbt, DB_DBT_MALLOC)) {
                dbt->data = db_malloc == NULL ?
-                   (void *)malloc(len + 1) :
+                   (void *)__db_malloc(len + 1) :
                    (void *)db_malloc(len + 1);
                if (dbt->data == NULL)
                        return (ENOMEM);
@@ -134,8 +134,8 @@ __db_retcopy(dbt, data, len, memp, memsize, db_malloc)
        } else {
                if (*memsize == 0 || *memsize < len) {
                        *memp = *memp == NULL ?
-                           (void *)malloc(len + 1) :
-                           (void *)realloc(*memp, len + 1);
+                           (void *)__db_malloc(len + 1) :
+                           (void *)__db_realloc(*memp, len + 1);
                        if (*memp == NULL) {
                                *memsize = 0;
                                return (ENOMEM);
index 170baf5345062953f1a52e1dc75efd10a0d114a6..d9086918ddfa9478789b083ecdc0b61121efa524 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_thread.c  8.12 (Sleepycat) 9/23/97";
+static const char sccsid[] = "@(#)db_thread.c  8.13 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -42,8 +42,7 @@ __db_gethandle(dbp, am_func, dbpp)
        DB *ret_dbp;
        int ret, t_ret;
 
-       if ((ret = __db_mutex_lock((db_mutex_t *)dbp->mutexp, -1,
-           dbp->dbenv == NULL ? NULL : dbp->dbenv->db_yield)) != 0)
+       if ((ret = __db_mutex_lock((db_mutex_t *)dbp->mutexp, -1)) != 0)
                return (ret);
 
        if ((ret_dbp = LIST_FIRST(&dbp->handleq)) != NULL)
@@ -51,7 +50,7 @@ __db_gethandle(dbp, am_func, dbpp)
                LIST_REMOVE(ret_dbp, links);
        else {
                /* Allocate a new handle. */
-               if ((ret_dbp = (DB *)malloc(sizeof(*dbp))) == NULL) {
+               if ((ret_dbp = (DB *)__db_malloc(sizeof(*dbp))) == NULL) {
                        ret = ENOMEM;
                        goto err;
                }
@@ -94,8 +93,7 @@ __db_puthandle(dbp)
        int ret;
 
        master = dbp->master;
-       if ((ret = __db_mutex_lock((db_mutex_t *)master->mutexp, -1,
-           dbp->dbenv == NULL ? NULL : dbp->dbenv->db_yield)) != 0)
+       if ((ret = __db_mutex_lock((db_mutex_t *)master->mutexp, -1)) != 0)
                return (ret);
 
        LIST_INSERT_HEAD(&master->handleq, dbp, links);
index bf5e37edcb286bd6e3fcc1a06bfad9b778faab98..1affdcdf0dbce2a5af4318b993544357c1cdd646 100644 (file)
@@ -11,7 +11,7 @@
 static const char copyright[] =
 "@(#) Copyright (c) 1997\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db185.c      8.13 (Sleepycat) 8/24/97";
+static const char sccsid[] = "@(#)db185.c      8.14 (Sleepycat) 10/25/97";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -52,7 +52,7 @@ __dbopen(file, oflags, mode, type, openinfo)
        DB_INFO dbinfo, *dbinfop;
        int s_errno;
 
-       if ((db185p = (DB185 *)calloc(1, sizeof(DB185))) == NULL)
+       if ((db185p = (DB185 *)__db_calloc(1, sizeof(DB185))) == NULL)
                return (NULL);
        dbinfop = NULL;
        memset(&dbinfo, 0, sizeof(dbinfo));
@@ -119,7 +119,7 @@ __dbopen(file, oflags, mode, type, openinfo)
                 */
                if (file != NULL) {
                        if (oflags & O_CREAT && __db_exists(file, NULL) != 0)
-                               (void)close(open(file, oflags, mode));
+                               (void)__os_close(open(file, oflags, mode));
                        dbinfop->re_source = (char *)file;
                        file = NULL;
                }
@@ -131,7 +131,7 @@ __dbopen(file, oflags, mode, type, openinfo)
                         */
 #define        BFMSG   "DB: DB 1.85's recno bfname field is not supported.\n"
                        if (ri->bfname != NULL) {
-                               (void)write(2, BFMSG, sizeof(BFMSG) - 1);
+                               (void)__os_write(2, BFMSG, sizeof(BFMSG) - 1);
                                goto einval;
                        }
 
@@ -183,7 +183,7 @@ __dbopen(file, oflags, mode, type, openinfo)
         */
        if ((__set_errno(db_open(file,
            type, __db_oflags(oflags), mode, NULL, dbinfop, &dbp))) != 0) {
-               free(db185p);
+               __db_free(db185p);
                return (NULL);
        }
 
@@ -192,7 +192,7 @@ __dbopen(file, oflags, mode, type, openinfo)
            != 0) {
                s_errno = errno;
                (void)dbp->close(dbp, 0);
-               free(db185p);
+               __db_free(db185p);
                __set_errno(s_errno);
                return (NULL);
        }
@@ -200,7 +200,7 @@ __dbopen(file, oflags, mode, type, openinfo)
        db185p->internal = dbp;
        return (db185p);
 
-einval:        free(db185p);
+einval:        __db_free(db185p);
        __set_errno(EINVAL);
        return (NULL);
 }
@@ -216,7 +216,7 @@ db185_close(db185p)
 
        __set_errno(dbp->close(dbp, 0));
 
-       free(db185p);
+       __db_free(db185p);
 
        return (errno == 0 ? 0 : -1);
 }
@@ -461,7 +461,7 @@ db185_sync(db185p, flags)
                 * We can't support the R_RECNOSYNC flag.
                 */
 #define        RSMSG   "DB: DB 1.85's R_RECNOSYNC sync flag is not supported.\n"
-               (void)write(2, RSMSG, sizeof(RSMSG) - 1);
+               (void)__os_write(2, RSMSG, sizeof(RSMSG) - 1);
                goto einval;
        default:
                goto einval;
index 56dfddb73f557ee9a4f3d913aee112b02450023c..1f6c7903451f790b5d3759747b8898c533212661 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db_int.h.src        10.30 (Sleepycat) 9/23/97
+ *     @(#)db_int.h.src        10.36 (Sleepycat) 10/31/97
  */
 
 #ifndef _DB_INTERNAL_H_
@@ -12,6 +12,7 @@
 
 #include "db.h"                                /* Standard DB include file. */
 #include "queue.h"
+#include "os_func.h"
 #include "os_ext.h"
 
 /*******************************************************
 #undef SSZA
 #define SSZA(name, field)      ((int)&(((name *)0)->field[0]))
 
+/* Macros to return per-process address, offsets based on shared regions. */
+#define        R_ADDR(base, offset)    ((void *)((u_int8_t *)((base)->addr) + offset))
+#define        R_OFFSET(base, p)       ((u_int8_t *)(p) - (u_int8_t *)(base)->addr)
+
 /* Free and free-string macros that overwrite memory during debugging. */
 #ifdef DEBUG
 #undef FREE
 #define        FREE(p, len) {                                                  \
        memset(p, 0xff, len);                                           \
-       free(p);                                                        \
+       __db_free(p);                                                   \
 }
 #undef FREES
 #define        FREES(p) {                                                      \
 #else
 #undef FREE
 #define        FREE(p, len) {                                                  \
-       free(p);                                                        \
+       __db_free(p);                                                   \
 }
 #undef FREES
 #define        FREES(p) {                                                      \
-       free(p);                                                        \
+       __db_free(p);                                                   \
 }
 #endif
 
 /* Structure used to print flag values. */
 typedef struct __fn {
-       u_int32_t   mask;               /* Flag value. */
+       u_int32_t mask;                 /* Flag value. */
        const char *name;               /* Flag name. */
 } FN;
 
@@ -163,10 +168,8 @@ typedef struct _db_mutex_t {
        off_t   off;                    /* Backing file offset. */
        u_long  pid;                    /* Lock holder: 0 or process pid. */
 #endif
-#ifdef MUTEX_STATISTICS
-       u_long  mutex_set_wait;         /* Blocking mutex: required waiting. */
-       u_long  mutex_set_nowait;       /* Blocking mutex: without waiting. */
-#endif
+       u_int32_t mutex_set_wait;       /* Granted after wait. */
+       u_int32_t mutex_set_nowait;     /* Granted without waiting. */
 } db_mutex_t;
 
 #include "mutex_ext.h"
@@ -177,11 +180,10 @@ typedef struct _db_mutex_t {
 /* Lock/unlock a DB thread. */
 #define        DB_THREAD_LOCK(dbp)                                             \
        (F_ISSET(dbp, DB_AM_THREAD) ?                                   \
-           __db_mutex_lock((db_mutex_t *)(dbp)->mutexp,  -1,           \
-               (dbp)->dbenv == NULL ? NULL : (dbp)->dbenv->db_yield) : 0)
+           __db_mutex_lock((db_mutex_t *)(dbp)->mutexp, -1) : 0)
 #define        DB_THREAD_UNLOCK(dbp)                                           \
        (F_ISSET(dbp, DB_AM_THREAD) ?                                   \
-           __db_mutex_unlock((db_mutex_t *)(dbp)->mutexp,  -1) : 0)
+           __db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1) : 0)
 
 /* Btree/recno local statistics structure. */
 struct __db_bt_lstat;  typedef struct __db_bt_lstat DB_BTREE_LSTAT;
@@ -260,7 +262,7 @@ typedef struct __dbpginfo {
 #define        IS_ZERO_LSN(LSN)        ((LSN).file == 0)
 
 /* Test if we need to log a change. */
-#define        DB_LOGGING(dbp) \
+#define        DB_LOGGING(dbp)                                                 \
        (F_ISSET(dbp, DB_AM_LOGGING) && !F_ISSET(dbp, DB_AM_RECOVER))
 
 #ifdef DEBUG
index d986e08087021421ca7bc6e2e6dce6cb77b5ab79..c08495378e68de83e15dbe4570ac8bbb2f644808 100644 (file)
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash.c       10.27 (Sleepycat) 9/15/97";
+static const char sccsid[] = "@(#)hash.c       10.33 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -79,7 +79,7 @@ static int  __ham_cursor __P((DB *, DB_TXN *, DBC **));
 static int  __ham_delete __P((DB *, DB_TXN *, DBT *, int));
 static int  __ham_dup_return __P((HTAB *, HASH_CURSOR *, DBT *, int));
 static int  __ham_get __P((DB *, DB_TXN *, DBT *, DBT *, int));
-static void __ham_init_htab __P((HTAB *));
+static void __ham_init_htab __P((HTAB *, u_int));
 static int  __ham_lookup __P((HTAB *,
                HASH_CURSOR *, const DBT *, u_int32_t, db_lockmode_t));
 static int  __ham_overwrite __P((HTAB *, HASH_CURSOR *, DBT *));
@@ -106,7 +106,7 @@ __ham_open(dbp, dbinfo)
 
        dbenv = dbp->dbenv;
 
-       if ((hashp = (HTAB *)calloc(1, sizeof(HTAB))) == NULL)
+       if ((hashp = (HTAB *)__db_calloc(1, sizeof(HTAB))) == NULL)
                return (ENOMEM);
        hashp->dbp = dbp;
 
@@ -175,10 +175,9 @@ __ham_open(dbp, dbinfo)
                        goto out;
                }
 
-               hashp->hdr->nelem = dbinfo != NULL ? dbinfo->h_nelem : 0;
                hashp->hdr->ffactor =
                    dbinfo != NULL && dbinfo->h_ffactor ? dbinfo->h_ffactor : 0;
-               __ham_init_htab(hashp);
+               __ham_init_htab(hashp, dbinfo != NULL ? dbinfo->h_nelem : 0);
                if (F_ISSET(dbp, DB_AM_DUP))
                        F_SET(hashp->hdr, DB_HASH_DUP);
                if ((ret = __ham_dirty_page(hashp, (PAGE *)hashp->hdr)) != 0)
@@ -190,7 +189,7 @@ __ham_open(dbp, dbinfo)
        TAILQ_INSERT_TAIL(&dbp->curs_queue, curs, links);
 
        /* Allocate memory for our split buffer. */
-       if ((hashp->split_buf = (PAGE *)malloc(dbp->pgsize)) == NULL) {
+       if ((hashp->split_buf = (PAGE *)__db_malloc(dbp->pgsize)) == NULL) {
                ret = ENOMEM;
                goto out;
        }
@@ -265,13 +264,13 @@ __ham_close(dbp)
  * Returns 0 on No Error
  */
 static void
-__ham_init_htab(hashp)
+__ham_init_htab(hashp, nelem)
        HTAB *hashp;
+       u_int nelem;
 {
-       u_int32_t nelem;
        int32_t l2, nbuckets;
 
-       nelem = hashp->hdr->nelem;
+       hashp->hdr->nelem = 0;
        hashp->hdr->pagesize = hashp->dbp->pgsize;
        ZERO_LSN(hashp->hdr->lsn);
        hashp->hdr->magic = DB_HASHMAGIC;
@@ -502,11 +501,11 @@ __ham_c_init(dbp, txnid, dbcp)
        DBC *db_curs;
        HASH_CURSOR *new_curs;
 
-       if ((db_curs = (DBC *)calloc(sizeof(DBC), 1)) == NULL)
+       if ((db_curs = (DBC *)__db_calloc(sizeof(DBC), 1)) == NULL)
                return (ENOMEM);
 
        if ((new_curs =
-           (HASH_CURSOR *)calloc(sizeof(struct cursor_t), 1)) == NULL) {
+           (HASH_CURSOR *)__db_calloc(sizeof(struct cursor_t), 1)) == NULL) {
                FREE(db_curs, sizeof(DBC));
                return (ENOMEM);
        }
@@ -555,7 +554,7 @@ __ham_delete(dbp, txn, key, flags)
        hashp->hash_accesses++;
        if ((ret = __ham_lookup(hashp, hcp, key, 0, DB_LOCK_WRITE)) == 0)
                if (F_ISSET(hcp, H_OK))
-                       ret = __ham_del_pair(hashp, hcp);
+                       ret = __ham_del_pair(hashp, hcp, 1);
                else
                        ret = DB_NOTFOUND;
 
@@ -669,30 +668,41 @@ __ham_c_del(cursor, flags)
        if ((ret = __ham_get_cpage(hashp, hcp, DB_LOCK_WRITE)) != 0)
                goto out;
        if (F_ISSET(hcp, H_ISDUP) && hcp->dpgno != PGNO_INVALID) {
-               ppgno = PREV_PGNO(hcp->dpagep);
-
-               /* Remove item from duplicate page. */
-               chg_pgno = hcp->dpgno;
-               if ((ret = __db_drem(hashp->dbp,
-                   &hcp->dpagep, hcp->dndx, __ham_del_page)) != 0)
-                       goto out;
-
                /*
+                * We are about to remove a duplicate from offpage.
+                *
                 * There are 4 cases.
-                * 1. We removed an item on a page, but nothing else changed.
-                * 2. We removed the last item on a page, but there is a
+                * 1. We will remove an item on a page, but there are more
+                *    items on that page.
+                * 2. We will remove the last item on a page, but there is a
                 *    following page of duplicates.
-                * 3. We removed the last item on a page, this page was the
+                * 3. We will remove the last item on a page, this page was the
                 *    last page in a duplicate set, but there were dups before
                 *    it.
-                * 4. We removed the last item on a page, removing the last
+                * 4. We will remove the last item on a page, removing the last
                 *    duplicate.
                 * In case 1 hcp->dpagep is unchanged.
                 * In case 2 hcp->dpagep comes back pointing to the next dup
                 *     page.
                 * In case 3 hcp->dpagep comes back NULL.
                 * In case 4 hcp->dpagep comes back NULL.
+                *
+                * Case 4 results in deleting the pair off the master page.
+                * The normal code for doing this knows how to delete the
+                * duplicates, so we will handle this case in the normal code.
                 */
+               ppgno = PREV_PGNO(hcp->dpagep);
+               if (ppgno == PGNO_INVALID &&
+                   NEXT_PGNO(hcp->dpagep) == PGNO_INVALID &&
+                   NUM_ENT(hcp->dpagep) == 1)
+                       goto normal;
+
+               /* Remove item from duplicate page. */
+               chg_pgno = hcp->dpgno;
+               if ((ret = __db_drem(hashp->dbp,
+                   &hcp->dpagep, hcp->dndx, __ham_del_page)) != 0)
+                       goto out;
+
                if (hcp->dpagep == NULL) {
                        if (ppgno != PGNO_INVALID) {            /* Case 3 */
                                hcp->dpgno = ppgno;
@@ -702,7 +712,7 @@ __ham_c_del(cursor, flags)
                                hcp->dndx = NUM_ENT(hcp->dpagep);
                                F_SET(hcp, H_DELETED);
                        } else {                                /* Case 4 */
-                               ret = __ham_del_pair(hashp, hcp);
+                               ret = __ham_del_pair(hashp, hcp, 1);
                                hcp->dpgno = PGNO_INVALID;
                                /*
                                 * Delpair updated the cursor queue, so we
@@ -718,14 +728,14 @@ __ham_c_del(cursor, flags)
                                    H_DATAINDEX(hcp->bndx))),
                                    &hcp->dpgno, sizeof(db_pgno_t));
                        F_SET(hcp, H_DELETED);
-               } else                                  /* Case 1 */
+               } else                                          /* Case 1 */
                        F_SET(hcp, H_DELETED);
                if (chg_pgno != PGNO_INVALID)
                        __ham_c_update(hashp, hcp, chg_pgno, 0, 0, 1);
        } else if (F_ISSET(hcp, H_ISDUP)) {                     /* on page */
                if (hcp->dup_off == 0 && DUP_SIZE(hcp->dup_len) ==
                    LEN_HDATA(hcp->pagep, hashp->hdr->pagesize, hcp->bndx))
-                       ret = __ham_del_pair(hashp, hcp);
+                       ret = __ham_del_pair(hashp, hcp, 1);
                else {
                        DBT repldbt;
 
@@ -736,14 +746,14 @@ __ham_c_del(cursor, flags)
                        repldbt.size = 0;
                        ret = __ham_replpair(hashp, hcp, &repldbt, 0);
                        hcp->dup_tlen -= DUP_SIZE(hcp->dup_len);
+                       F_SET(hcp, H_DELETED);
                        __ham_c_update(hashp, hcp, hcp->pgno,
                            DUP_SIZE(hcp->dup_len), 0, 1);
-                       F_SET(hcp, H_DELETED);
                }
 
        } else
                /* Not a duplicate */
-               ret = __ham_del_pair(hashp, hcp);
+normal:                ret = __ham_del_pair(hashp, hcp, 1);
 
 out:   if ((t_ret = __ham_item_done(hashp, hcp, ret == 0)) != 0 && ret == 0)
                t_ret = ret;
@@ -975,8 +985,8 @@ int
 __ham_expand_table(hashp)
        HTAB *hashp;
 {
-       u_int32_t old_bucket, new_bucket;
-       u_int32_t spare_ndx;
+       DB_LSN new_lsn;
+       u_int32_t old_bucket, new_bucket, spare_ndx;
        int ret;
 
        ret = 0;
@@ -984,9 +994,30 @@ __ham_expand_table(hashp)
        if (ret)
                return (ret);
 
-       if (DB_LOGGING(hashp->dbp)) {
-               DB_LSN new_lsn;
+       /*
+        * If the split point is about to increase, make sure that we
+        * have enough extra pages.  The calculation here is weird.
+        * We'd like to do this after we've upped max_bucket, but it's
+        * too late then because we've logged the meta-data split.  What
+        * we'll do between then and now is increment max bucket and then
+        * see what the log of one greater than that is; here we have to
+        * look at the log of max + 2.  VERY NASTY STUFF.
+        */
+       if (__db_log2(hashp->hdr->max_bucket + 2) > hashp->hdr->ovfl_point) {
+               /*
+                * We are about to shift the split point.  Make sure that
+                * if the next doubling is going to be big (more than 8
+                * pages), we have some extra pages around.
+                */
+               if (hashp->hdr->max_bucket + 1 >= 8 && 
+                   hashp->hdr->spares[hashp->hdr->ovfl_point] <
+                   hashp->hdr->spares[hashp->hdr->ovfl_point - 1] + 
+                   hashp->hdr->ovfl_point + 1)
+                       __ham_init_ovflpages(hashp);
+       }
 
+       /* Now we can log the meta-data split. */
+       if (DB_LOGGING(hashp->dbp)) {
                if ((ret = __ham_splitmeta_log(hashp->dbp->dbenv->lg_info,
                    (DB_TXN *)hashp->dbp->txn, &new_lsn, 0,
                    hashp->dbp->log_fileid,
@@ -1003,22 +1034,11 @@ __ham_expand_table(hashp)
        old_bucket = (hashp->hdr->max_bucket & hashp->hdr->low_mask);
 
        /*
-        * If the split point is increasing (hdr.max_bucket's log base 2
-        * increases), max sure that we have enough extra pages, then
-        * copy the current contents of the spare split bucket to the
-        * next bucket.
+        * If the split point is increasing, copy the current contents
+        * of the spare split bucket to the next bucket.
         */
        spare_ndx = __db_log2(hashp->hdr->max_bucket + 1);
        if (spare_ndx > hashp->hdr->ovfl_point) {
-               /*
-                * We are about to shift the split point.  Make sure that
-                * if the next doubling is going to be big (more than 8
-                * pages), we have some extra pages around.
-                */
-               if (hashp->hdr->spares[hashp->hdr->ovfl_point] == 0 &&
-                   new_bucket >= 8)
-                       __ham_init_ovflpages(hashp);
-
                hashp->hdr->spares[spare_ndx] =
                    hashp->hdr->spares[hashp->hdr->ovfl_point];
                hashp->hdr->ovfl_point = spare_ndx;
@@ -1306,7 +1326,7 @@ __ham_init_dbt(dbt, size, bufp, sizep)
        memset(dbt, 0, sizeof(*dbt));
        if (*sizep < size) {
                if ((*bufp = (void *)(*bufp == NULL ?
-                   malloc(size) : realloc(*bufp, size))) == NULL) {
+                   __db_malloc(size) : __db_realloc(*bufp, size))) == NULL) {
                        *sizep = 0;
                        return (ENOMEM);
                }
@@ -1352,9 +1372,20 @@ __ham_c_update(hashp, hcp, chg_pgno, len, add, dup)
        if (!dup && add)
                return;
 
-       page_deleted = chg_pgno != PGNO_INVALID &&
-           ((!dup && chg_pgno != hcp->pgno) ||
-           (dup && chg_pgno != hcp->dpgno));
+       /*
+        * Determine if a page was deleted.    If this is a regular update
+        * (i.e., not dup) then the deleted page's number will be that in
+        * chg_pgno, and the pgno in the cursor will be different.  If this
+        * was an onpage-duplicate, then the same conditions apply.  If this
+        * was an off-page duplicate, then we need to verify if hcp->dpgno
+        * is the same (no delete) or different (delete) than chg_pgno.
+        */
+       if (!dup || hcp->dpgno == PGNO_INVALID)
+               page_deleted =
+                   chg_pgno != PGNO_INVALID && chg_pgno != hcp->pgno;
+       else
+               page_deleted =
+                   chg_pgno != PGNO_INVALID && chg_pgno != hcp->dpgno;
 
        hp = hcp->db_cursor->dbp->master->internal;
        DB_THREAD_LOCK(hp->dbp);
@@ -1432,7 +1463,7 @@ __ham_hdup(orig, new)
        DBC *curs;
        int ret;
 
-       if ((hashp = (HTAB *)malloc(sizeof(HTAB))) == NULL)
+       if ((hashp = (HTAB *)__db_malloc(sizeof(HTAB))) == NULL)
                return (ENOMEM);
 
        new->internal = hashp;
@@ -1441,7 +1472,7 @@ __ham_hdup(orig, new)
        hashp->hlock = 0;
        hashp->hdr = NULL;
        hashp->hash = ((HTAB *)orig->internal)->hash;
-       if ((hashp->split_buf = (PAGE *)malloc(orig->pgsize)) == NULL)
+       if ((hashp->split_buf = (PAGE *)__db_malloc(orig->pgsize)) == NULL)
                return (ENOMEM);
        hashp->local_errno = 0;
        hashp->hash_accesses = 0;
index 04a98d3cb37c3a079ae3dfb42568ce982d987315..8cbcee73f7153a85eeeea6d6e081b5e889a7b2ea 100644 (file)
@@ -43,7 +43,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)hash.src    10.1 (Sleepycat) 4/12/97
+ *     @(#)hash.src    10.2 (Sleepycat) 11/2/97
  */
 
 #include "config.h"
@@ -207,5 +207,27 @@ ARG        fileid          u_int32_t       lu
 ARG    start_pgno      db_pgno_t       lu
 ARG    npages          u_int32_t       lu
 ARG    free_pgno       db_pgno_t       lu
+ARG    ovflpoint       u_int32_t       lu
 POINTER        metalsn         DB_LSN *        lu
 END
+
+/*
+ * Used when we empty the first page in a bucket and there are pages
+ * after it.  The page after it gets copied into the bucket page (since
+ * bucket pages have to be in fixed locations).
+ * pgno: the bucket page
+ * pagelsn: the old LSN on the bucket page
+ * next_pgno: the page number of the next page
+ * nnext_pgno: page after next_pgno (may need to change its prev)
+ * nnextlsn: the LSN of nnext_pgno.
+ */
+BEGIN copypage
+ARG    fileid          u_int32_t       lu
+ARG    pgno            db_pgno_t       lu
+POINTER        pagelsn         DB_LSN *        lu
+ARG    next_pgno       db_pgno_t       lu
+POINTER        nextlsn         DB_LSN *        lu
+ARG    nnext_pgno      db_pgno_t       lu
+POINTER        nnextlsn        DB_LSN *        lu
+DBT    page            DBT             s
+END
index 2279de9668293c2c8dc277cff7c25bcea5ef602b..4820eb8611a77b56a2a65c9d17fcc4b78acc3822 100644 (file)
@@ -61,7 +61,7 @@ int __ham_insdel_log(logp, txnid, ret_lsnp, flags,
            + sizeof(*pagelsn)
            + sizeof(u_int32_t) + (key == NULL ? 0 : key->size)
            + sizeof(u_int32_t) + (data == NULL ? 0 : data->size);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -111,7 +111,7 @@ int __ham_insdel_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -172,7 +172,7 @@ __ham_insdel_print(notused1, dbtp, lsnp, notused3, notused4)
        }
        printf("\n");
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -187,7 +187,7 @@ __ham_insdel_read(recbuf, argpp)
        __ham_insdel_args *argp;
        u_int8_t *bp;
 
-       argp = (__ham_insdel_args *)malloc(sizeof(__ham_insdel_args) +
+       argp = (__ham_insdel_args *)__db_malloc(sizeof(__ham_insdel_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -266,7 +266,7 @@ int __ham_newpage_log(logp, txnid, ret_lsnp, flags,
            + sizeof(*pagelsn)
            + sizeof(next_pgno)
            + sizeof(*nextlsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -308,7 +308,7 @@ int __ham_newpage_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -356,7 +356,7 @@ __ham_newpage_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tnextlsn: [%lu][%lu]\n",
            (u_long)argp->nextlsn.file, (u_long)argp->nextlsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -371,7 +371,7 @@ __ham_newpage_read(recbuf, argpp)
        __ham_newpage_args *argp;
        u_int8_t *bp;
 
-       argp = (__ham_newpage_args *)malloc(sizeof(__ham_newpage_args) +
+       argp = (__ham_newpage_args *)__db_malloc(sizeof(__ham_newpage_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -441,7 +441,7 @@ int __ham_splitmeta_log(logp, txnid, ret_lsnp, flags,
            + sizeof(ovflpoint)
            + sizeof(spares)
            + sizeof(*metalsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -471,7 +471,7 @@ int __ham_splitmeta_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -514,7 +514,7 @@ __ham_splitmeta_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tmetalsn: [%lu][%lu]\n",
            (u_long)argp->metalsn.file, (u_long)argp->metalsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -529,7 +529,7 @@ __ham_splitmeta_read(recbuf, argpp)
        __ham_splitmeta_args *argp;
        u_int8_t *bp;
 
-       argp = (__ham_splitmeta_args *)malloc(sizeof(__ham_splitmeta_args) +
+       argp = (__ham_splitmeta_args *)__db_malloc(sizeof(__ham_splitmeta_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -594,7 +594,7 @@ int __ham_splitdata_log(logp, txnid, ret_lsnp, flags,
            + sizeof(pgno)
            + sizeof(u_int32_t) + (pageimage == NULL ? 0 : pageimage->size)
            + sizeof(*pagelsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -632,7 +632,7 @@ int __ham_splitdata_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -683,7 +683,7 @@ __ham_splitdata_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tpagelsn: [%lu][%lu]\n",
            (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -698,7 +698,7 @@ __ham_splitdata_read(recbuf, argpp)
        __ham_splitdata_args *argp;
        u_int8_t *bp;
 
-       argp = (__ham_splitdata_args *)malloc(sizeof(__ham_splitdata_args) +
+       argp = (__ham_splitdata_args *)__db_malloc(sizeof(__ham_splitdata_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -772,7 +772,7 @@ int __ham_replace_log(logp, txnid, ret_lsnp, flags,
            + sizeof(u_int32_t) + (olditem == NULL ? 0 : olditem->size)
            + sizeof(u_int32_t) + (newitem == NULL ? 0 : newitem->size)
            + sizeof(makedup);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -824,7 +824,7 @@ int __ham_replace_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -886,7 +886,7 @@ __ham_replace_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\n");
        printf("\tmakedup: %lu\n", (u_long)argp->makedup);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -901,7 +901,7 @@ __ham_replace_read(recbuf, argpp)
        __ham_replace_args *argp;
        u_int8_t *bp;
 
-       argp = (__ham_replace_args *)malloc(sizeof(__ham_replace_args) +
+       argp = (__ham_replace_args *)__db_malloc(sizeof(__ham_replace_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -985,7 +985,7 @@ int __ham_newpgno_log(logp, txnid, ret_lsnp, flags,
            + sizeof(new_type)
            + sizeof(*pagelsn)
            + sizeof(*metalsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -1026,7 +1026,7 @@ int __ham_newpgno_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -1074,7 +1074,7 @@ __ham_newpgno_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tmetalsn: [%lu][%lu]\n",
            (u_long)argp->metalsn.file, (u_long)argp->metalsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -1089,7 +1089,7 @@ __ham_newpgno_read(recbuf, argpp)
        __ham_newpgno_args *argp;
        u_int8_t *bp;
 
-       argp = (__ham_newpgno_args *)malloc(sizeof(__ham_newpgno_args) +
+       argp = (__ham_newpgno_args *)__db_malloc(sizeof(__ham_newpgno_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -1127,10 +1127,10 @@ __ham_newpgno_read(recbuf, argpp)
  * PUBLIC: int __ham_ovfl_log
  * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
  * PUBLIC:     u_int32_t, db_pgno_t, u_int32_t, db_pgno_t,
- * PUBLIC:     DB_LSN *));
+ * PUBLIC:     u_int32_t, DB_LSN *));
  */
 int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
-       fileid, start_pgno, npages, free_pgno, metalsn)
+       fileid, start_pgno, npages, free_pgno, ovflpoint, metalsn)
        DB_LOG *logp;
        DB_TXN *txnid;
        DB_LSN *ret_lsnp;
@@ -1139,6 +1139,7 @@ int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
        db_pgno_t start_pgno;
        u_int32_t npages;
        db_pgno_t free_pgno;
+       u_int32_t ovflpoint;
        DB_LSN * metalsn;
 {
        DBT logrec;
@@ -1160,8 +1161,9 @@ int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
            + sizeof(start_pgno)
            + sizeof(npages)
            + sizeof(free_pgno)
+           + sizeof(ovflpoint)
            + sizeof(*metalsn);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -1179,6 +1181,8 @@ int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
        bp += sizeof(npages);
        memcpy(bp, &free_pgno, sizeof(free_pgno));
        bp += sizeof(free_pgno);
+       memcpy(bp, &ovflpoint, sizeof(ovflpoint));
+       bp += sizeof(ovflpoint);
        if (metalsn != NULL)
                memcpy(bp, metalsn, sizeof(*metalsn));
        else
@@ -1191,7 +1195,7 @@ int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -1231,10 +1235,11 @@ __ham_ovfl_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tstart_pgno: %lu\n", (u_long)argp->start_pgno);
        printf("\tnpages: %lu\n", (u_long)argp->npages);
        printf("\tfree_pgno: %lu\n", (u_long)argp->free_pgno);
+       printf("\tovflpoint: %lu\n", (u_long)argp->ovflpoint);
        printf("\tmetalsn: [%lu][%lu]\n",
            (u_long)argp->metalsn.file, (u_long)argp->metalsn.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -1249,7 +1254,7 @@ __ham_ovfl_read(recbuf, argpp)
        __ham_ovfl_args *argp;
        u_int8_t *bp;
 
-       argp = (__ham_ovfl_args *)malloc(sizeof(__ham_ovfl_args) +
+       argp = (__ham_ovfl_args *)__db_malloc(sizeof(__ham_ovfl_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -1269,12 +1274,215 @@ __ham_ovfl_read(recbuf, argpp)
        bp += sizeof(argp->npages);
        memcpy(&argp->free_pgno, bp, sizeof(argp->free_pgno));
        bp += sizeof(argp->free_pgno);
+       memcpy(&argp->ovflpoint, bp, sizeof(argp->ovflpoint));
+       bp += sizeof(argp->ovflpoint);
        memcpy(&argp->metalsn, bp,  sizeof(argp->metalsn));
        bp += sizeof(argp->metalsn);
        *argpp = argp;
        return (0);
 }
 
+/*
+ * PUBLIC: int __ham_copypage_log
+ * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
+ * PUBLIC:     u_int32_t, db_pgno_t, DB_LSN *, db_pgno_t,
+ * PUBLIC:     DB_LSN *, db_pgno_t, DB_LSN *, DBT *));
+ */
+int __ham_copypage_log(logp, txnid, ret_lsnp, flags,
+       fileid, pgno, pagelsn, next_pgno, nextlsn, nnext_pgno,
+       nnextlsn, page)
+       DB_LOG *logp;
+       DB_TXN *txnid;
+       DB_LSN *ret_lsnp;
+       u_int32_t flags;
+       u_int32_t fileid;
+       db_pgno_t pgno;
+       DB_LSN * pagelsn;
+       db_pgno_t next_pgno;
+       DB_LSN * nextlsn;
+       db_pgno_t nnext_pgno;
+       DB_LSN * nnextlsn;
+       DBT *page;
+{
+       DBT logrec;
+       DB_LSN *lsnp, null_lsn;
+       u_int32_t zero;
+       u_int32_t rectype, txn_num;
+       int ret;
+       u_int8_t *bp;
+
+       rectype = DB_ham_copypage;
+       txn_num = txnid == NULL ? 0 : txnid->txnid;
+       if (txnid == NULL) {
+               null_lsn.file = 0;
+               null_lsn.offset = 0;
+               lsnp = &null_lsn;
+       } else
+               lsnp = &txnid->last_lsn;
+       logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
+           + sizeof(fileid)
+           + sizeof(pgno)
+           + sizeof(*pagelsn)
+           + sizeof(next_pgno)
+           + sizeof(*nextlsn)
+           + sizeof(nnext_pgno)
+           + sizeof(*nnextlsn)
+           + sizeof(u_int32_t) + (page == NULL ? 0 : page->size);
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
+               return (ENOMEM);
+
+       bp = logrec.data;
+       memcpy(bp, &rectype, sizeof(rectype));
+       bp += sizeof(rectype);
+       memcpy(bp, &txn_num, sizeof(txn_num));
+       bp += sizeof(txn_num);
+       memcpy(bp, lsnp, sizeof(DB_LSN));
+       bp += sizeof(DB_LSN);
+       memcpy(bp, &fileid, sizeof(fileid));
+       bp += sizeof(fileid);
+       memcpy(bp, &pgno, sizeof(pgno));
+       bp += sizeof(pgno);
+       if (pagelsn != NULL)
+               memcpy(bp, pagelsn, sizeof(*pagelsn));
+       else
+               memset(bp, 0, sizeof(*pagelsn));
+       bp += sizeof(*pagelsn);
+       memcpy(bp, &next_pgno, sizeof(next_pgno));
+       bp += sizeof(next_pgno);
+       if (nextlsn != NULL)
+               memcpy(bp, nextlsn, sizeof(*nextlsn));
+       else
+               memset(bp, 0, sizeof(*nextlsn));
+       bp += sizeof(*nextlsn);
+       memcpy(bp, &nnext_pgno, sizeof(nnext_pgno));
+       bp += sizeof(nnext_pgno);
+       if (nnextlsn != NULL)
+               memcpy(bp, nnextlsn, sizeof(*nnextlsn));
+       else
+               memset(bp, 0, sizeof(*nnextlsn));
+       bp += sizeof(*nnextlsn);
+       if (page == NULL) {
+               zero = 0;
+               memcpy(bp, &zero, sizeof(u_int32_t));
+               bp += sizeof(u_int32_t);
+       } else {
+               memcpy(bp, &page->size, sizeof(page->size));
+               bp += sizeof(page->size);
+               memcpy(bp, page->data, page->size);
+               bp += page->size;
+       }
+#ifdef DEBUG
+       if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
+               fprintf(stderr, "Error in log record length");
+#endif
+       ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
+       if (txnid != NULL)
+               txnid->last_lsn = *ret_lsnp;
+       __db_free(logrec.data);
+       return (ret);
+}
+
+/*
+ * PUBLIC: int __ham_copypage_print
+ * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
+ */
+
+int
+__ham_copypage_print(notused1, dbtp, lsnp, notused3, notused4)
+       DB_LOG *notused1;
+       DBT *dbtp;
+       DB_LSN *lsnp;
+       int notused3;
+       void *notused4;
+{
+       __ham_copypage_args *argp;
+       u_int32_t i;
+       int c, ret;
+
+       i = 0;
+       c = 0;
+       notused1 = NULL;
+       notused3 = 0;
+       notused4 = NULL;
+
+       if ((ret = __ham_copypage_read(dbtp->data, &argp)) != 0)
+               return (ret);
+       printf("[%lu][%lu]ham_copypage: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
+           (u_long)lsnp->file,
+           (u_long)lsnp->offset,
+           (u_long)argp->type,
+           (u_long)argp->txnid->txnid,
+           (u_long)argp->prev_lsn.file,
+           (u_long)argp->prev_lsn.offset);
+       printf("\tfileid: %lu\n", (u_long)argp->fileid);
+       printf("\tpgno: %lu\n", (u_long)argp->pgno);
+       printf("\tpagelsn: [%lu][%lu]\n",
+           (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset);
+       printf("\tnext_pgno: %lu\n", (u_long)argp->next_pgno);
+       printf("\tnextlsn: [%lu][%lu]\n",
+           (u_long)argp->nextlsn.file, (u_long)argp->nextlsn.offset);
+       printf("\tnnext_pgno: %lu\n", (u_long)argp->nnext_pgno);
+       printf("\tnnextlsn: [%lu][%lu]\n",
+           (u_long)argp->nnextlsn.file, (u_long)argp->nnextlsn.offset);
+       printf("\tpage: ");
+       for (i = 0; i < argp->page.size; i++) {
+               c = ((char *)argp->page.data)[i];
+               if (isprint(c) || c == 0xa)
+                       putchar(c);
+               else
+                       printf("%#x ", c);
+       }
+       printf("\n");
+       printf("\n");
+       __db_free(argp);
+       return (0);
+}
+
+/*
+ * PUBLIC: int __ham_copypage_read __P((void *, __ham_copypage_args **));
+ */
+int
+__ham_copypage_read(recbuf, argpp)
+       void *recbuf;
+       __ham_copypage_args **argpp;
+{
+       __ham_copypage_args *argp;
+       u_int8_t *bp;
+
+       argp = (__ham_copypage_args *)__db_malloc(sizeof(__ham_copypage_args) +
+           sizeof(DB_TXN));
+       if (argp == NULL)
+               return (ENOMEM);
+       argp->txnid = (DB_TXN *)&argp[1];
+       bp = recbuf;
+       memcpy(&argp->type, bp, sizeof(argp->type));
+       bp += sizeof(argp->type);
+       memcpy(&argp->txnid->txnid,  bp, sizeof(argp->txnid->txnid));
+       bp += sizeof(argp->txnid->txnid);
+       memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN));
+       bp += sizeof(DB_LSN);
+       memcpy(&argp->fileid, bp, sizeof(argp->fileid));
+       bp += sizeof(argp->fileid);
+       memcpy(&argp->pgno, bp, sizeof(argp->pgno));
+       bp += sizeof(argp->pgno);
+       memcpy(&argp->pagelsn, bp,  sizeof(argp->pagelsn));
+       bp += sizeof(argp->pagelsn);
+       memcpy(&argp->next_pgno, bp, sizeof(argp->next_pgno));
+       bp += sizeof(argp->next_pgno);
+       memcpy(&argp->nextlsn, bp,  sizeof(argp->nextlsn));
+       bp += sizeof(argp->nextlsn);
+       memcpy(&argp->nnext_pgno, bp, sizeof(argp->nnext_pgno));
+       bp += sizeof(argp->nnext_pgno);
+       memcpy(&argp->nnextlsn, bp,  sizeof(argp->nnextlsn));
+       bp += sizeof(argp->nnextlsn);
+       memcpy(&argp->page.size, bp, sizeof(u_int32_t));
+       bp += sizeof(u_int32_t);
+       argp->page.data = bp;
+       bp += argp->page.size;
+       *argpp = argp;
+       return (0);
+}
+
 /*
  * PUBLIC: int __ham_init_print __P((DB_ENV *));
  */
@@ -1305,6 +1513,9 @@ __ham_init_print(dbenv)
        if ((ret = __db_add_recovery(dbenv,
            __ham_ovfl_print, DB_ham_ovfl)) != 0)
                return (ret);
+       if ((ret = __db_add_recovery(dbenv,
+           __ham_copypage_print, DB_ham_copypage)) != 0)
+               return (ret);
        return (0);
 }
 
@@ -1338,6 +1549,9 @@ __ham_init_recover(dbenv)
        if ((ret = __db_add_recovery(dbenv,
            __ham_ovfl_recover, DB_ham_ovfl)) != 0)
                return (ret);
+       if ((ret = __db_add_recovery(dbenv,
+           __ham_copypage_recover, DB_ham_copypage)) != 0)
+               return (ret);
        return (0);
 }
 
index 71bd1c5eb0a58acbbd84fdab509f8fd4733abf15..22444e496607b2f4ba40c3c8498ad6cbc4196453 100644 (file)
@@ -42,7 +42,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash_dup.c   10.7 (Sleepycat) 9/15/97";
+static const char sccsid[] = "@(#)hash_dup.c   10.8 (Sleepycat) 10/14/97";
 #endif /* not lint */
 
 /*
@@ -480,7 +480,7 @@ __ham_check_move(hashp, hcp, add_len)
        __ham_copy_item(hashp, hcp->pagep, H_DATAINDEX(hcp->bndx), next_pagep);
 
        /* Now delete the pair from the current page. */
-       ret = __ham_del_pair(hashp, hcp);
+       ret = __ham_del_pair(hashp, hcp, 0);
 
        (void)__ham_put_page(hashp->dbp, hcp->pagep, 1);
        hcp->pagep = next_pagep;
index 8ba42da1a4a9c7b3fb607a063a406416a50c4492..0a12c1454611e4d5452e0f110e2abeddca877ba7 100644 (file)
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash_page.c  10.24 (Sleepycat) 9/17/97";
+static const char sccsid[] = "@(#)hash_page.c  10.29 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 /*
@@ -489,19 +489,20 @@ __ham_putitem(p, dbt, type)
 
 
 /*
- * PUBLIC: int __ham_del_pair __P((HTAB *, HASH_CURSOR *));
+ * PUBLIC: int __ham_del_pair __P((HTAB *, HASH_CURSOR *, int));
  * XXX TODO: if the item is an offdup, delete the other pages and
  * then remove the pair. If the offpage page is 0, then you can
  * just remove the pair.
  */
 int
-__ham_del_pair(hashp, cursorp)
+__ham_del_pair(hashp, cursorp, reclaim_page)
        HTAB *hashp;
        HASH_CURSOR *cursorp;
+       int reclaim_page;
 {
        DBT data_dbt, key_dbt;
        DB_ENV *dbenv;
-       DB_LSN new_lsn, *n_lsn;
+       DB_LSN new_lsn, *n_lsn, tmp_lsn;
        PAGE *p;
        db_indx_t ndx;
        db_pgno_t chg_pgno, pgno;
@@ -542,6 +543,15 @@ __ham_del_pair(hashp, cursorp)
                            HOFFDUP_PGNO(P_ENTRY(p, H_DATAINDEX(ndx))),
                            sizeof(db_pgno_t));
                        ret = __db_ddup(hashp->dbp, pgno, __ham_del_page);
+                       F_CLR(cursorp, H_ISDUP);
+                       break;
+               case H_DUPLICATE:
+                       /*
+                        * If we delete a pair that is/was a duplicate, then
+                        * we had better clear the flag so that we update the
+                        * cursor appropriately.
+                        */
+                       F_CLR(cursorp, H_ISDUP);
                        break;
                }
 
@@ -578,13 +588,13 @@ __ham_del_pair(hashp, cursorp)
                --hashp->hdr->nelem;
 
        /*
-        * Check if the page is empty.  There are two cases.  If it's
-        * empty and it's not the first chain in the bucket (i.e., the
-        * bucket page) then we can simply remove it. If it is the first
-        * chain in the bucket, then we need to copy the second page into
-        * it and remove the second page.
+        * If we need to reclaim the page, then check if the page is empty.
+        * There are two cases.  If it's empty and it's not the first page
+        * in the bucket (i.e., the bucket page) then we can simply remove
+        * it. If it is the first chain in the bucket, then we need to copy
+        * the second page into it and remove the second page.
         */
-       if (NUM_ENT(p) == 0 && PREV_PGNO(p) == PGNO_INVALID &&
+       if (reclaim_page && NUM_ENT(p) == 0 && PREV_PGNO(p) == PGNO_INVALID &&
            NEXT_PGNO(p) != PGNO_INVALID) {
                PAGE *n_pagep, *nn_pagep;
                db_pgno_t tmp_pgno;
@@ -592,7 +602,6 @@ __ham_del_pair(hashp, cursorp)
                /*
                 * First page in chain is empty and we know that there
                 * are more pages in the chain.
-                * XXX Need to log this.
                 */
                if ((ret =
                    __ham_get_page(hashp->dbp, NEXT_PGNO(p), &n_pagep)) != 0)
@@ -605,13 +614,35 @@ __ham_del_pair(hashp, cursorp)
                                (void) __ham_put_page(hashp->dbp, n_pagep, 0);
                                return (ret);
                        }
+               }
+
+               if (DB_LOGGING(hashp->dbp)) {
+                       key_dbt.data = n_pagep;
+                       key_dbt.size = hashp->hdr->pagesize;
+                       if ((ret = __ham_copypage_log(dbenv->lg_info,
+                           (DB_TXN *)hashp->dbp->txn, &new_lsn, 0,
+                           hashp->dbp->log_fileid, PGNO(p), &LSN(p),
+                           PGNO(n_pagep), &LSN(n_pagep), NEXT_PGNO(n_pagep),
+                           NEXT_PGNO(n_pagep) == PGNO_INVALID ? NULL :
+                           &LSN(nn_pagep), &key_dbt)) != 0)
+                               return (ret);
+
+                       /* Move lsn onto page. */
+                       LSN(p) = new_lsn;       /* Structure assignment. */
+                       LSN(n_pagep) = new_lsn;
+                       if (NEXT_PGNO(n_pagep) != PGNO_INVALID)
+                               LSN(nn_pagep) = new_lsn;
+               }
+               if (NEXT_PGNO(n_pagep) != PGNO_INVALID) {
                        PREV_PGNO(nn_pagep) = PGNO(p);
                        (void)__ham_put_page(hashp->dbp, nn_pagep, 1);
                }
 
                tmp_pgno = PGNO(p);
+               tmp_lsn = LSN(p);
                memcpy(p, n_pagep, hashp->hdr->pagesize);
                PGNO(p) = tmp_pgno;
+               LSN(p) = tmp_lsn;
                PREV_PGNO(p) = PGNO_INVALID;
 
                /*
@@ -623,7 +654,8 @@ __ham_del_pair(hashp, cursorp)
                if ((ret = __ham_dirty_page(hashp, p)) != 0 ||
                    (ret = __ham_del_page(hashp->dbp, n_pagep)) != 0)
                        return (ret);
-       } else if (NUM_ENT(p) == 0 && PREV_PGNO(p) != PGNO_INVALID) {
+       } else if (reclaim_page &&
+           NUM_ENT(p) == 0 && PREV_PGNO(p) != PGNO_INVALID) {
                PAGE *n_pagep, *p_pagep;
 
                if ((ret =
@@ -690,13 +722,22 @@ __ham_del_pair(hashp, cursorp)
        }
        __ham_c_update(hashp, cursorp, chg_pgno, 0, 0, 0);
 
+       /*
+        * Since we just deleted a pair from the master page, anything
+        * in cursorp->dpgno should be cleared.
+        */
+       cursorp->dpgno = PGNO_INVALID;
+
        F_CLR(cursorp, H_OK);
        return (ret);
 }
+
 /*
+ * __ham_replpair --
+ *     Given the key data indicated by the cursor, replace part/all of it
+ *     according to the fields in the dbt.
+ *
  * PUBLIC: int __ham_replpair __P((HTAB *, HASH_CURSOR *, DBT *, u_int32_t));
- * Given the key data indicated by the cursor, replace part/all of it
- * according to the fields in the dbt.
  */
 int
 __ham_replpair(hashp, hcp, dbt, make_dup)
@@ -768,7 +809,7 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
                        return (ret);
 
                if (dbt->doff == 0 && dbt->dlen == len) {
-                       ret = __ham_del_pair(hashp, hcp);
+                       ret = __ham_del_pair(hashp, hcp, 0);
                        if (ret == 0)
                            ret = __ham_add_el(hashp,
                                hcp, &tmp, dbt, H_KEYDATA);
@@ -784,15 +825,15 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
                                goto err;
 
                        /* Now we can delete the item. */
-                       if ((ret = __ham_del_pair(hashp, hcp)) != 0) {
-                               free(tdata.data);
+                       if ((ret = __ham_del_pair(hashp, hcp, 0)) != 0) {
+                               __db_free(tdata.data);
                                goto err;
                        }
 
                        /* Now shift old data around to make room for new. */
                        if (change > 0) {
-                               tdata.data = (void *)
-                                   realloc(tdata.data, tdata.size + change);
+                               tdata.data = (void *)__db_realloc(tdata.data,
+                                   tdata.size + change);
                                memset((u_int8_t *)tdata.data + tdata.size,
                                    0, change);
                        }
@@ -812,9 +853,9 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
 
                        /* Now add the pair. */
                        ret = __ham_add_el(hashp, hcp, &tmp, &tdata, type);
-                       free(tdata.data);
+                       __db_free(tdata.data);
                }
-err:           free(tmp.data);
+err:           __db_free(tmp.data);
                return (ret);
        }
 
@@ -1025,7 +1066,7 @@ __ham_split_page(hashp, obucket, nbucket)
                }
        }
        if (big_buf != NULL)
-               free(big_buf);
+               __db_free(big_buf);
 
        /*
         * If the original bucket spanned multiple pages, then we've got
@@ -1549,17 +1590,20 @@ __ham_init_ovflpages(hp)
 {
        DB_LSN new_lsn;
        PAGE *p;
-       db_pgno_t last_pgno;
-       u_int32_t i, numpages;
+       db_pgno_t last_pgno, new_pgno;
+       u_int32_t i, curpages, numpages;
 
-       numpages = hp->hdr->ovfl_point + 1;
+       curpages = hp->hdr->spares[hp->hdr->ovfl_point] - 
+           hp->hdr->spares[hp->hdr->ovfl_point - 1];
+       numpages = hp->hdr->ovfl_point + 1 - curpages;
 
        last_pgno = hp->hdr->last_freed;
+       new_pgno = PGNO_OF(hp, hp->hdr->ovfl_point, curpages + 1);
        if (DB_LOGGING(hp->dbp)) {
                (void)__ham_ovfl_log(hp->dbp->dbenv->lg_info,
                    (DB_TXN *)hp->dbp->txn, &new_lsn, 0,
-                   hp->dbp->log_fileid, PGNO_OF(hp, hp->hdr->ovfl_point, 1),
-                   numpages, last_pgno, &hp->hdr->lsn);
+                   hp->dbp->log_fileid, new_pgno,
+                   numpages, last_pgno, hp->hdr->ovfl_point, &hp->hdr->lsn);
                hp->hdr->lsn = new_lsn;
        } else
                ZERO_LSN(new_lsn);
@@ -1567,7 +1611,8 @@ __ham_init_ovflpages(hp)
        hp->hdr->spares[hp->hdr->ovfl_point] += numpages;
        for (i = numpages; i > 0; i--) {
                if (__ham_new_page(hp,
-                   PGNO_OF(hp, hp->hdr->ovfl_point, i), P_INVALID, &p) != 0)
+                   PGNO_OF(hp, hp->hdr->ovfl_point, curpages + i),
+                   P_INVALID, &p) != 0)
                        break;
                LSN(p) = new_lsn;
                NEXT_PGNO(p) = last_pgno;
index 1b30be337df2e67944108734c4e52a5a46158a8f..d239e3d0df601f045bff4485e76b57f8690a1728 100644 (file)
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)hash_rec.c   10.13 (Sleepycat) 9/15/97";
+static const char sccsid[] = "@(#)hash_rec.c   10.14 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -756,7 +756,6 @@ __ham_ovfl_recover(logp, dbtp, lsnp, redo, info)
        hashp = (HTAB *)file_dbp->internal;
        GET_META(file_dbp, hashp);
        getmeta = 1;
-       file_dbp = NULL;
 
        cmp_n = log_compare(lsnp, &hashp->hdr->lsn);
        cmp_p = log_compare(&hashp->hdr->lsn, &argp->metalsn);
@@ -764,12 +763,12 @@ __ham_ovfl_recover(logp, dbtp, lsnp, redo, info)
        if (cmp_p == 0 && redo) {
                /* Redo the allocation. */
                hashp->hdr->last_freed = argp->start_pgno;
-               hashp->hdr->spares[argp->npages  - 1] += argp->npages;
+               hashp->hdr->spares[argp->ovflpoint] += argp->npages;
                hashp->hdr->lsn = *lsnp;
                F_SET(file_dbp, DB_HS_DIRTYMETA);
        } else if (cmp_n == 0 && !redo) {
                hashp->hdr->last_freed = argp->free_pgno;
-               hashp->hdr->spares[argp->npages  - 1] -= argp->npages;
+               hashp->hdr->spares[argp->ovflpoint] -= argp->npages;
                hashp->hdr->lsn = argp->metalsn;
                F_SET(file_dbp, DB_HS_DIRTYMETA);
        }
@@ -808,3 +807,142 @@ out:      if (getmeta)
                RELEASE_META(file_dbp, hashp);
        REC_CLOSE;
 }
+
+/*
+ * __ham_copypage_recover --
+ *     Recovery function for copypage.
+ * 
+ * PUBLIC: int __ham_copypage_recover
+ * PUBLIC:   __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
+ */
+int
+__ham_copypage_recover(logp, dbtp, lsnp, redo, info)
+       DB_LOG *logp;
+       DBT *dbtp;
+       DB_LSN *lsnp;
+       int redo;
+       void *info;
+{
+       __ham_copypage_args *argp;
+       DB *file_dbp, *mdbp;
+       DB_MPOOLFILE *mpf;
+       HTAB *hashp;
+       PAGE *pagep;
+       int cmp_n, cmp_p, getmeta, modified, ret;
+
+       getmeta = 0;
+       hashp = NULL;                           /* XXX: shut the compiler up. */
+       REC_PRINT(__ham_copypage_print);
+       REC_INTRO(__ham_copypage_read);
+
+       hashp = (HTAB *)file_dbp->internal;
+       GET_META(file_dbp, hashp);
+       getmeta = 1;
+       modified = 0;
+
+       /* This is the bucket page. */
+       ret = memp_fget(mpf, &argp->pgno, 0, &pagep);
+       if (ret != 0)
+               if (!redo) {
+                       /*
+                        * We are undoing and the page doesn't exist.  That
+                        * is equivalent to having a pagelsn of 0, so we
+                        * would not have to undo anything.  In this case,
+                        * don't bother creating a page.
+                        */
+                       ret = 0;
+                       goto donext;
+               } else if ((ret = memp_fget(mpf, &argp->pgno,
+                   DB_MPOOL_CREATE, &pagep)) != 0)
+                       goto out;
+
+       cmp_n = log_compare(lsnp, &LSN(pagep));
+       cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
+
+       if (cmp_p == 0 && redo) {
+               /* Need to redo update described. */
+               memcpy(pagep, argp->page.data, argp->page.size);
+               LSN(pagep) = *lsnp;
+               modified = 1;
+       } else if (cmp_n == 0 && !redo) {
+               /* Need to undo update described. */
+               P_INIT(pagep, hashp->hdr->pagesize, argp->pgno, PGNO_INVALID,
+                   argp->next_pgno, 0, P_HASH);
+               LSN(pagep) = argp->pagelsn;
+               modified = 1;
+       }
+       if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+               goto out;
+
+       /* Now fix up the "next" page. */
+donext:        ret = memp_fget(mpf, &argp->next_pgno, 0, &pagep);
+       if (ret != 0)
+               if (!redo) {
+                       /*
+                        * We are undoing and the page doesn't exist.  That
+                        * is equivalent to having a pagelsn of 0, so we
+                        * would not have to undo anything.  In this case,
+                        * don't bother creating a page.
+                        */
+                       ret = 0;
+                       goto do_nn;
+               } else if ((ret = memp_fget(mpf, &argp->next_pgno,
+                   DB_MPOOL_CREATE, &pagep)) != 0)
+                       goto out;
+
+       /* There is nothing to do in the REDO case; only UNDO. */
+
+       cmp_n = log_compare(lsnp, &LSN(pagep));
+       if (cmp_n == 0 && !redo) {
+               /* Need to undo update described. */
+               memcpy(pagep, argp->page.data, argp->page.size);
+               modified = 1;
+       }
+       if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+               goto out;
+
+       /* Now fix up the next's next page. */
+do_nn: if (argp->nnext_pgno == PGNO_INVALID) {
+               *lsnp = argp->prev_lsn;
+               goto out;
+       }
+
+       ret = memp_fget(mpf, &argp->nnext_pgno, 0, &pagep);
+       if (ret != 0)
+               if (!redo) {
+                       /*
+                        * We are undoing and the page doesn't exist.  That
+                        * is equivalent to having a pagelsn of 0, so we
+                        * would not have to undo anything.  In this case,
+                        * don't bother creating a page.
+                        */
+                       ret = 0;
+                       *lsnp = argp->prev_lsn;
+                       goto out;
+               } else if ((ret = memp_fget(mpf, &argp->nnext_pgno,
+                   DB_MPOOL_CREATE, &pagep)) != 0)
+                       goto out;
+
+       cmp_n = log_compare(lsnp, &LSN(pagep));
+       cmp_p = log_compare(&LSN(pagep), &argp->nnextlsn);
+
+       if (cmp_p == 0 && redo) {
+               /* Need to redo update described. */
+               PREV_PGNO(pagep) = argp->pgno;
+               LSN(pagep) = *lsnp;
+               modified = 1;
+       } else if (cmp_n == 0 && !redo) {
+               /* Need to undo update described. */
+               PREV_PGNO(pagep) = argp->next_pgno;
+               LSN(pagep) = argp->nnextlsn;
+               modified = 1;
+       }
+       if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+               goto out;
+
+       *lsnp = argp->prev_lsn;
+
+out:   if (getmeta)
+               RELEASE_META(file_dbp, hashp);
+       REC_CLOSE;
+}
index b422e1db1b77fd45a265aa37bbb9747b632239d8..041b80f19684239789e6f6fcd9932690bb248c8c 100644 (file)
@@ -58,6 +58,7 @@ typedef struct _bam_rsplit_args {
        u_int32_t       fileid;
        db_pgno_t       pgno;
        DBT     pgdbt;
+       db_pgno_t       nrec;
        DBT     rootent;
        DB_LSN  rootlsn;
 } __bam_rsplit_args;
@@ -105,4 +106,22 @@ typedef struct _bam_cdel_args {
        u_int32_t       indx;
 } __bam_cdel_args;
 
+
+#define        DB_bam_repl     (DB_bam_BEGIN + 8)
+
+typedef struct _bam_repl_args {
+       u_int32_t type;
+       DB_TXN *txnid;
+       DB_LSN prev_lsn;
+       u_int32_t       fileid;
+       db_pgno_t       pgno;
+       DB_LSN  lsn;
+       u_int32_t       indx;
+       u_int32_t       isdeleted;
+       DBT     orig;
+       DBT     repl;
+       u_int32_t       prefix;
+       u_int32_t       suffix;
+} __bam_repl_args;
+
 #endif
index 9133c58c6bf46a6c504338e95dac5ea52534a761..bbe0d971b2dd09ca0cba04788c5d8a1d129e5c50 100644 (file)
@@ -1,4 +1,4 @@
-/* Do not edit: automatically built by dist/distrib. */
+/* DO NOT EDIT: automatically built by dist/distrib. */
 int __bam_close __P((DB *));
 int __bam_sync __P((DB *, int));
 int __bam_cmp __P((DB *, const DBT *, EPG *));
@@ -35,6 +35,7 @@ int __bam_pget __P((DB *, PAGE **, db_pgno_t *, int));
 int __bam_put __P((DB *, DB_TXN *, DBT *, DBT *, int));
 int __bam_iitem __P((DB *,
    PAGE **, db_indx_t *, DBT *, DBT *, int, int));
+int __bam_ritem __P((DB *, PAGE *, u_int32_t, DBT *));
 int __bam_pg_alloc_recover
   __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __bam_pg_free_recover
@@ -49,6 +50,8 @@ int __bam_cadjust_recover
   __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __bam_cdel_recover
   __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
+int __bam_repl_recover
+  __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __ram_open __P((DB *, DBTYPE, DB_INFO *));
 int __ram_cursor __P((DB *, DB_TXN *, DBC **));
 int __ram_close __P((DB *));
@@ -94,8 +97,8 @@ int __bam_split_print
 int __bam_split_read __P((void *, __bam_split_args **));
 int __bam_rsplit_log
     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
-    u_int32_t, db_pgno_t, DBT *, DBT *,
-    DB_LSN *));
+    u_int32_t, db_pgno_t, DBT *, db_pgno_t,
+    DBT *, DB_LSN *));
 int __bam_rsplit_print
    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __bam_rsplit_read __P((void *, __bam_rsplit_args **));
@@ -119,5 +122,13 @@ int __bam_cdel_log
 int __bam_cdel_print
    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __bam_cdel_read __P((void *, __bam_cdel_args **));
+int __bam_repl_log
+    __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
+    u_int32_t, db_pgno_t, DB_LSN *, u_int32_t,
+    u_int32_t, DBT *, DBT *, u_int32_t,
+    u_int32_t));
+int __bam_repl_print
+   __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
+int __bam_repl_read __P((void *, __bam_repl_args **));
 int __bam_init_print __P((DB_ENV *));
 int __bam_init_recover __P((DB_ENV *));
index 8ccd2b559fc7c4516c597a477f60bc09a2b8741c..91e4a13fa588f158ed99adb3b580a60b85fdcb87 100644 (file)
@@ -1,4 +1,4 @@
-/* Do not edit: automatically built by dist/distrib. */
+/* DO NOT EDIT: automatically built by dist/distrib. */
 #ifdef __STDC__
 void err __P((int eval, const char *, ...));
 #else
index 9840162a12e838ef6366e6c6faa556340a463f0d..b814582abd7088b93b2574ae318575c2a454f70e 100644 (file)
@@ -1,4 +1,4 @@
-/* Do not edit: automatically built by dist/distrib. */
+/* DO NOT EDIT: automatically built by dist/distrib. */
 int __db_appname __P((DB_ENV *,
    APPNAME, const char *, const char *, int *, char **));
 int __db_apprec __P((DB_ENV *, int));
@@ -24,6 +24,7 @@ int __db_ferr __P((const DB_ENV *, const char *, int));
 u_int32_t __db_log2 __P((u_int32_t));
 int __db_rcreate __P((DB_ENV *, APPNAME,
    const char *, const char *, int, size_t, int *, void *));
+int __db_rinit __P((DB_ENV *, RLAYOUT *, int, size_t, int));
 int __db_ropen __P((DB_ENV *,
    APPNAME, const char *, const char *, int, int *, void *));
 int __db_rclose __P((DB_ENV *, int, void *));
index 63d9603dbae032f7976fc66d57b6af5b37ef9d88..3cc2bfd4fc4c466173bbd036a061c391fa7f50fb 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db.h.src    10.77 (Sleepycat) 9/24/97
+ *     @(#)db.h.src    10.91 (Sleepycat) 11/3/97
  */
 
 #ifndef _DB_H_
  * XXX
  * Handle function prototypes and the keyword "const".  This steps on name
  * space that DB doesn't control, but all of the other solutions are worse.
+ *
+ * XXX
+ * While Microsoft's compiler is ANSI C compliant, it doesn't have _STDC_
+ * defined by default, you specify a command line flag or #pragma to turn
+ * it on.  Don't do that, however, because some of Microsoft's own header
+ * files won't compile.
  */
 #undef __P
-#if defined(__STDC__) || defined(__cplusplus)
+#if defined(__STDC__) || defined(__cplusplus) || defined(_MSC_VER)
 #define        __P(protos)     protos          /* ANSI C prototypes */
 #else
 #define        const
@@ -67,8 +73,8 @@
 
 #define        DB_VERSION_MAJOR        2
 #define        DB_VERSION_MINOR        3
-#define        DB_VERSION_PATCH        10
-#define        DB_VERSION_STRING       "Sleepycat Software: DB 2.3.10: (9/24/97)"
+#define        DB_VERSION_PATCH        12
+#define        DB_VERSION_STRING       "Sleepycat Software: DB 2.3.12: (11/3/97)"
 
 typedef        u_int32_t       db_pgno_t;      /* Page number type. */
 typedef        u_int16_t       db_indx_t;      /* Page offset type. */
@@ -93,6 +99,7 @@ struct __db_lockregion;       typedef struct __db_lockregion DB_LOCKREGION;
 struct __db_lockreq;   typedef struct __db_lockreq DB_LOCKREQ;
 struct __db_locktab;   typedef struct __db_locktab DB_LOCKTAB;
 struct __db_log;       typedef struct __db_log DB_LOG;
+struct __db_log_stat;  typedef struct __db_log_stat DB_LOG_STAT;
 struct __db_lsn;       typedef struct __db_lsn DB_LSN;
 struct __db_mpool;     typedef struct __db_mpool DB_MPOOL;
 struct __db_mpool_fstat;typedef struct __db_mpool_fstat DB_MPOOL_FSTAT;
@@ -121,6 +128,31 @@ struct __db_dbt {
        u_int32_t flags;
 };
 
+/*
+ * DB configuration.  There are a set of functions which the application
+ * can replace with its own versions.
+ */
+#define        DB_FUNC_CALLOC   1              /* ANSI C calloc. */
+#define        DB_FUNC_CLOSE    2              /* POSIX 1003.1 close. */
+#define        DB_FUNC_DIRFREE  3              /* DB: free directory list. */
+#define        DB_FUNC_DIRLIST  4              /* DB: create directory list. */
+#define        DB_FUNC_EXISTS   5              /* DB: return if file exists. */
+#define        DB_FUNC_FREE     6              /* ANSI C free. */
+#define        DB_FUNC_FSYNC    7              /* POSIX 1003.1 fsync. */
+#define        DB_FUNC_IOINFO   8              /* DB: return file I/O information. */
+#define        DB_FUNC_MALLOC   9              /* ANSI C malloc. */
+#define        DB_FUNC_MAP     10              /* DB: map file into shared memory. */
+#define        DB_FUNC_OPEN    11              /* POSIX 1003.1 open. */
+#define        DB_FUNC_READ    12              /* POSIX 1003.1 read. */
+#define        DB_FUNC_REALLOC 13              /* ANSI C realloc. */
+#define        DB_FUNC_SEEK    14              /* POSIX 1003.1 lseek. */
+#define        DB_FUNC_SLEEP   15              /* DB: sleep secs/usecs. */
+#define        DB_FUNC_STRDUP  16              /* ANSI C strdup. */
+#define        DB_FUNC_UNLINK  17              /* POSIX 1003.1 unlink. */
+#define        DB_FUNC_UNMAP   18              /* DB: unmap shared memory file. */
+#define        DB_FUNC_WRITE   19              /* POSIX 1003.1 write. */
+#define        DB_FUNC_YIELD   20              /* DB: yield thread to scheduler. */
+
 /*
  * Database configuration and initialization.
  */
@@ -134,21 +166,20 @@ struct __db_dbt {
 /*
  * Flags understood by db_appinit(3).
  *
- * DB_APP_INIT and DB_MUTEXDEBUG are internal only, and not documented.
+ * DB_MUTEXDEBUG is internal only, and not documented.
  */
 /*                             0x00007    COMMON MASK. */
-#define        DB_APP_INIT             0x00008 /* Appinit called, paths initialized. */
-#define        DB_INIT_LOCK            0x00010 /* Initialize locking. */
-#define        DB_INIT_LOG             0x00020 /* Initialize logging. */
-#define        DB_INIT_MPOOL           0x00040 /* Initialize mpool. */
-#define        DB_INIT_TXN             0x00080 /* Initialize transactions. */
-#define        DB_MPOOL_PRIVATE        0x00100 /* Mpool: private memory pool. */
-#define        DB_MUTEXDEBUG           0x00200 /* Do not get/set mutexes in regions. */
-#define        DB_RECOVER              0x00400 /* Run normal recovery. */
-#define        DB_RECOVER_FATAL        0x00800 /* Run catastrophic recovery. */
-#define        DB_TXN_NOSYNC           0x01000 /* Do not sync log on commit. */
-#define        DB_USE_ENVIRON          0x02000 /* Use the environment. */
-#define        DB_USE_ENVIRON_ROOT     0x04000 /* Use the environment if root. */
+#define        DB_INIT_LOCK            0x00008 /* Initialize locking. */
+#define        DB_INIT_LOG             0x00010 /* Initialize logging. */
+#define        DB_INIT_MPOOL           0x00020 /* Initialize mpool. */
+#define        DB_INIT_TXN             0x00040 /* Initialize transactions. */
+#define        DB_MPOOL_PRIVATE        0x00080 /* Mpool: private memory pool. */
+#define        DB_MUTEXDEBUG           0x00100 /* Do not get/set mutexes in regions. */
+#define        DB_RECOVER              0x00200 /* Run normal recovery. */
+#define        DB_RECOVER_FATAL        0x00400 /* Run catastrophic recovery. */
+#define        DB_TXN_NOSYNC           0x00800 /* Do not sync log on commit. */
+#define        DB_USE_ENVIRON          0x01000 /* Use the environment. */
+#define        DB_USE_ENVIRON_ROOT     0x02000 /* Use the environment if root. */
 
 /* CURRENTLY UNUSED LOCK FLAGS. */
 #define        DB_TXN_LOCK_2PL         0x00000 /* Two-phase locking. */
@@ -209,7 +240,6 @@ struct __db_env {
        int              lk_modes;      /* Number of lock modes in table. */
        unsigned int     lk_max;        /* Maximum number of locks. */
        u_int32_t        lk_detect;     /* Deadlock detect on every conflict. */
-       int (*db_yield) __P((void));    /* Yield function for threads. */
 
        /* Logging. */
        DB_LOG          *lg_info;       /* Return from log_open(). */
@@ -226,6 +256,9 @@ struct __db_env {
        int (*tx_recover)               /* Dispatch function for recovery. */
            __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 
+#define        DB_ENV_APPINIT          0x01    /* Paths initialized by db_appinit(). */
+#define        DB_ENV_STANDALONE       0x02    /* Test: freestanding environment. */
+#define        DB_ENV_THREAD           0x04    /* DB_ENV is multi-threaded. */
        u_int32_t        flags;         /* Flags. */
 };
 
@@ -301,7 +334,7 @@ struct __db_info {
 #define        DB_CURRENT      0x000010        /* c_get(), c_put(), log_get() */
 #define        DB_FIRST        0x000020        /* c_get(), log_get() */
 #define        DB_FLUSH        0x000040        /* log_put() */
-#define        DB_GET_RECNO    0x000080        /* c_get() */
+#define        DB_GET_RECNO    0x000080        /* get(), c_get() */
 #define        DB_KEYFIRST     0x000100        /* c_put() */
 #define        DB_KEYLAST      0x000200        /* c_put() */
 #define        DB_LAST         0x000400        /* c_get(), log_get() */
@@ -312,7 +345,7 @@ struct __db_info {
 #define        DB_RECORDCOUNT  0x008000        /* stat() */
 #define        DB_SET          0x010000        /* c_get(), log_get() */
 #define        DB_SET_RANGE    0x020000        /* c_get() */
-#define        DB_SET_RECNO    0x040000        /* get(), c_get() */
+#define        DB_SET_RECNO    0x040000        /* c_get() */
 
 /* DB (user visible) error return codes. */
 #define        DB_INCOMPLETE           ( -1)   /* Sync didn't finish. */
@@ -472,6 +505,8 @@ struct __db_bt_stat {
        u_int32_t bt_get;               /* Items retrieved. */
        u_int32_t bt_cache_hit;         /* Hits in fast-insert code. */
        u_int32_t bt_cache_miss;        /* Misses in fast-insert code. */
+       u_int32_t bt_magic;             /* Magic number. */
+       u_int32_t bt_version;           /* Version number. */
 };
 
 #if defined(__cplusplus)
@@ -479,6 +514,7 @@ extern "C" {
 #endif
 int   db_appinit __P((const char *, char * const *, DB_ENV *, int));
 int   db_appexit __P((DB_ENV *));
+int   db_jump_set __P((void *, int));
 int   db_open __P((const char *, DBTYPE, int, int, DB_ENV *, DB_INFO *, DB **));
 char *db_version __P((int *, int *, int *));
 #if defined(__cplusplus)
@@ -576,6 +612,22 @@ struct __db_lsn {
        u_int32_t       offset;         /* File offset. */
 };
 
+/* Log statistics structure. */
+struct __db_log_stat {
+       u_int32_t st_magic;             /* Log file magic number. */
+       u_int32_t st_version;           /* Log file version number. */
+       int st_mode;                    /* Log file mode. */
+       u_int32_t st_lg_max;            /* Maximum log file size. */
+       u_int32_t st_w_bytes;           /* Bytes to log. */
+       u_int32_t st_w_mbytes;          /* Megabytes to log. */
+       u_int32_t st_wc_bytes;          /* Bytes to log since checkpoint. */
+       u_int32_t st_wc_mbytes;         /* Megabytes to log since checkpoint. */
+       u_int32_t st_wcount;            /* Total syncs to the log. */
+       u_int32_t st_scount;            /* Total writes to the log. */
+       u_int32_t st_region_wait;       /* Region lock granted after wait. */
+       u_int32_t st_region_nowait;     /* Region lock granted without wait. */
+};
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -588,6 +640,7 @@ int  log_get __P((DB_LOG *, DB_LSN *, DBT *, int));
 int     log_open __P((const char *, int, int, DB_ENV *, DB_LOG **));
 int     log_put __P((DB_LOG *, DB_LSN *, const DBT *, int));
 int     log_register __P((DB_LOG *, DB *, const char *, DBTYPE, u_int32_t *));
+int     log_stat __P((DB_LOG *, DB_LOG_STAT **, void *(*)(size_t)));
 int     log_unlink __P((const char *, int, DB_ENV *));
 int     log_unregister __P((DB_LOG *, u_int32_t));
 #if defined(__cplusplus)
@@ -610,30 +663,35 @@ int        log_unregister __P((DB_LOG *, u_int32_t));
 /* Mpool statistics structure. */
 struct __db_mpool_stat {
        size_t st_cachesize;            /* Cache size. */
-       unsigned long st_cache_hit;     /* Pages found in the cache. */
-       unsigned long st_cache_miss;    /* Pages not found in the cache. */
-       unsigned long st_map;           /* Pages from mapped files. */
-       unsigned long st_page_create;   /* Pages created in the cache. */
-       unsigned long st_page_in;       /* Pages read in. */
-       unsigned long st_page_out;      /* Pages written out. */
-       unsigned long st_ro_evict;      /* Read-only pages evicted. */
-       unsigned long st_rw_evict;      /* Read-write pages evicted. */
-       unsigned long st_hash_buckets;  /* Number of hash buckets. */
-       unsigned long st_hash_searches; /* Total hash chain searches. */
-       unsigned long st_hash_longest;  /* Longest hash chain searched. */
-       unsigned long st_hash_examined; /* Total hash entries searched. */
+       u_int32_t st_cache_hit;         /* Pages found in the cache. */
+       u_int32_t st_cache_miss;        /* Pages not found in the cache. */
+       u_int32_t st_map;               /* Pages from mapped files. */
+       u_int32_t st_page_create;       /* Pages created in the cache. */
+       u_int32_t st_page_in;           /* Pages read in. */
+       u_int32_t st_page_out;          /* Pages written out. */
+       u_int32_t st_ro_evict;          /* Clean pages forced from the cache. */
+       u_int32_t st_rw_evict;          /* Dirty pages forced from the cache. */
+       u_int32_t st_hash_buckets;      /* Number of hash buckets. */
+       u_int32_t st_hash_searches;     /* Total hash chain searches. */
+       u_int32_t st_hash_longest;      /* Longest hash chain searched. */
+       u_int32_t st_hash_examined;     /* Total hash entries searched. */
+       u_int32_t st_page_clean;        /* Clean pages. */
+       u_int32_t st_page_dirty;        /* Dirty pages. */
+       u_int32_t st_page_trickle;      /* Pages written by memp_trickle. */
+       u_int32_t st_region_wait;       /* Region lock granted after wait. */
+       u_int32_t st_region_nowait;     /* Region lock granted without wait. */
 };
 
 /* Mpool file statistics structure. */
 struct __db_mpool_fstat {
        char *file_name;                /* File name. */
        size_t st_pagesize;             /* Page size. */
-       unsigned long st_cache_hit;     /* Pages found in the cache. */
-       unsigned long st_cache_miss;    /* Pages not found in the cache. */
-       unsigned long st_map;           /* Pages from mapped files. */
-       unsigned long st_page_create;   /* Pages created in the cache. */
-       unsigned long st_page_in;       /* Pages read in. */
-       unsigned long st_page_out;      /* Pages written out. */
+       u_int32_t st_cache_hit;         /* Pages found in the cache. */
+       u_int32_t st_cache_miss;        /* Pages not found in the cache. */
+       u_int32_t st_map;               /* Pages from mapped files. */
+       u_int32_t st_page_create;       /* Pages created in the cache. */
+       u_int32_t st_page_in;           /* Pages read in. */
+       u_int32_t st_page_out;          /* Pages written out. */
 };
 
 #if defined(__cplusplus)
@@ -654,6 +712,7 @@ int memp_register __P((DB_MPOOL *, int,
 int    memp_stat __P((DB_MPOOL *,
            DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, void *(*)(size_t)));
 int    memp_sync __P((DB_MPOOL *, DB_LSN *));
+int    memp_trickle __P((DB_MPOOL *, int, int *));
 int    memp_unlink __P((const char *, int, DB_ENV *));
 #if defined(__cplusplus)
 };
index 5814ff88c3e540f04659181737eda701bc95367d..0ea24be667390b263c8b0ef908ba85360b1b8813 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db_am.h     10.6 (Sleepycat) 8/27/97
+ *     @(#)db_am.h     10.7 (Sleepycat) 10/25/97
  */
 #ifndef _DB_AM_H
 #define _DB_AM_H
@@ -49,7 +49,7 @@
 }
 #define        REC_CLOSE {                                                     \
        if (argp != NULL)                                               \
-               free (argp);                                            \
+               __db_free(argp);                                        \
        if (file_dbp != NULL) {                                         \
                F_CLR(file_dbp, DB_AM_RECOVER);                         \
                if (F_ISSET(file_dbp, DB_AM_THREAD))                    \
@@ -67,7 +67,7 @@
 }
 #define        REC_NOOP_CLOSE {                                                \
        if (argp != NULL)                                               \
-               free (argp);                                            \
+               __db_free(argp);                                        \
        return (ret);                                                   \
 }
 
index 7478173740fd7f43a2ba0fe2630f770781406618..4c7b4da97084409d1352d53ee584aa6170915f3e 100644 (file)
@@ -59,6 +59,7 @@ typedef struct _db_ovref_args {
        DB_LSN prev_lsn;
        u_int32_t       fileid;
        db_pgno_t       pgno;
+       int32_t adjust;
        DB_LSN  lsn;
 } __db_ovref_args;
 
index 611d967ef9436458eaf80545a544ea51ece6df45..01d12310924e51b3ba8597c01283b6687b667723 100644 (file)
@@ -4,12 +4,11 @@
  * Copyright (c) 1997
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db_cxx.h    10.8 (Sleepycat) 9/20/97
+ *     @(#)db_cxx.h    10.12 (Sleepycat) 10/25/97
  */
 
 #ifndef _DB_CXX_H_
 #define _DB_CXX_H_
-
 //
 // C++ assumptions:
 //
@@ -264,7 +263,7 @@ public:
     // Normally these would be called register and unregister to
     // parallel the C interface, but "register" is a reserved word.
     //
-    int db_register(Db *dbp, const char *name, u_int32_t *fidp);
+    int db_register(Db *dbp, const char *name, DBTYPE type, u_int32_t *fidp);
     int db_unregister(u_int32_t fid);
 
     // Create or remove new log files
@@ -353,6 +352,7 @@ public:
     int stat(DB_MPOOL_STAT **gsp, DB_MPOOL_FSTAT ***fsp,
              void *(*db_malloc)(size_t));
     int sync(DbLsn *lsn);
+    int trickle(int pct, int *nwrotep);
 
     // Create or remove new mpool files
     //
@@ -598,6 +598,11 @@ public:
     //
     int appinit(const char *homeDir, char *const *db_config, int flags);
 
+    // Called automatically when DbEnv is destroyed, or can be
+    // called at any time to shut down Db.
+    //
+    int appexit();
+
     ////////////////////////////////////////////////////////////////
     // simple get/set access methods
     //
@@ -675,11 +680,6 @@ public:
     u_int32_t get_lk_detect() const;
     void set_lk_detect(u_int32_t);
 
-    // Yield function for threads.
-    typedef int (*db_yield_fcn) (void);
-    db_yield_fcn get_yield() const;
-    void set_yield(db_yield_fcn);
-
 
     ////////////////////////////////////////////////////////////////
     // Logging.
@@ -783,7 +783,7 @@ class _exported Db
 public:
     int close(int flags);
     int cursor(DbTxn *txnid, Dbc **cursorp);
-    int del(Dbt *key, DbTxn *txnid);
+    int del(DbTxn *txnid, Dbt *key, int flags);
     int fd(int *fdp);
     int get(DbTxn *txnid, Dbt *key, Dbt *data, int flags);
     int put(DbTxn *txnid, Dbt *key, Dbt *data, int flags);
@@ -884,5 +884,4 @@ private:
     Dbc(const Dbc &);
     Dbc &operator = (const Dbc &);
 };
-
 #endif /* !_DB_CXX_H_ */
index b18b10ff7f24e565a0d3fd2d5333d04afc9c992c..f9b3b3a214d646dd23b3bd0206dffe5a8dc0cd38 100644 (file)
@@ -1,4 +1,4 @@
-/* Do not edit: automatically built by dist/distrib. */
+/* DO NOT EDIT: automatically built by dist/distrib. */
 int __db_pgerr __P((DB *, db_pgno_t));
 int __db_pgfmt __P((DB *, db_pgno_t));
 int __db_addrem_log
@@ -25,7 +25,7 @@ int __db_big_print
 int __db_big_read __P((void *, __db_big_args **));
 int __db_ovref_log
     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
-    u_int32_t, db_pgno_t, DB_LSN *));
+    u_int32_t, db_pgno_t, int32_t, DB_LSN *));
 int __db_ovref_print
    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __db_ovref_read __P((void *, __db_ovref_args **));
@@ -79,7 +79,7 @@ int __db_goff __P((DB *, DBT *,
     u_int32_t, db_pgno_t, void **, u_int32_t *));
 int __db_poff __P((DB *, const DBT *, db_pgno_t *,
     int (*)(DB *, u_int32_t, PAGE **)));
-int __db_ioff __P((DB *, db_pgno_t));
+int __db_ovref __P((DB *, db_pgno_t, int));
 int __db_doff __P((DB *, db_pgno_t, int (*)(DB *, PAGE *)));
 int __db_moff __P((DB *, const DBT *, db_pgno_t));
 void __db_loadme __P((void));
index ebadb35d364a53877f87246b2c4331415d2b6a9d..abd93a6e8e84b2a8f19b1e897abe4d7311be1ff4 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)db_int.h.src        10.30 (Sleepycat) 9/23/97
+ *     @(#)db_int.h.src        10.36 (Sleepycat) 10/31/97
  */
 
 #ifndef _DB_INTERNAL_H_
@@ -12,6 +12,7 @@
 
 #include "db.h"                                /* Standard DB include file. */
 #include "queue.h"
+#include "os_func.h"
 #include "os_ext.h"
 
 /*******************************************************
 #undef SSZA
 #define SSZA(name, field)      ((int)&(((name *)0)->field[0]))
 
+/* Macros to return per-process address, offsets based on shared regions. */
+#define        R_ADDR(base, offset)    ((void *)((u_int8_t *)((base)->addr) + offset))
+#define        R_OFFSET(base, p)       ((u_int8_t *)(p) - (u_int8_t *)(base)->addr)
+
 /* Free and free-string macros that overwrite memory during debugging. */
 #ifdef DEBUG
 #undef FREE
 #define        FREE(p, len) {                                                  \
        memset(p, 0xff, len);                                           \
-       free(p);                                                        \
+       __db_free(p);                                                   \
 }
 #undef FREES
 #define        FREES(p) {                                                      \
 #else
 #undef FREE
 #define        FREE(p, len) {                                                  \
-       free(p);                                                        \
+       __db_free(p);                                                   \
 }
 #undef FREES
 #define        FREES(p) {                                                      \
-       free(p);                                                        \
+       __db_free(p);                                                   \
 }
 #endif
 
 /* Structure used to print flag values. */
 typedef struct __fn {
        u_int32_t mask;                 /* Flag value. */
-       char     *name;                 /* Flag name. */
+       const char *name;               /* Flag name. */
 } FN;
 
 /* Set, clear and test flags. */
@@ -163,10 +168,8 @@ typedef struct _db_mutex_t {
        off_t   off;                    /* Backing file offset. */
        u_long  pid;                    /* Lock holder: 0 or process pid. */
 #endif
-#ifdef MUTEX_STATISTICS
-       u_long  mutex_set_wait;         /* Blocking mutex: required waiting. */
-       u_long  mutex_set_nowait;       /* Blocking mutex: without waiting. */
-#endif
+       u_int32_t mutex_set_wait;       /* Granted after wait. */
+       u_int32_t mutex_set_nowait;     /* Granted without waiting. */
 } db_mutex_t;
 
 #include "mutex_ext.h"
@@ -177,11 +180,10 @@ typedef struct _db_mutex_t {
 /* Lock/unlock a DB thread. */
 #define        DB_THREAD_LOCK(dbp)                                             \
        (F_ISSET(dbp, DB_AM_THREAD) ?                                   \
-           __db_mutex_lock((db_mutex_t *)(dbp)->mutexp,  -1,           \
-               (dbp)->dbenv == NULL ? NULL : (dbp)->dbenv->db_yield) : 0)
+           __db_mutex_lock((db_mutex_t *)(dbp)->mutexp, -1) : 0)
 #define        DB_THREAD_UNLOCK(dbp)                                           \
        (F_ISSET(dbp, DB_AM_THREAD) ?                                   \
-           __db_mutex_unlock((db_mutex_t *)(dbp)->mutexp,  -1) : 0)
+           __db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1) : 0)
 
 /* Btree/recno local statistics structure. */
 struct __db_bt_lstat;  typedef struct __db_bt_lstat DB_BTREE_LSTAT;
@@ -260,7 +262,7 @@ typedef struct __dbpginfo {
 #define        IS_ZERO_LSN(LSN)        ((LSN).file == 0)
 
 /* Test if we need to log a change. */
-#define        DB_LOGGING(dbp) \
+#define        DB_LOGGING(dbp)                                                 \
        (F_ISSET(dbp, DB_AM_LOGGING) && !F_ISSET(dbp, DB_AM_RECOVER))
 
 #ifdef DEBUG
index cb8ea350f52fd2e9e834a156b13e8d9944cb16da..ae6d3843c62722cd6bfa58e93508f45b4ff46a96 100644 (file)
@@ -43,7 +43,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)hash.h      10.6 (Sleepycat) 8/18/97
+ *     @(#)hash.h      10.7 (Sleepycat) 11/1/97
  */
 
 /* Cursor structure definitions. */
@@ -179,8 +179,8 @@ typedef struct htab {               /* Memory resident data structure. */
 /* Constraints about number of pages and how much data goes on a page. */
 
 #define        MAX_PAGES(H)    UINT32_T_MAX
-#define        MINFILL         0.25
-#define        ISBIG(H, N)     (((N) > ((H)->hdr->pagesize * MINFILL)) ? 1 : 0)
+#define        MINFILL         4
+#define        ISBIG(H, N)     (((N) > ((H)->hdr->pagesize / MINFILL)) ? 1 : 0)
 
 /* Shorthands for accessing structure */
 #define        NDX_INVALID     0xFFFF
index 5ff1229115e59e0ec2772e83b68de12bd87578b1..2b8aea8d86966b1ad25c944fa75fd6f01df4f88e 100644 (file)
@@ -108,7 +108,25 @@ typedef struct _ham_ovfl_args {
        db_pgno_t       start_pgno;
        u_int32_t       npages;
        db_pgno_t       free_pgno;
+       u_int32_t       ovflpoint;
        DB_LSN  metalsn;
 } __ham_ovfl_args;
 
+
+#define        DB_ham_copypage (DB_ham_BEGIN + 8)
+
+typedef struct _ham_copypage_args {
+       u_int32_t type;
+       DB_TXN *txnid;
+       DB_LSN prev_lsn;
+       u_int32_t       fileid;
+       db_pgno_t       pgno;
+       DB_LSN  pagelsn;
+       db_pgno_t       next_pgno;
+       DB_LSN  nextlsn;
+       db_pgno_t       nnext_pgno;
+       DB_LSN  nnextlsn;
+       DBT     page;
+} __ham_copypage_args;
+
 #endif
index 32788c7b8a2baabf48ac6e0b8fe07b6e86db6dc1..5abbb274f0da9ac16390174c0ca58d09a7a81647 100644 (file)
@@ -1,4 +1,4 @@
-/* Do not edit: automatically built by dist/distrib. */
+/* DO NOT EDIT: automatically built by dist/distrib. */
 int __ham_open __P((DB *, DB_INFO *));
 int  __ham_close __P((DB *));
 int __ham_c_iclose __P((DB *, DBC *));
@@ -54,10 +54,17 @@ int __ham_newpgno_read __P((void *, __ham_newpgno_args **));
 int __ham_ovfl_log
     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
     u_int32_t, db_pgno_t, u_int32_t, db_pgno_t,
-    DB_LSN *));
+    u_int32_t, DB_LSN *));
 int __ham_ovfl_print
    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __ham_ovfl_read __P((void *, __ham_ovfl_args **));
+int __ham_copypage_log
+    __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
+    u_int32_t, db_pgno_t, DB_LSN *, db_pgno_t,
+    DB_LSN *, db_pgno_t, DB_LSN *, DBT *));
+int __ham_copypage_print
+   __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
+int __ham_copypage_read __P((void *, __ham_copypage_args **));
 int __ham_init_print __P((DB_ENV *));
 int __ham_init_recover __P((DB_ENV *));
 int __ham_pgin __P((db_pgno_t, void *, DBT *));
@@ -81,7 +88,7 @@ int __ham_item_first __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
 int __ham_item_prev __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
 int __ham_item_next __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
 void __ham_putitem __P((PAGE *p, const DBT *, int));
-int __ham_del_pair __P((HTAB *, HASH_CURSOR *));
+int __ham_del_pair __P((HTAB *, HASH_CURSOR *, int));
 int __ham_replpair __P((HTAB *, HASH_CURSOR *, DBT *, u_int32_t));
 void __ham_onpage_replace __P((PAGE *, size_t, u_int32_t, int32_t,
     int32_t,  DBT *));
@@ -118,4 +125,6 @@ int __ham_splitdata_recover
    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __ham_ovfl_recover
     __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
+int __ham_copypage_recover
+  __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
 int __ham_stat __P((DB *, FILE *));
index 8f9e81c0faedb60279f3d9352fba2aca7cdca8a6..8a927f076ec4652927aaaece564917ab0026b728 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)lock.h      10.8 (Sleepycat) 9/23/97
+ *     @(#)lock.h      10.9 (Sleepycat) 10/25/97
  */
 
 typedef struct __db_lockobj    DB_LOCKOBJ;
@@ -54,8 +54,7 @@ struct __db_lockregion {
 
 /* Macros to lock/unlock the region. */
 #define        LOCK_LOCKREGION(lt)                                             \
-       (void)__db_mutex_lock(&(lt)->region->hdr.lock,(lt)->fd,         \
-           (lt)->dbenv == NULL ? NULL : (lt)->dbenv->db_yield)
+       (void)__db_mutex_lock(&(lt)->region->hdr.lock, (lt)->fd)
 #define        UNLOCK_LOCKREGION(lt)                                           \
        (void)__db_mutex_unlock(&(lt)->region->hdr.lock, (lt)->fd)
 
index 59d5072bc41ae37e3625c8050ce4db1ba3ad7a60..0d0ba148b6c41892ef07f5e32f9458b0fad30695 100644 (file)
@@ -1,4 +1,4 @@
-/* Do not edit: automatically built by dist/distrib. */
+/* DO NOT EDIT: automatically built by dist/distrib. */
 int __lock_getobj  __P((DB_LOCKTAB *,
     u_int32_t, DBT *, u_int32_t type, DB_LOCKOBJ **));
 int __lock_cmp __P((DBT *, DB_LOCKOBJ *));
index a9c82fa04df436d2d22e34b403126b1416fb462c..a192a38136e3bc6ea516b25273579da0005c9085 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)log.h       10.9 (Sleepycat) 9/23/97
+ *     @(#)log.h       10.15 (Sleepycat) 11/2/97
  */
 
 #ifndef _LOG_H_
@@ -15,6 +15,8 @@ struct __hdr;         typedef struct __hdr HDR;
 struct __log;          typedef struct __log LOG;
 struct __log_persist;  typedef struct __log_persist LOGP;
 
+#define        MEGABYTE        (1024 * 1024)
+
 #define        MAXLFNAME       99999           /* Maximum log file name. */
 #define        LFNAME          "log.%05d"      /* Log file name template. */
 
@@ -23,21 +25,15 @@ struct __log_persist;       typedef struct __log_persist LOGP;
 
 #define        DEFAULT_MAX     (10 * 1048576)  /* 10 Mb. */
 
-/* Macros to return per-process address, offsets. */
-#define        ADDR(base, offset)      ((void *)((u_int8_t *)((base)->addr) + offset))
-#define        OFFSET(base, p)         ((u_int8_t *)(p) - (u_int8_t *)(base)->addr)
-
 /* Macros to lock/unlock the region and threads. */
 #define        LOCK_LOGTHREAD(dblp)                                            \
        if (F_ISSET(dblp, DB_AM_THREAD))                                \
-               (void)__db_mutex_lock((dblp)->mutexp, -1,               \
-                   (dblp)->dbenv == NULL ? NULL : (dblp)->dbenv->db_yield)
+               (void)__db_mutex_lock((dblp)->mutexp, -1)
 #define        UNLOCK_LOGTHREAD(dblp)                                          \
        if (F_ISSET(dblp, DB_AM_THREAD))                                \
                (void)__db_mutex_unlock((dblp)->mutexp, -1);
 #define        LOCK_LOGREGION(dblp)                                            \
-       (void)__db_mutex_lock(&((RLAYOUT *)(dblp)->lp)->lock,           \
-           (dblp)->fd, (dblp)->dbenv == NULL ? NULL : (dblp)->dbenv->db_yield)
+       (void)__db_mutex_lock(&((RLAYOUT *)(dblp)->lp)->lock, (dblp)->fd)
 #define        UNLOCK_LOGREGION(dblp)                                          \
        (void)__db_mutex_unlock(&((RLAYOUT *)(dblp)->lp)->lock, (dblp)->fd)
 
@@ -124,7 +120,7 @@ struct __log {
        DB_LSN    lsn;                  /* LSN at current file offset. */
        DB_LSN    c_lsn;                /* LSN of the last checkpoint. */
        DB_LSN    s_lsn;                /* LSN of the last sync. */
-       DB_LSN    span_lsn;             /* LSN spanning buffer write. */
+       DB_LSN    uw_lsn;               /* LSN of 1st rec not fully on disk. */
 
        u_int32_t len;                  /* Length of the last record. */
 
@@ -132,7 +128,8 @@ struct __log {
        u_int32_t w_off;                /* Current write offset in the file. */
 
        time_t    chkpt;                /* Time of the last checkpoint. */
-       u_int32_t written;              /* Bytes written since checkpoint. */
+
+       DB_LOG_STAT stat;               /* Log statistics. */
 
        u_int8_t buf[4 * 1024];         /* Log buffer. */
 };
index bc63d9dac8a3f10f1612ed709461cd8d4e526f93..c32d1d6af6e4fa8a213063c16d8843e794a7c270 100644 (file)
@@ -1,4 +1,4 @@
-/* Do not edit: automatically built by dist/distrib. */
+/* DO NOT EDIT: automatically built by dist/distrib. */
 int __log_find __P((DB_LOG *, int *));
 int __log_valid __P((DB_LOG *, LOG *, int));
 int __log_register_log
index 3b71774484990ac7cc7f08d8fbf28c17f753f5e3..f68f42b1441f1a0e9340320fca19ca7c38bd1e9c 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)mp.h        10.16 (Sleepycat) 9/23/97
+ *     @(#)mp.h        10.19 (Sleepycat) 10/25/97
  */
 
 struct __bh;           typedef struct __bh BH;
@@ -22,30 +22,36 @@ struct __mpoolfile; typedef struct __mpoolfile MPOOLFILE;
 #define        DB_CACHESIZE_DEF        (128 * 1024)
 #define        DB_CACHESIZE_MIN        ( 20 * 1024)
 
-/* Macro to return per-process address, offsets. */
-#define        ADDR(base, offset)      ((void *)((u_int8_t *)((base)->addr) + offset))
-#define        OFFSET(base, p)         ((u_int8_t *)(p) - (u_int8_t *)(base)->addr)
-
 #define        INVALID         0               /* Invalid shared memory offset. */
 #define        TEMPORARY       "<tmp>"         /* Temporary file name. */
 
 /*
- * There are two kinds of locks in the mpool code.  The first is the region
- * lock, used to serialize modifications to all data structures.  The second
- * is a per-buffer header lock.  The locking order is as follows:
+ * There are three ways we do locking in the mpool code:
+ *
+ * Locking a handle mutex to provide concurrency for DB_THREAD operations.
+ * Locking the region mutex to provide mutual exclusion while reading and
+ *    writing structures in the shared region.
+ * Locking buffer header mutexes during I/O.
+ *
+ * The first will not be further described here.  We use the shared mpool
+ * region lock to provide mutual exclusion while reading/modifying all of
+ * the data structures, including the buffer headers.  We use a per-buffer
+ * header lock to wait on buffer I/O.  The order of locking is as follows:
  *
- * Process searching for a buffer:
+ * Searching for a buffer:
  *     Acquire the region lock.
  *     Find the buffer header.
  *     Increment the reference count (guarantee the buffer stays).
- *     If the BH_LOCKED flag is set:
+ *     If the BH_LOCKED flag is set (I/O is going on):
  *             Release the region lock.
+ *             Request the buffer lock.
+ *             The I/O will complete...
  *             Acquire the buffer lock.
  *             Release the buffer lock.
  *             Acquire the region lock.
  *     Return the buffer.
  *
- * Process reading/writing a buffer:
+ * Reading/writing a buffer:
  *     Acquire the region lock.
  *     Find/create the buffer header.
  *     If reading, increment the reference count (guarantee the buffer stays).
@@ -69,8 +75,7 @@ struct __mpoolfile;   typedef struct __mpoolfile MPOOLFILE;
 
 #define        LOCKHANDLE(dbmp, mutexp)                                        \
        if (F_ISSET(dbmp, MP_LOCKHANDLE))                               \
-               (void)__db_mutex_lock(mutexp, (dbmp)->fd,               \
-               (dbmp)->dbenv == NULL ? NULL : (dbmp)->dbenv->db_yield)
+               (void)__db_mutex_lock(mutexp, (dbmp)->fd)
 #define        UNLOCKHANDLE(dbmp, mutexp)                                      \
        if (F_ISSET(dbmp, MP_LOCKHANDLE))                               \
                (void)__db_mutex_unlock(mutexp, (dbmp)->fd)
@@ -78,8 +83,7 @@ struct __mpoolfile;   typedef struct __mpoolfile MPOOLFILE;
 #define        LOCKREGION(dbmp)                                                \
        if (F_ISSET(dbmp, MP_LOCKREGION))                               \
                (void)__db_mutex_lock(&((RLAYOUT *)(dbmp)->mp)->lock,   \
-                   (dbmp)->fd,                                         \
-                   (dbmp)->dbenv == NULL ? NULL : (dbmp)->dbenv->db_yield)
+                   (dbmp)->fd)
 #define        UNLOCKREGION(dbmp)                                              \
        if (F_ISSET(dbmp, MP_LOCKREGION))                               \
                (void)__db_mutex_unlock(&((RLAYOUT *)(dbmp)->mp)->lock, \
@@ -87,8 +91,7 @@ struct __mpoolfile;   typedef struct __mpoolfile MPOOLFILE;
 
 #define        LOCKBUFFER(dbmp, bhp)                                           \
        if (F_ISSET(dbmp, MP_LOCKREGION))                               \
-               (void)__db_mutex_lock(&(bhp)->mutex, (dbmp)->fd,        \
-                   (dbmp)->dbenv == NULL ? NULL : (dbmp)->dbenv->db_yield)
+               (void)__db_mutex_lock(&(bhp)->mutex, (dbmp)->fd)
 #define        UNLOCKBUFFER(dbmp, bhp)                                         \
        if (F_ISSET(dbmp, MP_LOCKREGION))                               \
                (void)__db_mutex_unlock(&(bhp)->mutex, (dbmp)->fd)
@@ -250,8 +253,8 @@ struct __bh {
 #define        BH_WRITE        0x020           /* Page scheduled for writing. */
        u_int16_t  flags;
 
-       SH_TAILQ_ENTRY  q;              /* LRU list of bucket headers. */
-       SH_TAILQ_ENTRY  mq;             /* MPOOLFILE list of bucket headers. */
+       SH_TAILQ_ENTRY  q;              /* LRU queue. */
+       SH_TAILQ_ENTRY  hq;             /* MPOOL hash bucket queue. */
 
        db_pgno_t pgno;                 /* Underlying MPOOLFILE page number. */
        size_t    mf_offset;            /* Associated MPOOLFILE offset. */
index 3934c130a8551f2ed07a02fbbb4337116146a580..49d86ba2e5d5f6780b6ad7064f8296de68cfacc3 100644 (file)
@@ -1,4 +1,4 @@
-/* Do not edit: automatically built by dist/distrib. */
+/* DO NOT EDIT: automatically built by dist/distrib. */
 int __memp_bhwrite
     __P((DB_MPOOL *, MPOOLFILE *, BH *, int *, int *));
 int __memp_pgread __P((DB_MPOOLFILE *, BH *, int));
index ff46b6a4043432395fe498626075304bcb9dd068..cb2d4886afb5b7dc86e5a914ef0118be46ae94d9 100644 (file)
@@ -1,4 +1,4 @@
-/* Do not edit: automatically built by dist/distrib. */
+/* DO NOT EDIT: automatically built by dist/distrib. */
 void __db_mutex_init __P((db_mutex_t *, off_t));
-int __db_mutex_lock __P((db_mutex_t *, int, int (*)(void)));
+int __db_mutex_lock __P((db_mutex_t *, int));
 int __db_mutex_unlock __P((db_mutex_t *, int));
index 59d72acf122ec4150a4b8df357cf81b22af929ba..e48a1e9407bc59546e197e2221a3437f13479420 100644 (file)
@@ -1,19 +1,19 @@
-/* Do not edit: automatically built by dist/distrib. */
+/* DO NOT EDIT: automatically built by dist/distrib. */
 int __db_abspath __P((const char *));
-char *__db_rpath __P((const char *));
-int __db_dir __P((DB_ENV *, const char *, char ***, int *));
-void __db_dirf __P((DB_ENV *, char **, int));
+int __os_dirlist __P((const char *, char ***, int *));
+void __os_dirfree __P((char **, int));
 int __db_fileid __P((DB_ENV *, const char *, int, u_int8_t *));
-int __db_lseek __P((int, size_t, db_pgno_t, u_long, int));
-int __db_mmap __P((int, size_t, int, int, void *));
-int __db_munmap __P((void *, size_t));
-int __db_oflags __P((int));
-int __db_fdopen __P((const char *, int, int, int, int *));
 int __db_fsync __P((int));
+int __os_map __P((int, size_t, int, int, void **));
+int __os_unmap __P((void *, size_t));
+int __db_oflags __P((int));
+int __db_open __P((const char *, int, int, int, int *));
 int __db_close __P((int));
+char *__db_rpath __P((const char *));
 int __db_read __P((int, void *, size_t, ssize_t *));
 int __db_write __P((int, void *, size_t, ssize_t *));
-int __db_sleep __P((u_long, u_long));
-int __db_exists __P((const char *, int *));
-int __db_stat __P((DB_ENV *, const char *, int, off_t *, off_t *));
+int __os_seek __P((int, size_t, db_pgno_t, u_long, int));
+int __os_sleep __P((u_long, u_long));
+int __os_exists __P((const char *, int *));
+int __os_ioinfo __P((const char *, int, off_t *, off_t *));
 int __db_unlink __P((const char *));
diff --git a/db2/include/os_func.h b/db2/include/os_func.h
new file mode 100644 (file)
index 0000000..0a72942
--- /dev/null
@@ -0,0 +1,76 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997
+ *     Sleepycat Software.  All rights reserved.
+ *
+ *     @(#)os_func.h   10.2 (Sleepycat) 10/28/97
+ */
+
+/* Calls which can be replaced by the application. */
+struct __db_jumptab {
+       void   *(*db_calloc) __P((size_t, size_t));     /* DB_FUNC_CALLOC */
+       int     (*db_close) __P((int));                 /* DB_FUNC_CLOSE */
+       void    (*db_dirfree) __P((char **, int));      /* DB_FUNC_DIRFREE */
+       int     (*db_dirlist)                           /* DB_FUNC_DIRLIST */
+                   __P((const char *, char ***, int *));
+       int     (*db_exists)                            /* DB_FUNC_EXISTS */
+                   __P((const char *, int *));
+       void    (*db_free) __P((void *));               /* DB_FUNC_FREE */
+       int     (*db_fsync) __P((int));                 /* DB_FUNC_FSYNC */
+       int     (*db_ioinfo)                            /* DB_FUNC_IOINFO */
+                   __P((const char *, int, off_t *, off_t *));
+       void   *(*db_malloc) __P((size_t));             /* DB_FUNC_MALLOC */
+       int     (*db_map)                               /* DB_FUNC_MAP */
+                   __P((int, size_t, int, int, void **));
+       int     (*db_open)                              /* DB_FUNC_OPEN */
+                   __P((const char *, int, ...));
+       ssize_t (*db_read) __P((int, void *, size_t));  /* DB_FUNC_READ */
+       void   *(*db_realloc) __P((void *, size_t));    /* DB_FUNC_REALLOC */
+       int     (*db_seek)                              /* DB_FUNC_SEEK */
+                   __P((int, size_t, db_pgno_t, u_long, int));
+       int     (*db_sleep) __P((u_long, u_long));      /* DB_FUNC_SLEEP */
+       char   *(*db_strdup) __P((const char *));       /* DB_FUNC_STRDUP */
+       int     (*db_unlink) __P((const char *));       /* DB_FUNC_UNLINK */
+       int     (*db_unmap) __P((void *, size_t));      /* DB_FUNC_UNMAP */
+       ssize_t (*db_write)                             /* DB_FUNC_WRITE */
+                   __P((int, const void *, size_t));
+       int     (*db_yield) __P((void));                /* DB_FUNC_YIELD */
+};
+
+extern struct __db_jumptab __db_jump;
+
+/*
+ * Names used by DB to call through the jump table.
+ *
+ * The naming scheme goes like this: if the functionality the application can
+ * replace is the same as the DB functionality, e.g., calloc, or dirlist, then
+ * we use the name __db_XXX, and the application is expected to replace the
+ * complete functionality, which may or may not map directly to an ANSI C or
+ * POSIX 1003.1 interface.  If the functionality that the aplication replaces
+ * only underlies what the DB os directory exports to other parts of DB, e.g.,
+ * read, then the name __os_XXX is used, and the application can only replace
+ * the underlying functionality.  Under most circumstances, the os directory
+ * part of DB is the only code that should use the __os_XXX names, all other
+ * parts of DB should be calling __db_XXX functions.
+ */
+#define        __db_calloc     __db_jump.db_calloc
+#define        __os_close      __db_jump.db_close      /* __db_close is a wrapper. */
+#define        __db_dirfree    __db_jump.db_dirfree
+#define        __db_dirlist    __db_jump.db_dirlist
+#define        __db_exists     __db_jump.db_exists
+#define        __db_free       __db_jump.db_free
+#define        __os_fsync      __db_jump.db_fsync      /* __db_fsync is a wrapper. */
+#define        __db_ioinfo     __db_jump.db_ioinfo
+#define        __db_malloc     __db_jump.db_malloc
+#define        __db_map        __db_jump.db_map
+#define        __os_open       __db_jump.db_open       /* __db_open is a wrapper. */
+#define        __os_read       __db_jump.db_read       /* __db_read is a wrapper. */
+#define        __db_realloc    __db_jump.db_realloc
+#define        __db_seek       __db_jump.db_seek
+#define        __db_sleep      __db_jump.db_sleep
+#define        __db_strdup     __db_jump.db_strdup
+#define        __os_unlink     __db_jump.db_unlink     /* __db_unlink is a wrapper. */
+#define        __db_unmap      __db_jump.db_unmap
+#define        __os_write      __db_jump.db_write      /* __db_write is a wrapper. */
+#define        __db_yield      __db_jump.db_yield
index 8bb3976c1ce0527d9e924a52debadd4967f45254..c64ac3fc52a4f073a9bbac3ec41fec167a1c8766 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *     Sleepycat Software.  All rights reserved.
  *
- *     @(#)txn.h       10.10 (Sleepycat) 9/23/97
+ *     @(#)txn.h       10.11 (Sleepycat) 10/25/97
  */
 #ifndef        _TXN_H_
 #define        _TXN_H_
@@ -96,15 +96,13 @@ struct __db_txnregion {
 /* Macros to lock/unlock the region and threads. */
 #define        LOCK_TXNTHREAD(tmgrp)                                           \
        if (F_ISSET(tmgrp, DB_THREAD))                                  \
-               (void)__db_mutex_lock((tmgrp)->mutexp, -1,              \
-                   (tmgrp)->dbenv == NULL ? NULL : (tmgrp)->dbenv->db_yield)
+               (void)__db_mutex_lock((tmgrp)->mutexp, -1)
 #define        UNLOCK_TXNTHREAD(tmgrp)                                         \
        if (F_ISSET(tmgrp, DB_THREAD))                                  \
                (void)__db_mutex_unlock((tmgrp)->mutexp, -1)
 
 #define        LOCK_TXNREGION(tmgrp)                                           \
-       (void)__db_mutex_lock(&(tmgrp)->region->hdr.lock,(tmgrp)->fd,   \
-           (tmgrp)->dbenv == NULL ? NULL : (tmgrp)->dbenv->db_yield)
+       (void)__db_mutex_lock(&(tmgrp)->region->hdr.lock, (tmgrp)->fd)
 #define        UNLOCK_TXNREGION(tmgrp)                                         \
        (void)__db_mutex_unlock(&(tmgrp)->region->hdr.lock, (tmgrp)->fd)
 
index 8ba0b0c44eae44ae3822fa4da260fdfae0fa5c28..9b617bb68c064f9e37498dfd11bb9931352b2a43 100644 (file)
@@ -1,4 +1,4 @@
-/* Do not edit: automatically built by dist/distrib. */
+/* DO NOT EDIT: automatically built by dist/distrib. */
 int __txn_regop_log
     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
     u_int32_t));
index a2a3b208f2d051e12929ac2ac3e121b29e984884..f1223a9fa6f2f9f853342569a97d12dd0faaad20 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)lock.c       10.36 (Sleepycat) 9/24/97";
+static const char sccsid[] = "@(#)lock.c       10.38 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -200,7 +200,7 @@ lock_open(path, flags, mode, dbenv, ltp)
        /*
         * Create the lock table structure.
         */
-       if ((lt = (DB_LOCKTAB *)calloc(1, sizeof(DB_LOCKTAB))) == NULL) {
+       if ((lt = (DB_LOCKTAB *)__db_calloc(1, sizeof(DB_LOCKTAB))) == NULL) {
                __db_err(dbenv, "%s", strerror(ENOMEM));
                return (ENOMEM);
        }
@@ -269,7 +269,7 @@ out:        if (lt->region != NULL)
                (void)__db_rclose(lt->dbenv, lt->fd, lt->region);
        if (LF_ISSET(DB_CREATE))
                (void)lock_unlink(path, 1, lt->dbenv);
-       free(lt);
+       __db_free(lt);
        return (ret);
 }
 
@@ -505,7 +505,7 @@ lock_close(lt)
                return (ret);
 
        /* Free lock table. */
-       free(lt);
+       __db_free(lt);
        return (0);
 }
 
@@ -728,8 +728,7 @@ __lock_get_internal(lt, locker, flags, obj, lock_mode, lockp)
         */
        (void)__db_mutex_init(&newl->mutex,
            MUTEX_LOCK_OFFSET(lt->region, &newl->mutex));
-       (void)__db_mutex_lock(&newl->mutex, lt->fd,
-           lt->dbenv == NULL ? NULL : lt->dbenv->db_yield);
+       (void)__db_mutex_lock(&newl->mutex, lt->fd);
 
        /*
         * Now, insert the lock onto its locker's list.
@@ -760,8 +759,7 @@ __lock_get_internal(lt, locker, flags, obj, lock_mode, lockp)
                if (lrp->detect != DB_LOCK_NORUN)
                        ret = lock_detect(lt, 0, lrp->detect);
 
-               (void)__db_mutex_lock(&newl->mutex,
-                   lt->fd, lt->dbenv == NULL ? NULL : lt->dbenv->db_yield);
+               (void)__db_mutex_lock(&newl->mutex, lt->fd);
 
                LOCK_LOCKREGION(lt);
                if (newl->status != DB_LSTAT_PENDING) {
@@ -975,11 +973,9 @@ __lock_dump_region(lt, flags)
 #ifndef HAVE_SPINLOCKS
        printf("Mutex: off %lu", (u_long)lrp->hdr.lock.off);
 #endif
-#ifdef MUTEX_STATISTICS
        printf(" waits %lu nowaits %lu",
            (u_long)lrp->hdr.lock.mutex_set_wait,
            (u_long)lrp->hdr.lock.mutex_set_nowait);
-#endif
        printf("\n%s:%lu\t%s:%lu\t%s:%lu\t%s:%lu\n",
            "nconflicts ", (u_long)lrp->nconflicts,
            "nrequests  ", (u_long)lrp->nrequests,
index f947f901c3e239ad864915b408fbbccef6171b5c..566021fe89698972843cae408dc2c5c0e0ce5ffe 100644 (file)
@@ -11,7 +11,7 @@
 static const char copyright[] =
 "@(#) Copyright (c) 1997\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)lock_deadlock.c      10.21 (Sleepycat) 9/6/97";
+static const char sccsid[] = "@(#)lock_deadlock.c      10.25 (Sleepycat) 11/1/97";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -50,16 +50,19 @@ typedef struct {
        int             valid;
        u_int32_t       id;
        DB_LOCK         last_lock;
+       db_pgno_t       pgno;
 } locker_info;
 
 static int  __dd_abort __P((DB_ENV *, locker_info *));
-static int  __dd_build __P((DB_ENV *, u_int32_t **, int *, locker_info **));
-#ifdef DEBUG
-static void __dd_debug __P((DB_ENV *, locker_info *, u_int32_t *, int));
-#endif
+static int  __dd_build
+       __P((DB_ENV *, u_int32_t **, u_int32_t *, locker_info **));
 static u_int32_t
           *__dd_find __P((u_int32_t *, locker_info *, u_int32_t));
 
+#ifdef DEBUG
+static void __dd_debug __P((DB_ENV *, locker_info *, u_int32_t *, u_int32_t));
+#endif
+
 int
 lock_detect(lt, flags, atype)
        DB_LOCKTAB *lt;
@@ -68,8 +71,8 @@ lock_detect(lt, flags, atype)
 {
        DB_ENV *dbenv;
        locker_info *idmap;
-       u_int32_t *bitmap, *deadlock, killid;
-       int do_pass, i, nlockers, nentries, ret;
+       u_int32_t *bitmap, *deadlock, i, killid, nentries, nlockers;
+       int do_pass, ret;
 
        /* Validate arguments. */
        if ((ret =
@@ -77,17 +80,16 @@ lock_detect(lt, flags, atype)
                return (ret);
 
        /* Check if a detector run is necessary. */
-       do_pass = 1;
        dbenv = lt->dbenv;
        if (LF_ISSET(DB_LOCK_CONFLICT)) {
                /* Make a pass every time a lock waits. */
                LOCK_LOCKREGION(lt);
                do_pass = dbenv->lk_info->region->need_dd != 0;
                UNLOCK_LOCKREGION(lt);
-       }
 
-       if (!do_pass)
-               return (0);
+               if (!do_pass)
+                       return (0);
+       }
 
        /* Build the waits-for bitmap. */
        if ((ret = __dd_build(dbenv, &bitmap, &nlockers, &idmap)) != 0)
@@ -118,8 +120,7 @@ lock_detect(lt, flags, atype)
 
                        if (killid == BAD_KILLID) {
                                __db_err(dbenv,
-                                   "warning: could not find %s",
-                                   "locker to abort");
+                                   "warning: could not find locker to abort");
                                break;
                        }
 
@@ -137,11 +138,8 @@ lock_detect(lt, flags, atype)
                        /*
                         * We are trying to calculate the id of the
                         * locker whose entry is indicated by deadlock.
-                        * We know that this is less than nlockers, so
-                        * the cast below is valid.
                         */
-                       killid =
-                           (u_int32_t)((deadlock - bitmap) / nentries);
+                       killid = (deadlock - bitmap) / nentries;
                        break;
                case DB_LOCK_YOUNGEST:
                        /*
@@ -155,8 +153,7 @@ lock_detect(lt, flags, atype)
 
                        if (killid == BAD_KILLID) {
                                __db_err(dbenv,
-                                   "warning: could not find %s",
-                                   "locker to abort");
+                                   "warning: could not find locker to abort");
                                break;
                        }
                        /*
@@ -184,8 +181,8 @@ lock_detect(lt, flags, atype)
                            "warning: unable to abort locker %lx",
                            (u_long)idmap[killid].id);
        }
-       free(bitmap);
-       free(idmap);
+       __db_free(bitmap);
+       __db_free(idmap);
 
        return (ret);
 }
@@ -197,15 +194,15 @@ lock_detect(lt, flags, atype)
 static int
 __dd_build(dbenv, bmp, nlockers, idmap)
        DB_ENV *dbenv;
-       u_int32_t **bmp;
-       int *nlockers;
+       u_int32_t **bmp, *nlockers;
        locker_info **idmap;
 {
-       DB_LOCKTAB *lt;
-       DB_LOCKOBJ *op, *lockerp;
        struct __db_lock *lp;
-       u_int32_t *bitmap, count, *entryp, i, id, nentries, *tmpmap;
+       DB_LOCKTAB *lt;
+       DB_LOCKOBJ *op, *lo, *lockerp;
+       u_int8_t *pptr;
        locker_info *id_array;
+       u_int32_t *bitmap, count, *entryp, i, id, nentries, *tmpmap;
        int is_first, ret;
 
        lt = dbenv->lk_info;
@@ -238,24 +235,24 @@ retry:    count = lt->region->nlockers;
         * We can probably save the malloc's between iterations just
         * reallocing if necessary because count grew by too much.
         */
-       if ((bitmap = (u_int32_t *)calloc((size_t)count,
+       if ((bitmap = (u_int32_t *)__db_calloc((size_t)count,
            sizeof(u_int32_t) * nentries)) == NULL) {
                __db_err(dbenv, "%s", strerror(ENOMEM));
                return (ENOMEM);
        }
 
        if ((tmpmap =
-           (u_int32_t *)calloc(sizeof(u_int32_t), nentries)) == NULL) {
+           (u_int32_t *)__db_calloc(sizeof(u_int32_t), nentries)) == NULL) {
                __db_err(dbenv, "%s", strerror(ENOMEM));
-               free(bitmap);
+               __db_free(bitmap);
                return (ENOMEM);
        }
 
-       if ((id_array = (locker_info *)calloc((size_t)count,
+       if ((id_array = (locker_info *)__db_calloc((size_t)count,
            sizeof(locker_info))) == NULL) {
                __db_err(dbenv, "%s", strerror(ENOMEM));
-               free(bitmap);
-               free(tmpmap);
+               __db_free(bitmap);
+               __db_free(tmpmap);
                return (ENOMEM);
        }
 
@@ -264,9 +261,9 @@ retry:      count = lt->region->nlockers;
         */
        LOCK_LOCKREGION(lt);
        if (lt->region->nlockers > count) {
-               free(bitmap);
-               free(tmpmap);
-               free(id_array);
+               __db_free(bitmap);
+               __db_free(tmpmap);
+               __db_free(id_array);
                goto retry;
        }
 
@@ -326,9 +323,8 @@ retry:      count = lt->region->nlockers;
                            lp != NULL;
                            is_first = 0,
                            lp = SH_TAILQ_NEXT(lp, links, __db_lock)) {
-                               if ((ret = __lock_getobj(lt,
-                                   lp->holder, NULL, DB_LOCK_LOCKER, &lockerp))
-                                   != 0) {
+                               if ((ret = __lock_getobj(lt, lp->holder,
+                                   NULL, DB_LOCK_LOCKER, &lockerp)) != 0) {
                                        __db_err(dbenv,
                                            "warning unable to find object");
                                        continue;
@@ -369,8 +365,16 @@ retry:     count = lt->region->nlockers;
                        continue;
                }
                lp = SH_LIST_FIRST(&lockerp->heldby, __db_lock);
-               if (lp != NULL)
+               if (lp != NULL) {
                        id_array[id].last_lock = LOCK_TO_OFFSET(lt, lp);
+                       lo = (DB_LOCKOBJ *)((u_int8_t *)lp + lp->obj);
+                       pptr = SH_DBT_PTR(&lo->lockobj);
+                       if (lo->lockobj.size >= sizeof(db_pgno_t))
+                               memcpy(&id_array[id].pgno, pptr,
+                                   sizeof(db_pgno_t));
+                       else
+                               id_array[id].pgno = 0;
+               }
        }
 
        /* Pass complete, reset the deadlock detector bit. */
@@ -384,21 +388,20 @@ retry:    count = lt->region->nlockers;
        *nlockers = id;
        *idmap = id_array;
        *bmp = bitmap;
-       free(tmpmap);
+       __db_free(tmpmap);
        return (0);
 }
 
 static u_int32_t *
 __dd_find(bmp, idmap, nlockers)
-       u_int32_t *bmp;
+       u_int32_t *bmp, nlockers;
        locker_info *idmap;
-       u_int32_t nlockers;
 {
        u_int32_t i, j, nentries, *mymap, *tmpmap;
 
        /*
-        * For each locker, or in the bits from the lockers
-        * on which that locker is waiting.
+        * For each locker, OR in the bits from the lockers on which that
+        * locker is waiting.
         */
        nentries = ALIGN(nlockers, 32) / 32;
        for (mymap = bmp, i = 0; i < nlockers; i++, mymap += nentries) {
@@ -422,9 +425,9 @@ __dd_abort(dbenv, info)
        DB_ENV *dbenv;
        locker_info *info;
 {
+       struct __db_lock *lockp;
        DB_LOCKTAB *lt;
        DB_LOCKOBJ *lockerp, *sh_obj;
-       struct __db_lock *lockp;
        int ret;
 
        lt = dbenv->lk_info;
@@ -459,19 +462,17 @@ static void
 __dd_debug(dbenv, idmap, bitmap, nlockers)
        DB_ENV *dbenv;
        locker_info *idmap;
-       u_int32_t *bitmap;
-       int nlockers;
+       u_int32_t *bitmap, nlockers;
 {
-       u_int32_t *mymap;
-       int i, j, nentries;
+       u_int32_t i, j, *mymap, nentries;
        char *msgbuf;
 
        __db_err(dbenv, "Waitsfor array");
        __db_err(dbenv, "waiter\twaiting on");
        /*
-        * Alloc space to print 10 bytes per item waited on.
+        * Allocate space to print 10 bytes per item waited on.
         */
-       if ((msgbuf = (char *)malloc((nlockers + 1) * 10 + 64)) == NULL) {
+       if ((msgbuf = (char *)__db_malloc((nlockers + 1) * 10 + 64)) == NULL) {
                __db_err(dbenv, "%s", strerror(ENOMEM));
                return;
        }
@@ -480,7 +481,8 @@ __dd_debug(dbenv, idmap, bitmap, nlockers)
        for (mymap = bitmap, i = 0; i < nlockers; i++, mymap += nentries) {
                if (!idmap[i].valid)
                        continue;
-               sprintf(msgbuf, "%lx\t\t", (u_long)idmap[i].id);/* Waiter. */
+               sprintf(msgbuf,                                 /* Waiter. */
+                   "%lx/%lu:\t", (u_long)idmap[i].id, (u_long)idmap[i].pgno);
                for (j = 0; j < nlockers; j++)
                        if (ISSET_MAP(mymap, j))
                                sprintf(msgbuf, "%s %lx", msgbuf,
@@ -490,6 +492,6 @@ __dd_debug(dbenv, idmap, bitmap, nlockers)
                __db_err(dbenv, msgbuf);
        }
 
-       free(msgbuf);
+       __db_free(msgbuf);
 }
 #endif
index 893c1ee40272e4bd9d2cdfda5f13576249f3247b..17681f8e0ffe3df06da909a428e086556cd9b241 100644 (file)
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log.c        10.27 (Sleepycat) 9/23/97";
+static const char sccsid[] = "@(#)log.c        10.33 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -67,11 +67,11 @@ log_open(path, flags, mode, dbenv, lpp)
        }
 
        /* Create and initialize the DB_LOG structure. */
-       if ((dblp = (DB_LOG *)calloc(1, sizeof(DB_LOG))) == NULL)
+       if ((dblp = (DB_LOG *)__db_calloc(1, sizeof(DB_LOG))) == NULL)
                return (ENOMEM);
 
-       if (path != NULL && (dblp->dir = strdup(path)) == NULL) {
-               free(dblp);
+       if (path != NULL && (dblp->dir = __db_strdup(path)) == NULL) {
+               __db_free(dblp);
                return (ENOMEM);
        }
 
@@ -329,10 +329,12 @@ __log_find(dblp, valp)
        }
 
        /* Get the list of file names. */
-       ret = __db_dir(dblp->dbenv, dir, &names, &fcnt);
+       ret = __db_dirlist(dir, &names, &fcnt);
        FREES(p);
-       if (ret != 0)
+       if (ret != 0) {
+               __db_err(dblp->dbenv, "%s: %s", dir, strerror(ret));
                return (ret);
+       }
 
        /*
         * Search for a valid log file name, return a value of 0 on
@@ -350,7 +352,7 @@ __log_find(dblp, valp)
                }
 
        /* Discard the list. */
-       __db_dirf(dblp->dbenv, names, fcnt);
+       __db_dirfree(names, fcnt);
 
        return (ret);
 }
@@ -376,10 +378,10 @@ __log_valid(dblp, lp, cnt)
                return (ret);
 
        fd = -1;
-       if ((ret = __db_fdopen(p,
+       if ((ret = __db_open(p,
            DB_RDONLY | DB_SEQUENTIAL,
            DB_RDONLY | DB_SEQUENTIAL, 0, &fd)) != 0 ||
-           (ret = __db_lseek(fd, 0, 0, sizeof(HDR), SEEK_SET)) != 0 ||
+           (ret = __db_seek(fd, 0, 0, sizeof(HDR), SEEK_SET)) != 0 ||
            (ret = __db_read(fd, &persist, sizeof(LOGP), &nw)) != 0 ||
            nw != sizeof(LOGP)) {
                if (ret == 0)
@@ -474,3 +476,39 @@ log_unlink(path, force, dbenv)
        return (__db_runlink(dbenv,
            DB_APP_LOG, path, DB_DEFAULT_LOG_FILE, force));
 }
+
+/*
+ * log_stat --
+ *     Return LOG statistics.
+ */
+int
+log_stat(dblp, gspp, db_malloc)
+       DB_LOG *dblp;
+       DB_LOG_STAT **gspp;
+       void *(*db_malloc) __P((size_t));
+{
+       LOG *lp;
+
+       *gspp = NULL;
+       lp = dblp->lp;
+
+       if ((*gspp = db_malloc == NULL ?
+           (DB_LOG_STAT *)__db_malloc(sizeof(**gspp)) :
+           (DB_LOG_STAT *)db_malloc(sizeof(**gspp))) == NULL)
+               return (ENOMEM);
+
+       /* Copy out the global statistics. */
+       LOCK_LOGREGION(dblp);
+       **gspp = lp->stat;
+
+       (*gspp)->st_magic = lp->persist.magic;
+       (*gspp)->st_version = lp->persist.version;
+       (*gspp)->st_mode = lp->persist.mode;
+       (*gspp)->st_lg_max = lp->persist.lg_max;
+
+       (*gspp)->st_region_nowait = lp->rlayout.lock.mutex_set_nowait;
+       (*gspp)->st_region_wait = lp->rlayout.lock.mutex_set_wait;
+       UNLOCK_LOGREGION(dblp);
+
+       return (0);
+}
index 6904a2c72661bdee8fbceb62dcbe4d6cf77addff..140ea31fd17ec84446f4937c1309e53eafdb88f8 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_archive.c        10.26 (Sleepycat) 9/23/97";
+static const char sccsid[] = "@(#)log_archive.c        10.28 (Sleepycat) 10/28/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -68,7 +68,7 @@ log_archive(dblp, listp, flags, db_malloc)
         * but that's just not possible.
         */
        if (LF_ISSET(DB_ARCH_ABS)) {
-               __set_errno (0);
+               errno = 0;
                if ((pref = getcwd(buf, sizeof(buf))) == NULL)
                        return (errno == 0 ? ENOMEM : errno);
        } else
@@ -84,7 +84,7 @@ log_archive(dblp, listp, flags, db_malloc)
                if ((ret = log_get(dblp, &stable_lsn, &rec, DB_LAST)) != 0)
                        return (ret);
                if (F_ISSET(dblp, DB_AM_THREAD))
-                       free(rec.data);
+                       __db_free(rec.data);
                fnum = stable_lsn.file;
                break;
        case 0:
@@ -102,7 +102,7 @@ log_archive(dblp, listp, flags, db_malloc)
 #define        LIST_INCREMENT  64
        /* Get some initial space. */
        if ((array =
-           (char **)malloc(sizeof(char *) * (array_size = 10))) == NULL)
+           (char **)__db_malloc(sizeof(char *) * (array_size = 10))) == NULL)
                return (ENOMEM);
        array[0] = NULL;
 
@@ -115,7 +115,7 @@ log_archive(dblp, listp, flags, db_malloc)
 
                if (n >= array_size - 1) {
                        array_size += LIST_INCREMENT;
-                       if ((array = (char **)realloc(array,
+                       if ((array = (char **)__db_realloc(array,
                            sizeof(char *) * array_size)) == NULL) {
                                ret = ENOMEM;
                                goto err;
@@ -127,7 +127,7 @@ log_archive(dblp, listp, flags, db_malloc)
                                goto err;
                        FREES(name);
                } else if ((p = __db_rpath(name)) != NULL) {
-                       if ((array[n] = (char *)strdup(p + 1)) == NULL) {
+                       if ((array[n] = (char *)__db_strdup(p + 1)) == NULL) {
                                ret = ENOMEM;
                                goto err;
                        }
@@ -158,7 +158,7 @@ log_archive(dblp, listp, flags, db_malloc)
 err:   if (array != NULL) {
                for (arrayp = array; *arrayp != NULL; ++arrayp)
                        FREES(*arrayp);
-               free(array);
+               __db_free(array);
        }
        return (ret);
 }
@@ -182,7 +182,7 @@ __build_data(dblp, pref, listp, db_malloc)
 
        /* Get some initial space. */
        if ((array =
-           (char **)malloc(sizeof(char *) * (array_size = 10))) == NULL)
+           (char **)__db_malloc(sizeof(char *) * (array_size = 10))) == NULL)
                return (ENOMEM);
        array[0] = NULL;
 
@@ -200,7 +200,7 @@ __build_data(dblp, pref, listp, db_malloc)
                memcpy(&rectype, rec.data, sizeof(rectype));
                if (rectype != DB_log_register) {
                        if (F_ISSET(dblp, DB_AM_THREAD)) {
-                               free(rec.data);
+                               __db_free(rec.data);
                                rec.data = NULL;
                        }
                        continue;
@@ -214,25 +214,25 @@ __build_data(dblp, pref, listp, db_malloc)
 
                if (n >= array_size - 1) {
                        array_size += LIST_INCREMENT;
-                       if ((array = (char **)realloc(array,
+                       if ((array = (char **)__db_realloc(array,
                            sizeof(char *) * array_size)) == NULL) {
                                ret = ENOMEM;
                                goto lg_free;
                        }
                }
 
-               if ((array[n] = (char *)strdup(argp->name.data)) == NULL) {
+               if ((array[n] = (char *)__db_strdup(argp->name.data)) == NULL) {
                        ret = ENOMEM;
 lg_free:               if (F_ISSET(&rec, DB_DBT_MALLOC) && rec.data != NULL)
-                               free(rec.data);
+                               __db_free(rec.data);
                        goto err1;
                }
 
                array[++n] = NULL;
-               free(argp);
+               __db_free(argp);
 
                if (F_ISSET(dblp, DB_AM_THREAD)) {
-                       free(rec.data);
+                       __db_free(rec.data);
                        rec.data = NULL;
                }
        }
@@ -289,7 +289,7 @@ lg_free:            if (F_ISSET(&rec, DB_DBT_MALLOC) && rec.data != NULL)
                        if (ret != 0)
                                goto err2;
                } else if ((p = __db_rpath(real_name)) != NULL) {
-                       array[last] = (char *)strdup(p + 1);
+                       array[last] = (char *)__db_strdup(p + 1);
                        FREES(real_name);
                        if (array[last] == NULL)
                                goto err2;
@@ -321,7 +321,7 @@ err2:       /*
 err1:  if (array != NULL) {
                for (arrayp = array; *arrayp != NULL; ++arrayp)
                        FREES(*arrayp);
-               free(array);
+               __db_free(array);
        }
        return (ret);
 }
@@ -341,7 +341,7 @@ __absname(pref, name, newnamep)
        l_name = strlen(name);
 
        /* Malloc space for concatenating the two. */
-       if ((newname = (char *)malloc(l_pref + l_name + 2)) == NULL)
+       if ((newname = (char *)__db_malloc(l_pref + l_name + 2)) == NULL)
                return (ENOMEM);
 
        /* Build the name. */
@@ -379,7 +379,7 @@ __usermem(listp, func)
         * Don't simplify this expression, SunOS compilers don't like it.
         */
        if (func == NULL)
-               array = (char **)malloc(len);
+               array = (char **)__db_malloc(len);
        else
                array = (char **)func(len);
        if (array == NULL)
@@ -399,7 +399,7 @@ __usermem(listp, func)
        /* NULL-terminate the list. */
        *arrayp = NULL;
 
-       free(*listp);
+       __db_free(*listp);
        *listp = array;
 
        return (0);
index ea88a7bff993582bde3dfe5f05c8eca57da18b61..d5dbfe1f5f5b6010b970ea195ef7377af0d8bfe6 100644 (file)
@@ -53,7 +53,7 @@ int __log_register_log(logp, txnid, ret_lsnp, flags,
            + sizeof(u_int32_t) + (uid == NULL ? 0 : uid->size)
            + sizeof(id)
            + sizeof(ftype);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -94,7 +94,7 @@ int __log_register_log(logp, txnid, ret_lsnp, flags,
        ret = __log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -151,7 +151,7 @@ __log_register_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tid: %lu\n", (u_long)argp->id);
        printf("\tftype: 0x%lx\n", (u_long)argp->ftype);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -166,7 +166,7 @@ __log_register_read(recbuf, argpp)
        __log_register_args *argp;
        u_int8_t *bp;
 
-       argp = (__log_register_args *)malloc(sizeof(__log_register_args) +
+       argp = (__log_register_args *)__db_malloc(sizeof(__log_register_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -223,7 +223,7 @@ int __log_unregister_log(logp, txnid, ret_lsnp, flags,
                lsnp = &txnid->last_lsn;
        logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
            + sizeof(id);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -242,7 +242,7 @@ int __log_unregister_log(logp, txnid, ret_lsnp, flags,
        ret = __log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -280,7 +280,7 @@ __log_unregister_print(notused1, dbtp, lsnp, notused3, notused4)
            (u_long)argp->prev_lsn.offset);
        printf("\tid: %lu\n", (u_long)argp->id);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -295,7 +295,7 @@ __log_unregister_read(recbuf, argpp)
        __log_unregister_args *argp;
        u_int8_t *bp;
 
-       argp = (__log_unregister_args *)malloc(sizeof(__log_unregister_args) +
+       argp = (__log_unregister_args *)__db_malloc(sizeof(__log_unregister_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
index df75e20e03d56517feaed9a85799ae7d935590c3..115a00e8aa762e90e4cd0db801631141e7be4ce8 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_findckp.c        10.11 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)log_findckp.c        10.12 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -77,13 +77,13 @@ __log_findckp(lp, lsnp)
        next_lsn = last_ckp;
        do {
                if (F_ISSET(lp, DB_AM_THREAD))
-                       free(data.data);
+                       __db_free(data.data);
 
                if ((ret = log_get(lp, &next_lsn, &data, DB_SET)) != 0)
                        return (ret);
                if ((ret = __txn_ckp_read(data.data, &ckp_args)) != 0) {
                        if (F_ISSET(lp, DB_AM_THREAD))
-                               free(data.data);
+                               __db_free(data.data);
                        return (ret);
                }
                if (IS_ZERO_LSN(ckp_lsn))
@@ -100,12 +100,12 @@ __log_findckp(lp, lsnp)
                }
                last_ckp = next_lsn;
                next_lsn = ckp_args->last_ckp;
-               free(ckp_args);
+               __db_free(ckp_args);
        } while (!IS_ZERO_LSN(next_lsn) &&
            log_compare(&last_ckp, &ckp_lsn) > 0);
 
        if (F_ISSET(lp, DB_AM_THREAD))
-               free(data.data);
+               __db_free(data.data);
 
        /*
         * At this point, either, next_lsn is ZERO or ckp_lsn is the
@@ -118,7 +118,7 @@ __log_findckp(lp, lsnp)
                if ((ret = log_get(lp, &last_ckp, &data, DB_FIRST)) != 0)
                        return (ret);
                if (F_ISSET(lp, DB_AM_THREAD))
-                       free(data.data);
+                       __db_free(data.data);
        }
        *lsnp = last_ckp;
 
index 3f6df6c33cec8c41cd7c021b95bab038821264cf..ed35d57f820c8f15399ff18e5c809b0226a9c3a3 100644 (file)
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_get.c    10.19 (Sleepycat) 9/23/97";
+static const char sccsid[] = "@(#)log_get.c    10.21 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -170,7 +170,8 @@ __log_get(dblp, alsn, dbt, flags, silent)
                if (!IS_ZERO_LSN(nlsn)) {
                        /* If at start-of-file, move to the previous file. */
                        if (nlsn.offset == 0) {
-                               if (nlsn.file == 1)
+                               if (nlsn.file == 1 ||
+                                   __log_valid(dblp, NULL, nlsn.file - 1) != 0)
                                        return (DB_NOTFOUND);
 
                                --nlsn.file;
@@ -215,27 +216,21 @@ retry:
                goto cksum;
        }
 
-       /*
-        * Move the file descriptor to the page that has the hdr.  We dealt
-        * with moving to a previous log file in the flags switch code, but
-        * we don't yet know if we'll need to move to a subsequent file.
-        *
-        * Acquire a file descriptor.
-        */
+       /* Acquire a file descriptor. */
        if (dblp->c_fd == -1) {
                if ((ret = __log_name(dblp, nlsn.file, &np)) != 0)
                        goto err1;
-               if ((ret = __db_fdopen(np, DB_RDONLY | DB_SEQUENTIAL,
+               if ((ret = __db_open(np, DB_RDONLY | DB_SEQUENTIAL,
                    DB_RDONLY | DB_SEQUENTIAL, 0, &dblp->c_fd)) != 0) {
                        fail = np;
                        goto err1;
                }
-               free(np);
+               __db_free(np);
                np = NULL;
        }
 
        /* Seek to the header offset and read the header. */
-       if ((ret = __db_lseek(dblp->c_fd, 0, 0, nlsn.offset, SEEK_SET)) != 0) {
+       if ((ret = __db_seek(dblp->c_fd, 0, 0, nlsn.offset, SEEK_SET)) != 0) {
                fail = "seek";
                goto err1;
        }
@@ -289,7 +284,7 @@ retry:
        }
 
        /* Allocate temporary memory to hold the record. */
-       if ((tbuf = (char *)malloc(len)) == NULL) {
+       if ((tbuf = (char *)__db_malloc(len)) == NULL) {
                ret = ENOMEM;
                goto err1;
        }
@@ -318,7 +313,7 @@ retry:
        if ((ret = __db_retcopy(dbt, tbuf, len,
            &dblp->c_dbt.data, &dblp->c_dbt.ulen, NULL)) != 0)
                goto err1;
-       free(tbuf);
+       __db_free(tbuf);
        tbuf = NULL;
 
 cksum: if (hdr.cksum != __ham_func4(dbt->data, dbt->size)) {
@@ -349,8 +344,8 @@ err1:       if (!silent)
                        __db_err(dblp->dbenv,
                            "log_get: %s: %s", fail, strerror(ret));
 err2:  if (np != NULL)
-               free(np);
+               __db_free(np);
        if (tbuf != NULL)
-               free(tbuf);
+               __db_free(tbuf);
        return (ret);
 }
index 225595f33e756ce38a9da1b3c9939f4c09ba7f94..92d95633017513563dfe5d05ef98d9feeca8749a 100644 (file)
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_put.c    10.14 (Sleepycat) 9/23/97";
+static const char sccsid[] = "@(#)log_put.c    10.20 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -29,9 +29,10 @@ static const char sccsid[] = "@(#)log_put.c  10.14 (Sleepycat) 9/23/97";
 #include "common_ext.h"
 
 static int __log_fill __P((DB_LOG *, void *, u_int32_t));
+static int __log_flush __P((DB_LOG *, const DB_LSN *));
 static int __log_newfd __P((DB_LOG *));
-static int __log_write __P((DB_LOG *, void *, u_int32_t));
 static int __log_putr __P((DB_LOG *, const DBT *, u_int32_t));
+static int __log_write __P((DB_LOG *, void *, u_int32_t));
 
 /*
  * log_put --
@@ -63,11 +64,8 @@ log_put(dblp, lsn, dbt, flags)
        }
 
        LOCK_LOGREGION(dblp);
-
        ret = __log_put(dblp, lsn, dbt, flags);
-
        UNLOCK_LOGREGION(dblp);
-
        return (ret);
 }
 
@@ -102,14 +100,10 @@ __log_put(dblp, lsn, dbt, flags)
                            "log_put: record larger than maximum file size");
                        return (EINVAL);
                }
-               if (lp->b_off != 0) {
-                       if ((ret = __log_write(dblp, lp->buf, lp->b_off)) != 0)
-                               return (ret);
-                       if ((ret = __db_fsync(dblp->lfd)) != 0)
-                               return (ret);
-                       lp->s_lsn.file = lp->lsn.file;
-                       lp->s_lsn.offset = lp->lsn.offset - 1;
-               }
+
+               /* Flush the log. */
+               if ((ret = __log_flush(dblp, NULL)) != 0)
+                       return (ret);
 
                /*
                 * Save the last known offset from the previous file, we'll
@@ -117,9 +111,15 @@ __log_put(dblp, lsn, dbt, flags)
                 */
                lastoff = lp->lsn.offset;
 
+               /* Point the current LSN to the new file. */
                ++lp->lsn.file;
                lp->lsn.offset = 0;
+
+               /* Reset the file write offset. */
                lp->w_off = 0;
+
+               /* Reset the first-unwritten LSN for the buffer. */
+               lp->uw_lsn = lp->lsn;
        } else
                lastoff = 0;
 
@@ -149,56 +149,54 @@ __log_put(dblp, lsn, dbt, flags)
         *      Put out the checkpoint record (above).
         *      Save the LSN of the checkpoint in the shared region.
         *      Append the set of file name information into the log.
-        *      Flush the current buffer contents to disk.
-        *      Sync the log to disk.
-        *      Save the time the checkpoint was written.
-        *      Reset the bytes written since the last checkpoint.
         */
        if (flags == DB_CHECKPOINT) {
                lp->c_lsn = *lsn;
 
                for (fnp = SH_TAILQ_FIRST(&dblp->lp->fq, __fname);
                    fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
-                       t.data = ADDR(dblp, fnp->name_off);
+                       t.data = R_ADDR(dblp, fnp->name_off);
                        t.size = strlen(t.data) + 1;
                        memset(&fid_dbt, 0, sizeof(fid_dbt));
-                       fid_dbt.data = ADDR(dblp, fnp->fileid_off);
+                       fid_dbt.data = R_ADDR(dblp, fnp->fileid_off);
                        fid_dbt.size = DB_FILE_ID_LEN;
                        if ((ret = __log_register_log(dblp, NULL, &r_unused,
                            0, &t, &fid_dbt, fnp->id, fnp->s_type)) != 0)
                                return (ret);
                }
-               if (lp->b_off != 0 &&
-                   (ret = __log_write(dblp, lp->buf, lp->b_off)) != 0)
-                       return (ret);
-               (void)time(&lp->chkpt);
-               lp->written = 0;
-
-               if ((ret = __db_fsync(dblp->lfd)) != 0)
-                       return (ret);
-               lp->s_lsn.file = lp->lsn.file;
-               lp->s_lsn.offset = lp->lsn.offset - 1;
        }
 
-       /* We always flush on a checkpoint. */
-       if (flags == DB_FLUSH || flags == DB_CHECKPOINT) {
-               if (lp->b_off != 0 &&
-                   (ret = __log_write(dblp, lp->buf, lp->b_off)) != 0)
+       /*
+        * On a checkpoint or when flush is requested, we:
+        *      Flush the current buffer contents to disk.
+        *      Sync the log to disk.
+        */
+       if (flags == DB_FLUSH || flags == DB_CHECKPOINT)
+               if ((ret = __log_flush(dblp, NULL)) != 0)
                        return (ret);
 
-               if ((ret = __db_fsync(dblp->lfd)) != 0)
-                       return (ret);
-               lp->s_lsn.file = lp->lsn.file;
-               lp->s_lsn.offset = lp->lsn.offset - 1;
+       /*
+        * On a checkpoint, we:
+        *      Save the time the checkpoint was written.
+        *      Reset the bytes written since the last checkpoint.
+        */
+       if (flags == DB_CHECKPOINT) {
+               (void)time(&lp->chkpt);
+               lp->stat.st_wc_bytes = lp->stat.st_wc_mbytes = 0;
        }
 
        /*
-        * If we just did I/O, i.e., this LSN could have spanned the start of
-        * the in-core buffer, we remember it so that we can flush correctly
-        * during a sync.
+        * When an application calls the log_flush routine, we need to figure
+        * out if the current buffer needs to be flushed.  The problem is that
+        * if a record spans buffers, it's possible for the record continued
+        * in the current buffer to have begun in a previous buffer.  Each time
+        * we write a buffer, we update the first-unwritten LSN to point to the
+        * first LSN after that written buffer.  If we have a spanning record,
+        * correct that value to be the LSN that started it all, here.
         */
        if (lsn->offset < lp->w_off && lsn->offset + lp->len > lp->w_off)
-               lp->span_lsn = *lsn;
+               lp->uw_lsn = *lsn;
+
        return (0);
 }
 
@@ -247,6 +245,24 @@ int
 log_flush(dblp, lsn)
        DB_LOG *dblp;
        const DB_LSN *lsn;
+{
+       int ret;
+
+       LOCK_LOGREGION(dblp);
+       ret = __log_flush(dblp, lsn);
+       UNLOCK_LOGREGION(dblp);
+       return (ret);
+}
+
+/*
+ * __log_flush --
+ *     Write all records less than or equal to the specified LSN; internal
+ *     version.
+ */
+static int
+__log_flush(dblp, lsn)
+       DB_LOG *dblp;
+       const DB_LSN *lsn;
 {
        DB_LSN t_lsn;
        LOG *lp;
@@ -255,60 +271,64 @@ log_flush(dblp, lsn)
        ret = 0;
        lp = dblp->lp;
 
-       LOCK_LOGREGION(dblp);
-
-       /* If no LSN specified, flush the entire log. */
+       /*
+        * If no LSN specified, flush the entire log by setting the flush LSN
+        * to the last LSN written in the log.  Otherwise, check that the LSN
+        * isn't a non-existent record for the log.
+        */
        if (lsn == NULL) {
                t_lsn.file = lp->lsn.file;
                t_lsn.offset = lp->lsn.offset - lp->len;
                lsn = &t_lsn;
-       }
-
-       /* If it's a non-existent record, it's an error. */
-       if (lsn->file > lp->lsn.file ||
-           (lsn->file == lp->lsn.file && lsn->offset > lp->lsn.offset)) {
-               __db_err(dblp->dbenv, "log_flush: LSN past current end-of-log");
-               ret = EINVAL;
-               goto ret1;
-       }
-
-       /*
-        * If it's from a previous file, we're done because we sync each
-        * file when we move to a new one.
-        */
-       if (lsn->file < lp->lsn.file)
-               goto ret1;
+       } else
+               if (lsn->file > lp->lsn.file ||
+                   (lsn->file == lp->lsn.file &&
+                   lsn->offset > lp->lsn.offset - lp->len)) {
+                       __db_err(dblp->dbenv,
+                           "log_flush: LSN past current end-of-log");
+                       return (EINVAL);
+               }
 
        /*
-        * If it's less than the last-sync'd offset, we've already sync'd
-        * this LSN.
+        * If the LSN is less than the last-sync'd LSN, we're done.  Note,
+        * the last-sync LSN saved in s_lsn is the LSN of the first byte 
+        * that has not yet been written to disk, so the test is <, not <=.
         */
-       if (lsn->offset <= lp->s_lsn.offset)
-               goto ret1;
+       if (lsn->file < lp->s_lsn.file ||
+           (lsn->file == lp->s_lsn.file && lsn->offset < lp->s_lsn.offset))
+               return (0);
 
        /*
         * We may need to write the current buffer.  We have to write the
-        * current buffer if the sync LSN is greater than or equal to the
-        * saved spanning-LSN.
+        * current buffer if the flush LSN is greater than or equal to the
+        * first-unwritten LSN (uw_lsn).  If we write the buffer, then we
+        * update the first-unwritten LSN.
         */
-       if (lsn->file >= lp->span_lsn.file &&
-           lsn->offset >= lp->span_lsn.offset)
+       if (lp->b_off != 0 &&
+           lsn->file >= lp->uw_lsn.file && lsn->offset >= lp->uw_lsn.offset)
                if ((ret = __log_write(dblp, lp->buf, lp->b_off)) != 0)
-                       goto ret1;
+                       return (ret);
 
-       /* Acquire a file descriptor if we don't have one. */
-       if (dblp->lfname != dblp->lp->lsn.file &&
-           (ret = __log_newfd(dblp)) != 0)
-               goto ret1;
+       /*
+        * It's possible that this thread may never have written to this log
+        * file.  Acquire a file descriptor if we don't already have one.
+        */
+       if (dblp->lfname != dblp->lp->lsn.file)
+               if ((ret = __log_newfd(dblp)) != 0)
+                       return (ret);
 
+       /* Sync all writes to disk. */
        if ((ret = __db_fsync(dblp->lfd)) != 0)
-               goto ret1;
+               return (ret);
+       ++lp->stat.st_scount;
 
-       lp->s_lsn.file = lp->lsn.file;
-       lp->s_lsn.offset = lsn->offset;
+       /*
+        * Set the last-synced LSN, the first LSN after the last record
+        * that we know is on disk.
+        */
+       lp->s_lsn = lp->uw_lsn;
 
-ret1:  UNLOCK_LOGREGION(dblp);
-       return (ret);
+       return (0);
 }
 
 /*
@@ -385,17 +405,32 @@ __log_write(dblp, addr, len)
         * Seek to the offset in the file (someone may have written it
         * since we last did).
         */
-       if ((ret = __db_lseek(dblp->lfd, 0, 0, lp->w_off, SEEK_SET)) != 0)
+       if ((ret = __db_seek(dblp->lfd, 0, 0, lp->w_off, SEEK_SET)) != 0)
                return (ret);
        if ((ret = __db_write(dblp->lfd, addr, len, &nw)) != 0)
                return (ret);
        if (nw != (int32_t)len)
                return (EIO);
 
-       /* Update the seek offset and reset the buffer offset. */
+       /*
+        * Reset the buffer offset, update the seek offset, and update the
+        * first-unwritten LSN.
+        */
        lp->b_off = 0;
        lp->w_off += len;
-       lp->written += len;
+       lp->uw_lsn.file = lp->lsn.file;
+       lp->uw_lsn.offset = lp->w_off;
+
+       /* Update written statistics. */
+       if ((lp->stat.st_w_bytes += len) >= MEGABYTE) {
+               lp->stat.st_w_bytes -= MEGABYTE;
+               ++lp->stat.st_w_mbytes;
+       }
+       if ((lp->stat.st_wc_bytes += len) >= MEGABYTE) {
+               lp->stat.st_wc_bytes -= MEGABYTE;
+               ++lp->stat.st_wc_mbytes;
+       }
+       ++lp->stat.st_wcount;
 
        return (0);
 }
@@ -415,11 +450,8 @@ log_file(dblp, lsn, namep, len)
        char *p;
 
        LOCK_LOGREGION(dblp);
-
        ret = __log_name(dblp, lsn->file, &p);
-
        UNLOCK_LOGREGION(dblp);
-
        if (ret != 0)
                return (ret);
 
@@ -429,7 +461,7 @@ log_file(dblp, lsn, namep, len)
                return (ENOMEM);
        }
        (void)strcpy(namep, p);
-       free(p);
+       __db_free(p);
 
        return (0);
 }
@@ -455,7 +487,7 @@ __log_newfd(dblp)
        dblp->lfname = dblp->lp->lsn.file;
        if ((ret = __log_name(dblp, dblp->lfname, &p)) != 0)
                return (ret);
-       if ((ret = __db_fdopen(p,
+       if ((ret = __db_open(p,
            DB_CREATE | DB_SEQUENTIAL,
            DB_CREATE | DB_SEQUENTIAL,
            dblp->lp->persist.mode, &dblp->lfd)) != 0)
@@ -472,14 +504,14 @@ __log_newfd(dblp)
  * PUBLIC: int __log_name __P((DB_LOG *, int, char **));
  */
 int
-__log_name(dblp, fileno, namep)
+__log_name(dblp, filenumber, namep)
        DB_LOG *dblp;
        char **namep;
-       int fileno;
+       int filenumber;
 {
        char name[sizeof(LFNAME) + 10];
 
-       (void)snprintf(name, sizeof(name), LFNAME, fileno);
+       (void)snprintf(name, sizeof(name), LFNAME, filenumber);
        return (__db_appname(dblp->dbenv,
            DB_APP_LOG, dblp->dir, name, NULL, namep));
 }
index f49a7f16ead5564cc596a886de2ab49080aa7240..92b8203990f4d3d8b82d524164ac261c2a357338 100644 (file)
@@ -40,7 +40,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_rec.c    10.13 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)log_rec.c    10.14 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -99,7 +99,7 @@ __log_register_recover(logp, dbtp, lsnp, redo, info)
 
 out:   F_CLR(logp, DB_AM_RECOVER);
        if (argp != NULL)
-               free(argp);
+               __db_free(argp);
        return (ret);
 }
 
@@ -150,7 +150,7 @@ __log_unregister_recover(logp, dbtp, lsnp, redo, info)
 
 out:   F_CLR(logp, DB_AM_RECOVER);
        if (argp != NULL)
-               free(argp);
+               __db_free(argp);
        return (ret);
 }
 
@@ -227,14 +227,14 @@ __log_add_logid(logp, dbp, ndx)
         */
        if (logp->dbentry_cnt <= ndx) {
                if (logp->dbentry_cnt == 0) {
-                       logp->dbentry =
-                           (DB_ENTRY *)malloc(DB_GROW_SIZE * sizeof(DB_ENTRY));
+                       logp->dbentry = (DB_ENTRY *)
+                           __db_malloc(DB_GROW_SIZE * sizeof(DB_ENTRY));
                        if (logp->dbentry == NULL) {
                                ret = ENOMEM;
                                goto err;
                        }
                } else {
-                       temp_entryp = (DB_ENTRY *)realloc(logp->dbentry,
+                       temp_entryp = (DB_ENTRY *)__db_realloc(logp->dbentry,
                            (DB_GROW_SIZE + logp->dbentry_cnt) *
                            sizeof(DB_ENTRY));
                        if (temp_entryp == NULL) {
index 859b1e5bcbe5ffe22ad2b36b4437420ea9cef4d9..2dab361616af5ba232eda528cb23d5af13dc9bb8 100644 (file)
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_register.c       10.11 (Sleepycat) 9/15/97";
+static const char sccsid[] = "@(#)log_register.c       10.12 (Sleepycat) 9/29/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -72,7 +72,7 @@ log_register(dblp, dbp, name, type, idp)
                if (fid <= fnp->id)
                        fid = fnp->id + 1;
                if (!memcmp(dbp->lock.fileid,
-                   ADDR(dblp, fnp->fileid_off), DB_FILE_ID_LEN)) {
+                   R_ADDR(dblp, fnp->fileid_off), DB_FILE_ID_LEN)) {
                        ++fnp->ref;
                        fid = fnp->id;
                        if (!F_ISSET(dblp, DB_AM_RECOVER) &&
@@ -95,13 +95,13 @@ log_register(dblp, dbp, name, type, idp)
         * XXX Now that uids are fixed size, we can put them in the fnp
         * structure.
         */
-       fnp->fileid_off = OFFSET(dblp, fidp);
+       fnp->fileid_off = R_OFFSET(dblp, fidp);
        memcpy(fidp, dbp->lock.fileid, DB_FILE_ID_LEN);
 
        len = strlen(name) + 1;
        if ((ret = __db_shalloc(dblp->addr, len, 0, &namep)) != 0)
                goto err;
-       fnp->name_off = OFFSET(dblp, namep);
+       fnp->name_off = R_OFFSET(dblp, namep);
        memcpy(namep, name, len);
 
        SH_TAILQ_INSERT_HEAD(&dblp->lp->fq, fnp, q, __fname);
@@ -185,8 +185,8 @@ log_unregister(dblp, fid)
        }
 
        /* Free the unique file information, name and structure. */
-       __db_shalloc_free(dblp->addr, ADDR(dblp, fnp->fileid_off));
-       __db_shalloc_free(dblp->addr, ADDR(dblp, fnp->name_off));
+       __db_shalloc_free(dblp->addr, R_ADDR(dblp, fnp->fileid_off));
+       __db_shalloc_free(dblp->addr, R_ADDR(dblp, fnp->name_off));
        SH_TAILQ_REMOVE(&dblp->lp->fq, fnp, q, __fname);
        __db_shalloc_free(dblp->addr, fnp);
 
index fb6bc96ae79c411abc1e44b0f58cbcdff5ccc5aa..a707603eecf76771bf22fa4ae741392169734caa 100644 (file)
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_bh.c      10.16 (Sleepycat) 9/23/97";
+static const char sccsid[] = "@(#)mp_bh.c      10.21 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -94,10 +94,10 @@ __memp_bhwrite(dbmp, mfp, bhp, restartp, wrotep)
         * files that we have previously tried (and failed) to open.
         */
        dbt.size = mfp->pgcookie_len;
-       dbt.data = ADDR(dbmp, mfp->pgcookie_off);
-       if (__memp_fopen(dbmp, ADDR(dbmp, mfp->path_off),
+       dbt.data = R_ADDR(dbmp, mfp->pgcookie_off);
+       if (__memp_fopen(dbmp, R_ADDR(dbmp, mfp->path_off),
            mfp->ftype, 0, 0, mfp->stat.st_pagesize,
-           mfp->lsn_off, &dbt, ADDR(dbmp, mfp->fileid_off), 0, &dbmfp) != 0)
+           mfp->lsn_off, &dbt, R_ADDR(dbmp, mfp->fileid_off), 0, &dbmfp) != 0)
                return (0);
 
 found: return (__memp_pgwrite(dbmfp, bhp, restartp, wrotep));
@@ -137,7 +137,7 @@ __memp_pgread(dbmfp, bhp, can_create)
        ret = 0;
        LOCKHANDLE(dbmp, dbmfp->mutexp);
        if (dbmfp->fd == -1 || (ret =
-           __db_lseek(dbmfp->fd, pagesize, bhp->pgno, 0, SEEK_SET)) != 0) {
+           __db_seek(dbmfp->fd, pagesize, bhp->pgno, 0, SEEK_SET)) != 0) {
                if (!can_create) {
                        if (dbmfp->fd == -1)
                                ret = EINVAL;
@@ -230,6 +230,7 @@ __memp_pgwrite(dbmfp, bhp, restartp, wrotep)
 
        dbmp = dbmfp->dbmp;
        dbenv = dbmp->dbenv;
+       mp = dbmp->mp;
        mfp = dbmfp->mfp;
 
        if (restartp != NULL)
@@ -277,8 +278,7 @@ __memp_pgwrite(dbmfp, bhp, restartp, wrotep)
        }
 
        /* Write the page out. */
-       if ((ret =
-           __db_lseek(dbmfp->fd, pagesize, bhp->pgno, 0, SEEK_SET)) != 0)
+       if ((ret = __db_seek(dbmfp->fd, pagesize, bhp->pgno, 0, SEEK_SET)) != 0)
                fail = "seek";
        else if ((ret = __db_write(dbmfp->fd, bhp->buf, pagesize, &nw)) != 0)
                fail = "write";
@@ -309,15 +309,23 @@ __memp_pgwrite(dbmfp, bhp, restartp, wrotep)
        /* Clean up the flags based on a successful write. */
        F_SET(bhp, BH_CALLPGIN);
        F_CLR(bhp, BH_DIRTY | BH_LOCKED);
+
+       ++mp->stat.st_page_clean;
+       --mp->stat.st_page_dirty;
+
        UNLOCKBUFFER(dbmp, bhp);
 
        /*
-        * If we wrote a buffer which a checkpoint is waiting for, update
+        * If we write a buffer for which a checkpoint is waiting, update
         * the count of pending buffers (both in the mpool as a whole and
         * for this file).  If the count for this file goes to zero, flush
         * the writes.
         *
         * XXX:
+        * Don't lock the region around the sync, fsync(2) has no atomicity
+        * issues.
+        *
+        * XXX:
         * We ignore errors from the sync -- it makes no sense to return an
         * error to the calling process, so set a flag causing the sync to
         * be retried later.
@@ -325,21 +333,15 @@ __memp_pgwrite(dbmfp, bhp, restartp, wrotep)
         * If the buffer we wrote has a LSN larger than the current largest
         * we've written for this checkpoint, update the saved value.
         */
-       mp = dbmp->mp;
        if (F_ISSET(bhp, BH_WRITE)) {
                if (log_compare(&lsn, &mp->lsn) > 0)
                        mp->lsn = lsn;
                F_CLR(bhp, BH_WRITE);
 
                --mp->lsn_cnt;
-               if (--mfp->lsn_cnt == 0) {
-                       /*
-                        * Don't lock -- there are no atomicity issues for
-                        * fsync(2).
-                        */
-                       if (__db_fsync(dbmfp->fd) != 0)
-                               F_SET(mp, MP_LSN_RETRY);
-               }
+
+               if (--mfp->lsn_cnt == 0 && __db_fsync(dbmfp->fd) != 0)
+                       F_SET(mp, MP_LSN_RETRY);
        }
 
        /* Update I/O statistics. */
@@ -391,7 +393,7 @@ __memp_pg(dbmfp, bhp, is_pgin)
                        dbtp = NULL;
                else {
                        dbt.size = mfp->pgcookie_len;
-                       dbt.data = ADDR(dbmp, mfp->pgcookie_off);
+                       dbt.data = R_ADDR(dbmp, mfp->pgcookie_off);
                        dbtp = &dbt;
                }
                UNLOCKHANDLE(dbmp, dbmp->mutexp);
@@ -433,19 +435,21 @@ __memp_bhfree(dbmp, mfp, bhp, free_mem)
 {
        size_t off;
 
-       /* Delete the buffer header from the MPOOL hash list. */
-       off = BUCKET(dbmp->mp, OFFSET(dbmp, mfp), bhp->pgno);
-       SH_TAILQ_REMOVE(&dbmp->htab[off], bhp, mq, __bh);
+       /* Delete the buffer header from the hash bucket queue. */
+       off = BUCKET(dbmp->mp, R_OFFSET(dbmp, mfp), bhp->pgno);
+       SH_TAILQ_REMOVE(&dbmp->htab[off], bhp, hq, __bh);
 
-       /* Delete the buffer header from the LRU chain. */
+       /* Delete the buffer header from the LRU queue. */
        SH_TAILQ_REMOVE(&dbmp->mp->bhq, bhp, q, __bh);
 
        /*
         * If we're not reusing it immediately, free the buffer header
         * and data for real.
         */
-       if (free_mem)
+       if (free_mem) {
                __db_shalloc_free(dbmp->addr, bhp);
+               --dbmp->mp->stat.st_page_clean;
+       }
 }
 
 /*
@@ -474,13 +478,13 @@ __memp_upgrade(dbmp, dbmfp, mfp)
                return (1);
 
        /* Try the open. */
-       if (__db_fdopen(ADDR(dbmp, mfp->path_off), 0, 0, 0, &fd) != 0) {
+       if (__db_open(R_ADDR(dbmp, mfp->path_off), 0, 0, 0, &fd) != 0) {
                F_SET(dbmfp, MP_UPGRADE_FAIL);
                return (1);
        }
 
        /* Swap the descriptors and set the upgrade flag. */
-       (void)close(dbmfp->fd);
+       (void)__db_close(dbmfp->fd);
        dbmfp->fd = fd;
        F_SET(dbmfp, MP_UPGRADE);
 
index a0364e92c3f308af3b8b22c1d13cf6c6cc79081d..3f99e605051bf2e04355a7131f9b8f3fb9bc2614 100644 (file)
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_fget.c    10.25 (Sleepycat) 9/23/97";
+static const char sccsid[] = "@(#)mp_fget.c    10.30 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -87,14 +87,14 @@ memp_fget(dbmfp, pgnoaddr, flags, addrp)
         * We want to switch threads as often as possible.  Sleep every time
         * we get a new page to make it more likely.
         */
-       if (__sleep_on_every_page_get && (dbmp->dbenv == NULL ||
-           dbmp->dbenv->db_yield == NULL || dbmp->dbenv->db_yield() != 0))
+       if (__sleep_on_every_page_get &&
+           (__db_yield == NULL || __db_yield() != 0))
                __db_sleep(0, 1);
 #endif
 
        mp = dbmp->mp;
        mfp = dbmfp->mfp;
-       mf_offset = OFFSET(dbmp, mfp);
+       mf_offset = R_OFFSET(dbmp, mfp);
        addr = NULL;
        bhp = NULL;
        b_incr = b_inserted = readonly_alloc = ret = 0;
@@ -137,7 +137,7 @@ memp_fget(dbmfp, pgnoaddr, flags, addrp)
                        }
                }
                if (!readonly_alloc) {
-                       addr = ADDR(dbmfp, *pgnoaddr * mfp->stat.st_pagesize);
+                       addr = R_ADDR(dbmfp, *pgnoaddr * mfp->stat.st_pagesize);
 
                        ++mp->stat.st_map;
                        ++mfp->stat.st_map;
@@ -159,9 +159,12 @@ memp_fget(dbmfp, pgnoaddr, flags, addrp)
                 */
                if (dbmfp->fd == -1)
                        size = 0;
-               else if ((ret = __db_stat(dbmp->dbenv,
-                   dbmfp->path, dbmfp->fd, &size, NULL)) != 0)
+               else if ((ret =
+                   __db_ioinfo(dbmfp->path, dbmfp->fd, &size, NULL)) != 0) {
+                       __db_err(dbmp->dbenv,
+                           "%s: %s", dbmfp->path, strerror(ret));
                        goto err;
+               }
 
                *pgnoaddr = size == 0 ? 0 : (size - 1) / mfp->stat.st_pagesize;
 
@@ -190,26 +193,29 @@ memp_fget(dbmfp, pgnoaddr, flags, addrp)
                goto found;
        }
 
-       /* If we haven't checked the BH list yet, do the search. */
+       /* If we haven't checked the BH hash bucket queue, do the search. */
        if (!LF_ISSET(DB_MPOOL_LAST | DB_MPOOL_NEW)) {
-               ++mp->stat.st_hash_searches;
                bucket = BUCKET(mp, mf_offset, *pgnoaddr);
                for (cnt = 0,
                    bhp = SH_TAILQ_FIRST(&dbmp->htab[bucket], __bh);
-                   bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, mq, __bh)) {
+                   bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh)) {
                        ++cnt;
                        if (bhp->pgno == *pgnoaddr &&
                            bhp->mf_offset == mf_offset) {
                                addr = bhp->buf;
+                               ++mp->stat.st_hash_searches;
                                if (cnt > mp->stat.st_hash_longest)
                                        mp->stat.st_hash_longest = cnt;
                                mp->stat.st_hash_examined += cnt;
                                goto found;
                        }
                }
-               if (cnt > mp->stat.st_hash_longest)
-                       mp->stat.st_hash_longest = cnt;
-               mp->stat.st_hash_examined += cnt;
+               if (cnt != 0) {
+                       ++mp->stat.st_hash_searches;
+                       if (cnt > mp->stat.st_hash_longest)
+                               mp->stat.st_hash_longest = cnt;
+                       mp->stat.st_hash_examined += cnt;
+               }
        }
 
        /*
@@ -239,8 +245,9 @@ memp_fget(dbmfp, pgnoaddr, flags, addrp)
         * our region lock without screwing up the world.
         */
        bucket = BUCKET(mp, mf_offset, *pgnoaddr);
-       SH_TAILQ_INSERT_HEAD(&dbmp->htab[bucket], bhp, mq, __bh);
+       SH_TAILQ_INSERT_HEAD(&dbmp->htab[bucket], bhp, hq, __bh);
        SH_TAILQ_INSERT_TAIL(&mp->bhq, bhp, q);
+       ++mp->stat.st_page_clean;
        b_inserted = 1;
 
        /* Set the page number, and associated MPOOLFILE. */
@@ -281,7 +288,8 @@ reread:             if ((ret = __memp_pgread(dbmfp,
                 * !!!
                 * The __memp_pgread call discarded and reacquired the region
                 * lock.  Because the buffer reference count was incremented
-                * before the region lock was discarded the buffer didn't move.
+                * before the region lock was discarded the buffer can't move
+                * and its contents can't change.
                 */
                ++mp->stat.st_cache_miss;
                ++mfp->stat.st_cache_miss;
@@ -305,7 +313,8 @@ found:              /* Increment the reference count. */
                 * BH_LOCKED --
                 * I/O in progress, wait for it to finish.  Because the buffer
                 * reference count was incremented before the region lock was
-                * discarded we know the buffer didn't move.
+                * discarded we know the buffer can't move and its contents
+                * can't change.
                 */
                if (F_ISSET(bhp, BH_LOCKED)) {
                        UNLOCKREGION(dbmp);
index 5ab807701c77fa670f4dff8b6959c728220bf4e5..de59c9ea9b2ed5e7c0a7136e1dd84d3b8496723b 100644 (file)
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_fopen.c   10.27 (Sleepycat) 9/23/97";
+static const char sccsid[] = "@(#)mp_fopen.c   10.30 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -92,7 +92,7 @@ __memp_fopen(dbmp, path,
 
        /* Allocate and initialize the per-process structure. */
        if ((dbmfp =
-           (DB_MPOOLFILE *)calloc(1, sizeof(DB_MPOOLFILE))) == NULL) {
+           (DB_MPOOLFILE *)__db_calloc(1, sizeof(DB_MPOOLFILE))) == NULL) {
                __db_err(dbenv, "%s: %s",
                    path == NULL ? TEMPORARY : path, strerror(ENOMEM));
                return (ENOMEM);
@@ -120,7 +120,7 @@ __memp_fopen(dbmp, path,
 
 
                /* Open the file. */
-               if ((ret = __db_fdopen(dbmfp->path,
+               if ((ret = __db_open(dbmfp->path,
                    LF_ISSET(DB_CREATE | DB_RDONLY), DB_CREATE | DB_RDONLY,
                    mode, &dbmfp->fd)) != 0) {
                        __db_err(dbenv, "%s: %s", dbmfp->path, strerror(ret));
@@ -128,9 +128,11 @@ __memp_fopen(dbmp, path,
                }
 
                /* Don't permit files that aren't a multiple of the pagesize. */
-               if ((ret = __db_stat(dbenv,
-                    dbmfp->path, dbmfp->fd, &size, NULL)) != 0)
+               if ((ret =
+                   __db_ioinfo(dbmfp->path, dbmfp->fd, &size, NULL)) != 0) {
+                       __db_err(dbenv, "%s: %s", dbmfp->path, strerror(ret));
                        goto err;
+               }
                if (size % pagesize) {
                        __db_err(dbenv,
                            "%s: file size not a multiple of the pagesize",
@@ -198,7 +200,7 @@ __memp_fopen(dbmp, path,
        dbmfp->addr = NULL;
        if (mfp->can_mmap) {
                dbmfp->len = size;
-               if (__db_mmap(dbmfp->fd, dbmfp->len, 1, 1, &dbmfp->addr) != 0) {
+               if (__db_map(dbmfp->fd, dbmfp->len, 1, 1, &dbmfp->addr) != 0) {
                        mfp->can_mmap = 0;
                        dbmfp->addr = NULL;
                }
@@ -264,7 +266,7 @@ __memp_mf_open(dbmp, dbmfp,
        for (mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile);
            mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile))
                if (!memcmp(fileid,
-                   ADDR(dbmp, mfp->fileid_off), DB_FILE_ID_LEN)) {
+                   R_ADDR(dbmp, mfp->fileid_off), DB_FILE_ID_LEN)) {
                        if (ftype != mfp->ftype ||
                            pagesize != mfp->stat.st_pagesize) {
                                __db_err(dbmp->dbenv,
@@ -325,10 +327,10 @@ alloc:    if ((ret = __memp_ralloc(dbmp, sizeof(MPOOLFILE), NULL, &mfp)) != 0)
        if (0) {
 err:           if (mfp->path_off != 0)
                        __db_shalloc_free(dbmp->addr,
-                           ADDR(dbmp, mfp->path_off));
+                           R_ADDR(dbmp, mfp->path_off));
                if (!istemp)
                        __db_shalloc_free(dbmp->addr,
-                           ADDR(dbmp, mfp->fileid_off));
+                           R_ADDR(dbmp, mfp->fileid_off));
                if (mfp != NULL)
                        __db_shalloc_free(dbmp->addr, mfp);
                mfp = NULL;
@@ -367,7 +369,7 @@ memp_fclose(dbmfp)
 
        /* Discard any mmap information. */
        if (dbmfp->addr != NULL &&
-           (ret = __db_munmap(dbmfp->addr, dbmfp->len)) != 0)
+           (ret = __db_unmap(dbmfp->addr, dbmfp->len)) != 0)
                __db_err(dbmp->dbenv, "%s: %s", dbmfp->path, strerror(ret));
 
        /* Close the file; temporary files may not yet have been created. */
@@ -423,7 +425,7 @@ __memp_mf_close(dbmp, dbmfp)
         * fairly expensive to reintegrate the buffers back into the region for
         * no purpose.
         */
-       mf_offset = OFFSET(dbmp, mfp);
+       mf_offset = R_OFFSET(dbmp, mfp);
        for (bhp = SH_TAILQ_FIRST(&mp->bhq, __bh); bhp != NULL; bhp = nbhp) {
                nbhp = SH_TAILQ_NEXT(bhp, q, __bh);
 
@@ -436,6 +438,10 @@ __memp_mf_close(dbmp, dbmfp)
 #endif
 
                if (bhp->mf_offset == mf_offset) {
+                       if (F_ISSET(bhp, BH_DIRTY)) {
+                               ++mp->stat.st_page_clean;
+                               --mp->stat.st_page_dirty;
+                       }
                        __memp_bhfree(dbmp, mfp, bhp, 0);
                        SH_TAILQ_INSERT_HEAD(&mp->bhfq, bhp, q, __bh);
                }
@@ -446,11 +452,11 @@ __memp_mf_close(dbmp, dbmfp)
 
        /* Free the space. */
        __db_shalloc_free(dbmp->addr, mfp);
-       __db_shalloc_free(dbmp->addr, ADDR(dbmp, mfp->path_off));
+       __db_shalloc_free(dbmp->addr, R_ADDR(dbmp, mfp->path_off));
        if (mfp->fileid_off != 0)
-               __db_shalloc_free(dbmp->addr, ADDR(dbmp, mfp->fileid_off));
+               __db_shalloc_free(dbmp->addr, R_ADDR(dbmp, mfp->fileid_off));
        if (mfp->pgcookie_off != 0)
-               __db_shalloc_free(dbmp->addr, ADDR(dbmp, mfp->pgcookie_off));
+               __db_shalloc_free(dbmp->addr, R_ADDR(dbmp, mfp->pgcookie_off));
 
 ret1:  UNLOCKREGION(dbmp);
        return (0);
index 9ea7cd9d0dd9e653a16538226ce0d8174c234546..892f179d3a0a2fa7e3c19c3d62156770b6b89526 100644 (file)
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_fput.c    10.12 (Sleepycat) 9/23/97";
+static const char sccsid[] = "@(#)mp_fput.c    10.14 (Sleepycat) 10/5/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -35,10 +35,12 @@ memp_fput(dbmfp, pgaddr, flags)
 {
        BH *bhp;
        DB_MPOOL *dbmp;
+       MPOOL *mp;
        MPOOLFILE *mfp;
        int wrote, ret;
 
        dbmp = dbmfp->dbmp;
+       mp = dbmp->mp;
 
        /* Validate arguments. */
        if (flags) {
@@ -82,10 +84,16 @@ memp_fput(dbmfp, pgaddr, flags)
        LOCKREGION(dbmp);
 
        /* Set/clear the page bits. */
-       if (LF_ISSET(DB_MPOOL_CLEAN))
+       if (LF_ISSET(DB_MPOOL_CLEAN) && F_ISSET(bhp, BH_DIRTY)) {
+               ++mp->stat.st_page_clean;
+               --mp->stat.st_page_dirty;
                F_CLR(bhp, BH_DIRTY);
-       if (LF_ISSET(DB_MPOOL_DIRTY))
+       }
+       if (LF_ISSET(DB_MPOOL_DIRTY) && !F_ISSET(bhp, BH_DIRTY)) {
+               --mp->stat.st_page_clean;
+               ++mp->stat.st_page_dirty;
                F_SET(bhp, BH_DIRTY);
+       }
        if (LF_ISSET(DB_MPOOL_DISCARD))
                F_SET(bhp, BH_DISCARD);
 
@@ -108,11 +116,11 @@ memp_fput(dbmfp, pgaddr, flags)
        }
 
        /* Move the buffer to the head/tail of the LRU chain. */
-       SH_TAILQ_REMOVE(&dbmp->mp->bhq, bhp, q, __bh);
+       SH_TAILQ_REMOVE(&mp->bhq, bhp, q, __bh);
        if (F_ISSET(bhp, BH_DISCARD))
-               SH_TAILQ_INSERT_HEAD(&dbmp->mp->bhq, bhp, q, __bh);
+               SH_TAILQ_INSERT_HEAD(&mp->bhq, bhp, q, __bh);
        else
-               SH_TAILQ_INSERT_TAIL(&dbmp->mp->bhq, bhp, q);
+               SH_TAILQ_INSERT_TAIL(&mp->bhq, bhp, q);
 
        /*
         * If this buffer is scheduled for writing because of a checkpoint,
@@ -125,14 +133,14 @@ memp_fput(dbmfp, pgaddr, flags)
                if (F_ISSET(bhp, BH_DIRTY)) {
                        if (__memp_bhwrite(dbmp,
                            dbmfp->mfp, bhp, NULL, &wrote) != 0 || !wrote)
-                               F_SET(dbmp->mp, MP_LSN_RETRY);
+                               F_SET(mp, MP_LSN_RETRY);
                } else {
                        F_CLR(bhp, BH_WRITE);
 
-                       mfp = ADDR(dbmp, bhp->mf_offset);
+                       mfp = R_ADDR(dbmp, bhp->mf_offset);
                        --mfp->lsn_cnt;
 
-                       --dbmp->mp->lsn_cnt;
+                       --mp->lsn_cnt;
                }
 
        UNLOCKREGION(dbmp);
index a3a3dcef9cae5f62545c1ff26be2f13cb399baf7..a7d270600805158180a635ba66ab22bdbacfccc7 100644 (file)
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_fset.c    10.9 (Sleepycat) 9/20/97";
+static const char sccsid[] = "@(#)mp_fset.c    10.10 (Sleepycat) 10/5/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -34,9 +34,13 @@ memp_fset(dbmfp, pgaddr, flags)
 {
        BH *bhp;
        DB_MPOOL *dbmp;
+       MPOOL *mp;
+       MPOOLFILE *mfp;
        int ret;
 
        dbmp = dbmfp->dbmp;
+       mfp = dbmfp->mfp;
+       mp = dbmp->mp;
 
        /* Validate arguments. */
        if (flags != 0) {
@@ -60,10 +64,16 @@ memp_fset(dbmfp, pgaddr, flags)
 
        LOCKREGION(dbmp);
 
-       if (LF_ISSET(DB_MPOOL_DIRTY))
-               F_SET(bhp, BH_DIRTY);
-       if (LF_ISSET(DB_MPOOL_CLEAN))
+       if (LF_ISSET(DB_MPOOL_CLEAN) && F_ISSET(bhp, BH_DIRTY)) {
+               ++mp->stat.st_page_clean;
+               --mp->stat.st_page_dirty;
                F_CLR(bhp, BH_DIRTY);
+       }
+       if (LF_ISSET(DB_MPOOL_DIRTY) && !F_ISSET(bhp, BH_DIRTY)) {
+               --mp->stat.st_page_clean;
+               ++mp->stat.st_page_dirty;
+               F_SET(bhp, BH_DIRTY);
+       }
        if (LF_ISSET(DB_MPOOL_DISCARD))
                F_SET(bhp, BH_DISCARD);
 
index f622b1ed264f3aef8a9dac14ed90863b569d66cc..4c19739ebd1062ff8fc64065072dcf46e441d9ae 100644 (file)
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_open.c    10.13 (Sleepycat) 9/23/97";
+static const char sccsid[] = "@(#)mp_open.c    10.15 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -54,7 +54,7 @@ memp_open(path, flags, mode, dbenv, retp)
        cachesize = dbenv == NULL ? 0 : dbenv->mp_size;
 
        /* Create and initialize the DB_MPOOL structure. */
-       if ((dbmp = (DB_MPOOL *)calloc(1, sizeof(DB_MPOOL))) == NULL)
+       if ((dbmp = (DB_MPOOL *)__db_calloc(1, sizeof(DB_MPOOL))) == NULL)
                return (ENOMEM);
        LIST_INIT(&dbmp->dbregq);
        TAILQ_INIT(&dbmp->dbmfq);
@@ -62,8 +62,7 @@ memp_open(path, flags, mode, dbenv, retp)
        dbmp->dbenv = dbenv;
 
        /* Decide if it's possible for anyone else to access the pool. */
-       if ((dbenv == NULL && path == NULL) ||
-           (dbenv != NULL && F_ISSET(dbenv, DB_MPOOL_PRIVATE)))
+       if ((dbenv == NULL && path == NULL) || LF_ISSET(DB_MPOOL_PRIVATE))
                F_SET(dbmp, MP_ISPRIVATE);
 
        /*
@@ -183,7 +182,7 @@ memp_register(dbmp, ftype, pgin, pgout)
 {
        DB_MPREG *mpr;
 
-       if ((mpr = (DB_MPREG *)malloc(sizeof(DB_MPREG))) == NULL)
+       if ((mpr = (DB_MPREG *)__db_malloc(sizeof(DB_MPREG))) == NULL)
                return (ENOMEM);
 
        mpr->ftype = ftype;
index 7794cfa7f31ae660dbcf94a7bcbfeb1a7ea58b01..01f0920df49275ec3a9d4003f981fefdd3cd644e 100644 (file)
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_pr.c      10.13 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)mp_pr.c      10.18 (Sleepycat) 11/1/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -53,7 +53,7 @@ memp_stat(dbmp, gspp, fspp, db_malloc)
                *gspp = NULL;
 
                if ((*gspp = db_malloc == NULL ?
-                   (DB_MPOOL_STAT *)malloc(sizeof(**gspp)) :
+                   (DB_MPOOL_STAT *)__db_malloc(sizeof(**gspp)) :
                    (DB_MPOOL_STAT *)db_malloc(sizeof(**gspp))) == NULL)
                        return (ENOMEM);
 
@@ -62,6 +62,10 @@ memp_stat(dbmp, gspp, fspp, db_malloc)
                /* Copy out the global statistics. */
                **gspp = dbmp->mp->stat;
                (*gspp)->st_hash_buckets = dbmp->mp->htab_buckets;
+               (*gspp)->st_region_wait =
+                   dbmp->mp->rlayout.lock.mutex_set_wait;
+               (*gspp)->st_region_nowait =
+                   dbmp->mp->rlayout.lock.mutex_set_nowait;
 
                UNLOCKREGION(dbmp);
        }
@@ -85,7 +89,7 @@ memp_stat(dbmp, gspp, fspp, db_malloc)
                /* Allocate space for the pointers. */
                len = (len + 1) * sizeof(DB_MPOOL_FSTAT *);
                if ((*fspp = db_malloc == NULL ?
-                   (DB_MPOOL_FSTAT **)malloc(len) :
+                   (DB_MPOOL_FSTAT **)__db_malloc(len) :
                    (DB_MPOOL_FSTAT **)db_malloc(len)) == NULL)
                        return (ENOMEM);
 
@@ -96,11 +100,11 @@ memp_stat(dbmp, gspp, fspp, db_malloc)
                    mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile);
                    mfp != NULL;
                    ++tfsp, mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
-                       name = ADDR(dbmp, mfp->path_off);
+                       name = R_ADDR(dbmp, mfp->path_off);
                        nlen = strlen(name);
                        len = sizeof(DB_MPOOL_FSTAT) + nlen + 1;
                        if ((*tfsp = db_malloc == NULL ?
-                           (DB_MPOOL_FSTAT *)malloc(len) :
+                           (DB_MPOOL_FSTAT *)__db_malloc(len) :
                            (DB_MPOOL_FSTAT *)db_malloc(len)) == NULL)
                                return (ENOMEM);
                        **tfsp = mfp->stat;
@@ -200,18 +204,19 @@ __memp_pmp(fp, dbmp, mp, data)
        (void)fprintf(fp, "references: %lu; cachesize: %lu\n",
            (u_long)mp->rlayout.refcnt, (u_long)mp->stat.st_cachesize);
        (void)fprintf(fp,
-           "    %lu pages created\n", mp->stat.st_page_create);
+           "    %lu pages created\n", (u_long)mp->stat.st_page_create);
        (void)fprintf(fp,
-           "    %lu mmap pages returned\n", mp->stat.st_map);
+           "    %lu mmap pages returned\n", (u_long)mp->stat.st_map);
        (void)fprintf(fp, "    %lu I/O's (%lu read, %lu written)\n",
-           mp->stat.st_page_in + mp->stat.st_page_out,
-           mp->stat.st_page_in, mp->stat.st_page_out);
+           (u_long)mp->stat.st_page_in + mp->stat.st_page_out,
+           (u_long)mp->stat.st_page_in, (u_long)mp->stat.st_page_out);
        if (mp->stat.st_cache_hit + mp->stat.st_cache_miss != 0)
                (void)fprintf(fp,
                    "    %.0f%% cache hit rate (%lu hit, %lu miss)\n",
                    ((double)mp->stat.st_cache_hit /
            (mp->stat.st_cache_hit + mp->stat.st_cache_miss)) * 100,
-                   mp->stat.st_cache_hit, mp->stat.st_cache_miss);
+                   (u_long)mp->stat.st_cache_hit,
+                   (u_long)mp->stat.st_cache_miss);
 
        /* Display the MPOOLFILE structures. */
        for (cnt = 0, mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile);
@@ -230,17 +235,18 @@ __memp_pmp(fp, dbmp, mp, data)
        (void)fprintf(fp, "%s\nHASH table of BH's (%lu buckets):\n",
            DB_LINE, (u_long)mp->htab_buckets);
        (void)fprintf(fp,
-           "longest chain searched %lu\n", mp->stat.st_hash_longest);
+           "longest chain searched %lu\n", (u_long)mp->stat.st_hash_longest);
        (void)fprintf(fp, "average chain searched %lu (total/calls: %lu/%lu)\n",
-           mp->stat.st_hash_examined /
+           (u_long)mp->stat.st_hash_examined /
            (mp->stat.st_hash_searches ? mp->stat.st_hash_searches : 1),
-           mp->stat.st_hash_examined, mp->stat.st_hash_searches);
+           (u_long)mp->stat.st_hash_examined,
+           (u_long)mp->stat.st_hash_searches);
        for (htabp = dbmp->htab,
            bucket = 0; bucket < mp->htab_buckets; ++htabp, ++bucket) {
                if (SH_TAILQ_FIRST(&dbmp->htab[bucket], __bh) != NULL)
                        (void)fprintf(fp, "%lu:\n", (u_long)bucket);
                for (bhp = SH_TAILQ_FIRST(&dbmp->htab[bucket], __bh);
-                   bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, mq, __bh))
+                   bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh))
                        __memp_pbh(fp, dbmp, bhp, data);
        }
 
@@ -249,7 +255,7 @@ __memp_pmp(fp, dbmp, mp, data)
        for (sep = "\n    ", bhp = SH_TAILQ_FIRST(&dbmp->mp->bhq, __bh);
            bhp != NULL; sep = ", ", bhp = SH_TAILQ_NEXT(bhp, q, __bh))
                (void)fprintf(fp, "%s%lu/%lu", sep,
-                   (u_long)bhp->pgno, (u_long)OFFSET(dbmp, bhp));
+                   (u_long)bhp->pgno, (u_long)R_OFFSET(dbmp, bhp));
        (void)fprintf(fp, "\n");
 }
 
@@ -263,16 +269,18 @@ __memp_pmf(fp, mfp, data)
        MPOOLFILE *mfp;
        int data;
 {
-       (void)fprintf(fp, "    %lu pages created\n", mfp->stat.st_page_create);
+       (void)fprintf(fp, "    %lu pages created\n",
+           (u_long)mfp->stat.st_page_create);
        (void)fprintf(fp, "    %lu I/O's (%lu read, %lu written)\n",
-           mfp->stat.st_page_in + mfp->stat.st_page_out,
-           mfp->stat.st_page_in, mfp->stat.st_page_out);
+           (u_long)mfp->stat.st_page_in + mfp->stat.st_page_out,
+           (u_long)mfp->stat.st_page_in, (u_long)mfp->stat.st_page_out);
        if (mfp->stat.st_cache_hit + mfp->stat.st_cache_miss != 0)
                (void)fprintf(fp,
                    "    %.0f%% cache hit rate (%lu hit, %lu miss)\n",
                    ((double)mfp->stat.st_cache_hit /
                    (mfp->stat.st_cache_hit + mfp->stat.st_cache_miss)) * 100,
-                   mfp->stat.st_cache_hit, mfp->stat.st_cache_miss);
+                   (u_long)mfp->stat.st_cache_hit,
+                   (u_long)mfp->stat.st_cache_miss);
        if (!data)
                return;
 
@@ -298,7 +306,7 @@ __memp_pbh(fp, dbmp, bhp, data)
                return;
 
        (void)fprintf(fp, "    BH @ %lu (mf: %lu): page %lu; ref %lu",
-           (u_long)OFFSET(dbmp, bhp),
+           (u_long)R_OFFSET(dbmp, bhp),
            (u_long)bhp->mf_offset, (u_long)bhp->pgno, (u_long)bhp->ref);
        sep = "; ";
        if (F_ISSET(bhp, BH_DIRTY)) {
index a5c52123b96ff9800b53c0fab8aca56ce9f852b5..6b2f93125cf7f4e2a7c47ff342d5496d27477fbe 100644 (file)
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_region.c  10.11 (Sleepycat) 8/2/97";
+static const char sccsid[] = "@(#)mp_region.c  10.16 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -51,7 +51,7 @@ __memp_ralloc(dbmp, len, offsetp, retp)
        nomore = 0;
 alloc: if ((ret = __db_shalloc(dbmp->addr, len, MUTEX_ALIGNMENT, &p)) == 0) {
                if (offsetp != NULL)
-                       *offsetp = OFFSET(dbmp, p);
+                       *offsetp = R_OFFSET(dbmp, p);
                *(void **)retp = p;
                return (0);
        }
@@ -68,7 +68,7 @@ alloc:        if ((ret = __db_shalloc(dbmp->addr, len, MUTEX_ALIGNMENT, &p)) == 0) {
                if (__db_shsizeof(bhp) == len) {
                        SH_TAILQ_REMOVE(&mp->bhfq, bhp, q, __bh);
                        if (offsetp != NULL)
-                               *offsetp = OFFSET(dbmp, bhp);
+                               *offsetp = R_OFFSET(dbmp, bhp);
                        *(void **)retp = bhp;
                        return (0);
                }
@@ -82,6 +82,7 @@ alloc:        if ((ret = __db_shalloc(dbmp->addr, len, MUTEX_ALIGNMENT, &p)) == 0) {
 
                SH_TAILQ_REMOVE(&mp->bhfq, bhp, q, __bh);
                __db_shalloc_free(dbmp->addr, bhp);
+               --mp->stat.st_page_clean;
 
                /*
                 * Retry as soon as we've freed up sufficient space.  If we
@@ -104,7 +105,7 @@ retry:      /* Find a buffer we can flush; pure LRU. */
                        continue;
 
                /* Find the associated MPOOLFILE. */
-               mfp = ADDR(dbmp, bhp->mf_offset);
+               mfp = R_ADDR(dbmp, bhp->mf_offset);
 
                /*
                 * Write the page if it's dirty.
@@ -135,8 +136,7 @@ retry:      /* Find a buffer we can flush; pure LRU. */
                        else {
                                if (restart)
                                        goto retry;
-                               else
-                                       continue;
+                               continue;
                        }
                } else
                        ++mp->stat.st_ro_evict;
@@ -150,7 +150,7 @@ retry:      /* Find a buffer we can flush; pure LRU. */
                        __memp_bhfree(dbmp, mfp, bhp, 0);
 
                        if (offsetp != NULL)
-                               *offsetp = OFFSET(dbmp, bhp);
+                               *offsetp = R_OFFSET(dbmp, bhp);
                        *(void **)retp = bhp;
                        return (0);
                }
@@ -225,9 +225,13 @@ retry:     if (LF_ISSET(DB_CREATE)) {
                 * be possible for DB_THREAD to be set if HAVE_SPINLOCKS aren't
                 * defined.
                 */
-               if (F_ISSET(dbmp, MP_ISPRIVATE))
-                       ret = (dbmp->maddr = malloc(rlen)) == NULL ? ENOMEM : 0;
-               else
+               if (F_ISSET(dbmp, MP_ISPRIVATE)) {
+                       if ((dbmp->maddr = __db_malloc(rlen)) == NULL)
+                               ret = ENOMEM;
+                       else
+                               ret = __db_rinit(dbmp->dbenv,
+                                   dbmp->maddr, 0, rlen, 0);
+               } else
                        ret = __db_rcreate(dbmp->dbenv, DB_APP_NONE, path,
                            DB_DEFAULT_MPOOL_FILE, mode, rlen, &fd,
                            &dbmp->maddr);
@@ -259,7 +263,10 @@ retry:     if (LF_ISSET(DB_CREATE)) {
                            0, &dbmp->htab)) != 0)
                                goto err;
                        __db_hashinit(dbmp->htab, mp->htab_buckets);
-                       mp->htab = OFFSET(dbmp, dbmp->htab);
+                       mp->htab = R_OFFSET(dbmp, dbmp->htab);
+
+                       ZERO_LSN(mp->lsn);
+                       mp->lsn_cnt = 0;
 
                        memset(&mp->stat, 0, sizeof(mp->stat));
                        mp->stat.st_cachesize = cachesize;
@@ -303,7 +310,7 @@ retry:      if (LF_ISSET(DB_CREATE)) {
         * Get the hash table address; it's on the shared page, so we have
         * to lock first.
         */
-       dbmp->htab = ADDR(dbmp, dbmp->mp->htab);
+       dbmp->htab = R_ADDR(dbmp, dbmp->mp->htab);
 
        dbmp->fd = fd;
 
@@ -333,7 +340,7 @@ __memp_rclose(dbmp)
        DB_MPOOL *dbmp;
 {
        if (F_ISSET(dbmp, MP_ISPRIVATE)) {
-               free(dbmp->maddr);
+               __db_free(dbmp->maddr);
                return (0);
        }
        return (__db_rclose(dbmp->dbenv, dbmp->fd, dbmp->maddr));
index 65b2a18267e5a47a3ea664db00d018040fd33bcc..2f042df9e1c51e3e52c306418486d923879d0674 100644 (file)
@@ -7,13 +7,14 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_sync.c    10.9 (Sleepycat) 8/29/97";
+static const char sccsid[] = "@(#)mp_sync.c    10.15 (Sleepycat) 11/1/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
+#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -23,6 +24,8 @@ static const char sccsid[] = "@(#)mp_sync.c   10.9 (Sleepycat) 8/29/97";
 #include "mp.h"
 #include "common_ext.h"
 
+static int __bhcmp __P((const void *, const void *));
+
 /*
  * memp_sync --
  *     Mpool sync function.
@@ -32,27 +35,40 @@ memp_sync(dbmp, lsnp)
        DB_MPOOL *dbmp;
        DB_LSN *lsnp;
 {
-       BH *bhp;
+       BH *bhp, **bharray;
        DB_ENV *dbenv;
        MPOOL *mp;
        MPOOLFILE *mfp;
-       int can_write, wrote, lsn_cnt, restart, ret;
+       int ar_cnt, cnt, nalloc, next, notused, ret, wrote;
 
        dbenv = dbmp->dbenv;
 
-       if (dbmp->dbenv->lg_info == NULL) {
-               __db_err(dbenv, "memp_sync requires logging");
+       if (dbenv->lg_info == NULL) {
+               __db_err(dbenv, "memp_sync: requires logging");
                return (EINVAL);
        }
 
+       /*
+        * We try and write the buffers in page order so that the underlying
+        * filesystem doesn't have to seek and can write contiguous blocks,
+        * plus, we don't want to hold the region lock while we write the
+        * buffers.  Get memory to hold the buffer pointers.  Get a good-size
+        * block, too, because we realloc while holding the region lock if we
+        * run out.
+        */
+       if ((bharray =
+           (BH **)__db_malloc((nalloc = 1024) * sizeof(BH *))) == NULL)
+               return (ENOMEM);
+
        LOCKREGION(dbmp);
 
        /*
-        * If the application is asking about a previous call, and we haven't
-        * found any buffers that the application holding the pin couldn't
-        * write, return yes or no based on the current count.  Note, if the
-        * application is asking about a LSN *smaller* than one we've already
-        * handled, then we return based on the count for that LSN.
+        * If the application is asking about a previous call to memp_sync(),
+        * and we haven't found any buffers that the application holding the
+        * pin couldn't write, return yes or no based on the current count.
+        * Note, if the application is asking about a LSN *smaller* than one
+        * we've already handled or are currently handling, then we return a
+        * result based on the count for the larger LSN.
         */
        mp = dbmp->mp;
        if (!F_ISSET(mp, MP_LSN_RETRY) && log_compare(lsnp, &mp->lsn) <= 0) {
@@ -61,9 +77,7 @@ memp_sync(dbmp, lsnp)
                        ret = 0;
                } else
                        ret = DB_INCOMPLETE;
-
-               UNLOCKREGION(dbmp);
-               return (ret);
+               goto done;
        }
 
        /* Else, it's a new checkpoint. */
@@ -74,7 +88,7 @@ memp_sync(dbmp, lsnp)
         * for which we were already doing a checkpoint.  (BTW, I don't expect
         * to see multiple LSN's from the same or multiple processes, but You
         * Just Never Know.  Responding as if they all called with the largest
-        * of the LSNs specified makes everything work.
+        * of the LSNs specified makes everything work.)
         *
         * We don't currently use the LSN we save.  We could potentially save
         * the last-written LSN in each buffer header and use it to determine
@@ -93,64 +107,127 @@ memp_sync(dbmp, lsnp)
 
        /*
         * Walk the list of buffers and mark all dirty buffers to be written
-        * and all pinned buffers to be potentially written.  We do this in
-        * single fell swoop while holding the region locked so that processes
-        * can't make new buffers dirty, causing us to never finish.  Since
-        * the application may have restarted the sync, clear any BH_WRITE
-        * flags that appear to be left over.
+        * and all pinned buffers to be potentially written (we can't know if
+        * we'll need to write them until the holding process returns them to
+        * the cache).  We do this in one pass while holding the region locked
+        * so that processes can't make new buffers dirty, causing us to never
+        * finish.  Since the application may have restarted the sync, clear
+        * any BH_WRITE flags that appear to be left over from previous calls.
+        *
+        * Keep a count of the total number of buffers we need to write in
+        * MPOOL->lsn_cnt, and for each file, in MPOOLFILE->lsn_count.
         */
-       can_write = lsn_cnt = 0;
-       for (lsn_cnt = 0, bhp = SH_TAILQ_FIRST(&mp->bhq, __bh);
+       ar_cnt = 0;
+       for (bhp = SH_TAILQ_FIRST(&mp->bhq, __bh);
            bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh))
                if (F_ISSET(bhp, BH_DIRTY) || bhp->ref != 0) {
                        F_SET(bhp, BH_WRITE);
 
-                       if (bhp->ref == 0)
-                               can_write = 1;
+                       ++mp->lsn_cnt;
 
-                       mfp = ADDR(dbmp, bhp->mf_offset);
+                       mfp = R_ADDR(dbmp, bhp->mf_offset);
                        ++mfp->lsn_cnt;
 
-                       ++lsn_cnt;
+                       /*
+                        * If the buffer isn't in use, we should be able to
+                        * write it immediately, so save a reference to it.
+                        */
+                       if (bhp->ref == 0) {
+                               if (ar_cnt == nalloc) {
+                                       nalloc *= 2;
+                                       if ((bharray =
+                                           (BH **)__db_realloc(bharray,
+                                           nalloc * sizeof(BH *))) == NULL) {
+                                               ret = ENOMEM;
+                                               goto err;
+                                       }
+                               }
+                               bharray[ar_cnt++] = bhp;
+                       }
                } else
                        F_CLR(bhp, BH_WRITE);
 
-       mp->lsn_cnt = lsn_cnt;
-
-       /* If there no buffers we can write, we're done. */
-       if (!can_write) {
-               UNLOCKREGION(dbmp);
-               return (mp->lsn_cnt ? DB_INCOMPLETE : 0);
+       /* If there no buffers we can write immediately, we're done. */
+       if (ar_cnt == 0) {
+               ret = mp->lsn_cnt ? DB_INCOMPLETE : 0;
+               goto done;
        }
 
-       /*
-        * Write any buffers that we can.  Restart the walk after each write,
-        * __memp_pgwrite() discards and reacquires the region lock during I/O.
-        */
-retry: for (bhp = SH_TAILQ_FIRST(&mp->bhq, __bh);
-           bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh)) {
-               /* Ignore pinned or locked buffers. */
-               if (!F_ISSET(bhp, BH_WRITE) ||
-                   bhp->ref != 0 || F_ISSET(bhp, BH_LOCKED))
-                       continue;
+       /* Lock down the buffers and their contents. */
+       for (cnt = 0; cnt < ar_cnt; ++cnt)
+               ++bharray[cnt]->ref;
 
-               mfp = ADDR(dbmp, bhp->mf_offset);
-               if ((ret =
-                   __memp_bhwrite(dbmp, mfp, bhp, &restart, &wrote)) != 0)
-                       goto err;
-               if (wrote) {
-                       if (restart)
-                               goto retry;
+       UNLOCKREGION(dbmp);
+
+       /* Sort the buffers we're going to write. */
+       qsort(bharray, ar_cnt, sizeof(BH *), __bhcmp);
+
+       LOCKREGION(dbmp);
+
+       /* Walk the array, writing buffers. */
+       for (next = 0; next < ar_cnt; ++next) {
+               /*
+                * It's possible for a thread to have gotten the buffer since
+                * we listed it for writing.  If the reference count is still
+                * 1, we're the only ones using the buffer, go ahead and write.
+                * If it's >1, then skip the buffer and assume that it will be
+                * written when it's returned to the cache.
+                */
+               if (bharray[next]->ref > 1) {
+                       --bharray[next]->ref;
                        continue;
                }
-               __db_err(dbenv, "%s: unable to flush page: %lu",
-                   ADDR(dbmp, mfp->path_off), (u_long)bhp->pgno);
-               ret = EPERM;
-               goto err;
+
+               /* Write the buffer. */
+               mfp = R_ADDR(dbmp, bharray[next]->mf_offset);
+               ret =
+                   __memp_bhwrite(dbmp, mfp, bharray[next], &notused, &wrote);
+
+               /* Release the buffer. */
+               --bharray[next]->ref;
+
+               /* If there's an error, release the rest of the buffers. */
+               if (ret != 0 || !wrote) {
+                       while (++next < ar_cnt)
+                               --bharray[next]->ref;
+
+                       if (ret != 0)
+                               goto err;
+
+                       /*
+                        * Any process syncing the shared memory buffer pool
+                        * had better be able to write to any underlying file.
+                        * Be understanding, but firm, on this point.
+                        */
+                       if (!wrote) {
+                               __db_err(dbenv, "%s: unable to flush page: %lu",
+                                   R_ADDR(dbmp, mfp->path_off),
+                                   (u_long)bharray[next]->pgno);
+                               ret = EPERM;
+                               goto err;
+                       }
+               }
        }
        ret = mp->lsn_cnt ? DB_INCOMPLETE : 0;
 
-err:   UNLOCKREGION(dbmp);
+done:
+       if (0) {
+err:           /*
+                * On error, clear:
+                *      MPOOL->lsn_cnt (the total sync count)
+                *      MPOOLFILE->lsn_cnt (the per-file sync count)
+                *      BH_WRITE flag (the scheduled for writing flag)
+                */
+               mp->lsn_cnt = 0;
+               for (mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile);
+                   mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile))
+                       mfp->lsn_cnt = 0;
+               for (bhp = SH_TAILQ_FIRST(&mp->bhq, __bh);
+                   bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh))
+                       F_CLR(bhp, BH_WRITE);
+       }
+       UNLOCKREGION(dbmp);
+       __db_free(bharray);
        return (ret);
 }
 
@@ -162,10 +239,10 @@ int
 memp_fsync(dbmfp)
        DB_MPOOLFILE *dbmfp;
 {
-       BH *bhp;
+       BH *bhp, **bharray;
        DB_MPOOL *dbmp;
        size_t mf_offset;
-       int pincnt, restart, ret, wrote;
+       int ar_cnt, cnt, nalloc, next, pincnt, notused, ret, wrote;
 
        /*
         * If this handle doesn't have a file descriptor that's open for
@@ -175,35 +252,205 @@ memp_fsync(dbmfp)
        if (F_ISSET(dbmfp, MP_READONLY | MP_PATH_TEMP))
                return (0);
 
-       dbmp = dbmfp->dbmp;
        ret = 0;
+       dbmp = dbmfp->dbmp;
+       mf_offset = R_OFFSET(dbmp, dbmfp->mfp);
 
-       mf_offset = OFFSET(dbmp, dbmfp->mfp);
+       /*
+        * We try and write the buffers in page order so that the underlying
+        * filesystem doesn't have to seek and can write contiguous blocks,
+        * plus, we don't want to hold the region lock while we write the
+        * buffers.  Get memory to hold the buffer pointers.  Get a good-size
+        * block, too, because we realloc while holding the region lock if we
+        * run out.
+        */
+       nalloc = 1024;
+       if ((bharray =
+           (BH **)__db_malloc((size_t)nalloc * sizeof(BH *))) == NULL)
+               return (ENOMEM);
 
        LOCKREGION(dbmp);
 
        /*
-        * Walk the list of buffer headers for the MPOOLFILE, and write out any
-        * dirty buffers that we can.
+        * Walk the LRU list of buffer headers, and get a list of buffers to
+        * write for this MPOOLFILE.
         */
-retry: pincnt = 0;
+       ar_cnt = pincnt = 0;
        for (bhp = SH_TAILQ_FIRST(&dbmp->mp->bhq, __bh);
-           bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh))
-               if (F_ISSET(bhp, BH_DIRTY) && bhp->mf_offset == mf_offset) {
-                       if (bhp->ref != 0 || F_ISSET(bhp, BH_LOCKED)) {
-                               ++pincnt;
-                               continue;
-                       }
-                       if ((ret =
-                           __memp_pgwrite(dbmfp, bhp, &restart, &wrote)) != 0)
+           bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh)) {
+               if (!F_ISSET(bhp, BH_DIRTY) || bhp->mf_offset != mf_offset)
+                       continue;
+               if (bhp->ref != 0 || F_ISSET(bhp, BH_LOCKED)) {
+                       ++pincnt;
+                       continue;
+               }
+
+               if (ar_cnt == nalloc) {
+                       nalloc *= 2;
+                       if ((bharray = (BH **)__db_realloc(bharray,
+                           nalloc * sizeof(BH *))) == NULL) {
+                               ret = ENOMEM;
                                goto err;
-                       if (!wrote)
-                               ++pincnt;
-                       if (restart)
-                               goto retry;
+                       }
+               }
+
+               bharray[ar_cnt++] = bhp;
+       }
+
+       /* Lock down the buffers and their contents. */
+       for (cnt = 0; cnt < ar_cnt; ++cnt)
+               ++bharray[cnt]->ref;
+
+       UNLOCKREGION(dbmp);
+
+       /* Sort the buffers we're going to write. */
+       qsort(bharray, ar_cnt, sizeof(BH *), __bhcmp);
+
+       LOCKREGION(dbmp);
+
+       /* Walk the array, writing buffers. */
+       for (next = 0; next < ar_cnt; ++next) {
+               /*
+                * It's possible for a thread to have gotten the buffer since
+                * we listed it for writing.  If the reference count is still
+                * 1, we're the only ones using the buffer, go ahead and write.
+                * If it's >1, then skip the buffer and assume that it will be
+                * written when it's returned to the cache.
+                */
+               if (bharray[next]->ref > 1) {
+                       ++pincnt;
+
+                       --bharray[next]->ref;
+                       continue;
                }
 
+               /* Write the buffer. */
+               ret = __memp_pgwrite(dbmfp, bharray[next], &notused, &wrote);
+
+               /* Release the buffer. */
+               --bharray[next]->ref;
+
+               /* If there's an error, release the rest of the buffers. */
+               if (ret != 0) {
+                       while (++next < ar_cnt)
+                               --bharray[next]->ref;
+                       goto err;
+               }
+               if (!wrote)
+                       ++pincnt;
+       }
+
+err:   UNLOCKREGION(dbmp);
+
+       __db_free(bharray);
+
+       /*
+        * Sync the underlying file as the last thing we do, so that the OS
+        * has maximal opportunity to flush buffers before we request it.
+        *
+        * XXX:
+        * Don't lock the region around the sync, fsync(2) has no atomicity
+        * issues.
+        */
+       if (ret == 0)
+               return (pincnt == 0 ? __db_fsync(dbmfp->fd) : DB_INCOMPLETE);
+       return (ret);
+
+}
+
+/*
+ * memp_trickle --
+ *     Keep a specified percentage of the buffers clean.
+ */
+int
+memp_trickle(dbmp, pct, nwrotep)
+       DB_MPOOL *dbmp;
+       int pct, *nwrotep;
+{
+       BH *bhp;
+       MPOOL *mp;
+       MPOOLFILE *mfp;
+       u_long total;
+       int notused, ret, wrote;
+
+       mp = dbmp->mp;
+       if (nwrotep != NULL)
+               *nwrotep = 0;
+
+       if (pct < 1 || pct > 100)
+               return (EINVAL);
+
+       LOCKREGION(dbmp);
+
+       /*
+        * If there are sufficient clean buffers, or no buffers or no dirty
+        * buffers, we're done.
+        *
+        * XXX
+        * Using st_page_clean and st_page_dirty is our only choice at the
+        * moment, but it's not as correct as we might like in the presence
+        * of pools with more than one buffer size, as a free 512-byte buffer
+        * isn't the same as a free 8K buffer.
+        */
+loop:  total = mp->stat.st_page_clean + mp->stat.st_page_dirty;
+       if (total == 0 || mp->stat.st_page_dirty == 0 ||
+           (mp->stat.st_page_clean * 100) / total >= (u_long)pct) {
+               UNLOCKREGION(dbmp);
+               return (0);
+       }
+
+       /* Loop until we write a buffer. */
+       for (bhp = SH_TAILQ_FIRST(&mp->bhq, __bh);
+           bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh)) {
+               if (bhp->ref != 0 ||
+                   !F_ISSET(bhp, BH_DIRTY) || F_ISSET(bhp, BH_LOCKED))
+                       continue;
+
+               mfp = R_ADDR(dbmp, bhp->mf_offset);
+               if ((ret =
+                   __memp_bhwrite(dbmp, mfp, bhp, &notused, &wrote)) != 0)
+                       goto err;
+
+               /*
+                * Any process syncing the shared memory buffer pool
+                * had better be able to write to any underlying file.
+                * Be understanding, but firm, on this point.
+                */
+               if (!wrote) {
+                       __db_err(dbmp->dbenv, "%s: unable to flush page: %lu",
+                           R_ADDR(dbmp, mfp->path_off), (u_long)bhp->pgno);
+                       ret = EPERM;
+                       goto err;
+               }
+
+               ++mp->stat.st_page_trickle;
+               if (nwrotep != NULL)
+                       ++*nwrotep;
+               goto loop;
+       }
+
+       /* No more buffers to write. */
+       return (0);
+
 err:   UNLOCKREGION(dbmp);
+       return (ret);
+}
+
+static int
+__bhcmp(p1, p2)
+       const void *p1, *p2;
+{
+       BH *bhp1, *bhp2;
+
+       bhp1 = *(BH **)p1;
+       bhp2 = *(BH **)p2;
+
+       /* Sort by file (shared memory pool offset). */
+       if (bhp1->mf_offset < bhp2->mf_offset)
+               return (-1);
+       if (bhp1->mf_offset > bhp2->mf_offset)
+               return (1);
 
-       return (ret == 0 ? (pincnt ? DB_INCOMPLETE : 0) : ret);
+       /* Sort by page in file. */
+       return (bhp1->pgno < bhp2->pgno ? -1 : 1);
 }
index 5315b2d3fe7f54ef02da5fd59cee10246266f80b..7c8ea6ebd14a53653f6baa28dcad5fe6ccf475aa 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mutex.c      10.25 (Sleepycat) 9/23/97";
+static const char sccsid[] = "@(#)mutex.c      10.28 (Sleepycat) 10/31/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -67,6 +67,10 @@ static const char sccsid[] = "@(#)mutex.c    10.25 (Sleepycat) 9/23/97";
 #define        TSL_UNSET(x)    _lock_clear(x)
 #endif
 
+#ifdef HAVE_ASSEM_SCO_CC
+#include "sco.cc"
+#endif
+
 #ifdef HAVE_ASSEM_SPARC_GCC
 #include "sparc.gcc"
 #endif
@@ -138,13 +142,12 @@ __db_mutex_init(mp, off)
  * __db_mutex_lock
  *     Lock on a mutex, logically blocking if necessary.
  *
- * PUBLIC: int __db_mutex_lock __P((db_mutex_t *, int, int (*)(void)));
+ * PUBLIC: int __db_mutex_lock __P((db_mutex_t *, int));
  */
 int
-__db_mutex_lock(mp, fd, yield)
+__db_mutex_lock(mp, fd)
        db_mutex_t *mp;
        int fd;
-       int (*yield) __P((void));
 {
        u_long usecs;
 
@@ -166,17 +169,15 @@ __db_mutex_lock(mp, fd, yield)
                                }
                                mp->pid = getpid();
 #endif
-#ifdef MUTEX_STATISTICS
                                if (usecs == MS(10))
                                        ++mp->mutex_set_nowait;
                                else
                                        ++mp->mutex_set_wait;
-#endif
                                return (0);
                        }
 
                /* Yield the processor; wait 10ms initially, up to 1 second. */
-               if (yield == NULL || yield() != 0) {
+               if (__db_yield == NULL || __db_yield() != 0) {
                        (void)__db_sleep(0, usecs);
                        if ((usecs <<= 1) > SECOND)
                                usecs = SECOND;
@@ -200,7 +201,7 @@ __db_mutex_lock(mp, fd, yield)
                 * up to 1 second.
                 */
                for (usecs = MS(10); mp->pid != 0;)
-                       if (yield == NULL || yield() != 0) {
+                       if (__db_yield == NULL || __db_yield() != 0) {
                                (void)__db_sleep(0, usecs);
                                if ((usecs <<= 1) > SECOND)
                                        usecs = SECOND;
@@ -234,10 +235,6 @@ __db_mutex_lock(mp, fd, yield)
                if (locked)
                        break;
        }
-
-#ifdef MUTEX_STATISTICS
-       ++mp->mutex_set_wait;
-#endif
        return (0);
 #endif /* !HAVE_SPINLOCKS */
 }
diff --git a/db2/os/db_os_abs.c b/db2/os/db_os_abs.c
deleted file mode 100644 (file)
index 8795205..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1997
- *     Sleepycat Software.  All rights reserved.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)db_os_abs.c  10.5 (Sleepycat) 7/5/97";
-#endif /* not lint */
-
-#ifndef NO_SYSTEM_INCLUDES
-#include <string.h>
-#endif
-
-#include "db_int.h"
-#include "os_ext.h"
-
-/*
- * __db_abspath --
- *     Return if a path is an absolute path.
- *
- * PUBLIC: int __db_abspath __P((const char *));
- */
-int
-__db_abspath(path)
-       const char *path;
-{
-#ifdef _WIN32
-       /*
-        * !!!
-        * Check for drive specifications, e.g., "C:".  In addition, the path
-        * separator used by the win32 DB (PATH_SEPARATOR) is \; look for both
-        * / and \ since these are user-input paths.
-        */
-       if (isalpha(path[0]) && path[1] == ':')
-               path += 2;
-       return (path[0] == '/' || path[0] == '\\');
-#else
-#ifdef macintosh
-       /*
-        * !!!
-        * Absolute pathnames always start with a volume name, which must be
-        * followed by a colon, thus they are of the form:
-        *      volume: or volume:dir1:dir2:file
-        *
-        * Relative pathnames are either a single name without colons or a
-        * path starting with a colon, thus of the form:
-        *      file or :file or :dir1:dir2:file
-        */
-       return (strchr(path, ':') != NULL && path[0] != ':');
-#else
-       return (path[0] == '/');
-#endif
-#endif
-}
-
-/*
- * __db_rpath --
- *     Return the last path separator in the path or NULL if none found.
- *
- * PUBLIC: char *__db_rpath __P((const char *));
- */
-char *
-__db_rpath(path)
-       const char *path;
-{
-       const char *s, *last;
-
-       last = NULL;
-       if (PATH_SEPARATOR[1] != '\0') {
-               for (s = path; s[0] != '\0'; ++s)
-                       if (strchr(PATH_SEPARATOR, s[0]) != NULL)
-                               last = s;
-       } else
-               for (s = path; s[0] != '\0'; ++s)
-                       if (s[0] == PATH_SEPARATOR[0])
-                               last = s;
-       return ((char *)last);
-}
diff --git a/db2/os/db_os_dir.c b/db2/os/db_os_dir.c
deleted file mode 100644 (file)
index 1206e3f..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1997
- *     Sleepycat Software.  All rights reserved.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)db_os_dir.c  10.10 (Sleepycat) 9/17/97";
-#endif /* not lint */
-
-#ifndef NO_SYSTEM_INCLUDES
-#include <sys/types.h>
-
-#if HAVE_DIRENT_H
-# include <dirent.h>
-# define NAMLEN(dirent) strlen((dirent)->d_name)
-#else
-# define dirent direct
-# define NAMLEN(dirent) (dirent)->d_namlen
-# if HAVE_SYS_NDIR_H
-#  include <sys/ndir.h>
-# endif
-# if HAVE_SYS_DIR_H
-#  include <sys/dir.h>
-# endif
-# if HAVE_NDIR_H
-#  include <ndir.h>
-# endif
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#endif
-
-#include "db_int.h"
-#include "os_ext.h"
-#include "common_ext.h"
-
-/*
- * __db_dir --
- *     Return a list of the files in a directory.
- *
- * PUBLIC: int __db_dir __P((DB_ENV *, const char *, char ***, int *));
- */
-int
-__db_dir(dbenv, dir, namesp, cntp)
-       DB_ENV *dbenv;
-       const char *dir;
-       char ***namesp;
-       int *cntp;
-{
-       int arraysz, cnt;
-       char **names;
-#ifdef _WIN32
-       struct _finddata_t fdata;
-       long dirhandle;
-       int finished;
-       char filespec[MAX_PATH];
-
-       (void)snprintf(filespec, sizeof(filespec), "%s/*", dir);
-       if ((dirhandle = _findfirst(filespec, &fdata)) == -1) {
-               __db_err(dbenv, "%s: %s", filespec, strerror(errno));
-               return (errno);
-       }
-
-       names = NULL;
-       finished = 0;
-       for (arraysz = cnt = 0; finished != 1; ++cnt) {
-               if (cnt >= arraysz) {
-                       arraysz += 100;
-                       names = (char **)(names == NULL ?
-                           malloc(arraysz * sizeof(names[0])) :
-                           realloc(names, arraysz * sizeof(names[0])));
-                       if (names == NULL)
-                               goto nomem;
-               }
-               if ((names[cnt] = (char *)strdup(fdata.name)) == NULL)
-                       goto nomem;
-               if (_findnext(dirhandle,&fdata) != 0)
-                       finished = 1;
-       }
-       _findclose(dirhandle);
-#else /* !_WIN32 */
-       struct dirent *dp;
-       DIR *dirp;
-
-       if ((dirp = opendir(dir)) == NULL) {
-               __db_err(dbenv, "%s: %s", dir, strerror(errno));
-               return (errno);
-       }
-       names = NULL;
-       for (arraysz = cnt = 0; (dp = readdir(dirp)) != NULL; ++cnt) {
-               if (cnt >= arraysz) {
-                       arraysz += 100;
-                       names = (char **)(names == NULL ?
-                           malloc(arraysz * sizeof(names[0])) :
-                           realloc(names, arraysz * sizeof(names[0])));
-                       if (names == NULL)
-                               goto nomem;
-               }
-               if ((names[cnt] = (char *)strdup(dp->d_name)) == NULL)
-                       goto nomem;
-       }
-       (void)closedir(dirp);
-#endif /* !_WIN32 */
-
-       *namesp = names;
-       *cntp = cnt;
-       return (0);
-
-nomem: if (names != NULL)
-               __db_dirf(dbenv, names, cnt);
-       __db_err(dbenv, "%s", strerror(ENOMEM));
-       return (ENOMEM);
-}
-
-/*
- * __db_dirf --
- *     Free the list of files.
- *
- * PUBLIC: void __db_dirf __P((DB_ENV *, char **, int));
- */
-void
-__db_dirf(dbenv, names, cnt)
-       DB_ENV *dbenv;
-       char **names;
-       int cnt;
-{
-       dbenv = dbenv;                  /* XXX: Shut the compiler up. */
-       while (cnt > 0)
-               free(names[--cnt]);
-       free (names);
-}
diff --git a/db2/os/db_os_lseek.c b/db2/os/db_os_lseek.c
deleted file mode 100644 (file)
index cecf0e1..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1997
- *     Sleepycat Software.  All rights reserved.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)db_os_lseek.c        10.3 (Sleepycat) 6/28/97";
-#endif /* not lint */
-
-#ifndef NO_SYSTEM_INCLUDES
-#include <sys/types.h>
-
-#include <errno.h>
-#include <unistd.h>
-#endif
-
-#include "db_int.h"
-#include "os_ext.h"
-
-/*
- * __db_lseek --
- *     Seek to a page/byte offset in the file.
- *
- * PUBLIC: int __db_lseek __P((int, size_t, db_pgno_t, u_long, int));
- */
-int
-__db_lseek(fd, pgsize, pageno, relative, whence)
-       int fd;
-       size_t pgsize;
-       db_pgno_t pageno;
-       u_long relative;
-       int whence;
-{
-       /* 64-bit offsets are done differently by different vendors. */
-#undef __LSEEK_SET
-#ifdef HAVE_LLSEEK
-#define        __LSEEK_SET
-       offset_t offset;                        /* Solaris. */
-
-       offset = pgsize * pageno + relative;
-       return (llseek(fd, offset, whence) == -1 ? errno : 0);
-#endif
-#ifdef HAVE_LSEEKI
-#define        __LSEEK_SET
-       __int64 offset;                         /* WNT */
-
-       offset = pgsize * pageno + relative;
-       return (_lseeki64(fd, offset, whence) == -1 ? errno : 0);
-#endif
-#ifndef        __LSEEK_SET
-       off_t offset;                           /* Default. */
-
-       offset = pgsize * pageno + relative;
-       return (lseek(fd, offset, whence) == -1 ? errno : 0);
-#endif
-}
diff --git a/db2/os/db_os_mmap.c b/db2/os/db_os_mmap.c
deleted file mode 100644 (file)
index 0cd8fad..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997
- *     Sleepycat Software.  All rights reserved.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)db_os_mmap.c 10.4 (Sleepycat) 6/28/97";
-#endif /* not lint */
-
-#ifndef NO_SYSTEM_INCLUDES
-#include <sys/types.h>
-#include <sys/mman.h>
-
-#include <errno.h>
-#endif
-
-#include "db_int.h"
-#include "os_ext.h"
-
-/*
- * __db_mmap --
- *     Map in some shared memory backed by a file descriptor.
- *
- * PUBLIC: int __db_mmap __P((int, size_t, int, int, void *));
- */
-int
-__db_mmap(fd, len, is_private, rdonly, addr)
-       int fd, is_private, rdonly;
-       size_t len;
-       void *addr;
-{
-#ifdef _WIN32
-       /* We have not implemented copy-on-write here */
-       void * pMemory = 0;
-       HANDLE hFile = (HANDLE)_get_osfhandle(fd);
-       HANDLE hMemory = CreateFileMapping(
-             hFile,
-             0,
-             (rdonly ? PAGE_READONLY : PAGE_READWRITE),
-             0,
-             len, /* This code fails if the library is ever compiled on a 64-bit machine */
-             0
-             );
-       if (NULL == hMemory)
-       {
-             return errno;
-       }
-       pMemory = MapViewOfFile(
-             hMemory,
-             (rdonly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS),
-             0,
-             0,
-             len
-             );
-       CloseHandle(hMemory);
-       *(void **)addr = pMemory;
-       return 0;
-
-#else /* !_WIN32 */
-
-       void *p;
-       int flags, prot;
-
-       flags = is_private ? MAP_PRIVATE : MAP_SHARED;
-#ifdef MAP_HASSEMAPHORE
-       flags += MAP_HASSEMAPHORE;
-#endif
-       prot = PROT_READ | (rdonly ? 0 : PROT_WRITE);
-
-#ifndef MAP_FAILED                     /* XXX: Mmap(2) failure return. */
-#define        MAP_FAILED      -1
-#endif
-       if ((p =
-           mmap(NULL, len, prot, flags, fd, (off_t)0)) == (void *)MAP_FAILED)
-               return (errno);
-
-       *(void **)addr = p;
-       return (0);
-#endif /* _WIN32 */
-}
-
-/*
- * __db_unmap --
- *     Release the specified shared memory.
- *
- * PUBLIC: int __db_munmap __P((void *, size_t));
- */
-int
-__db_munmap(addr, len)
-       void *addr;
-       size_t len;
-{
-       /*
-        * !!!
-        * The argument len is always the same length as was mapped.
-        */
-#ifdef _WIN32
-       return (!UnmapViewOfFile(addr) ? errno : 0);
-#else
-       return (munmap(addr, len) ? errno : 0);
-#endif
-}
diff --git a/db2/os/os_abs.c b/db2/os/os_abs.c
new file mode 100644 (file)
index 0000000..872e46d
--- /dev/null
@@ -0,0 +1,31 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997
+ *     Sleepycat Software.  All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)os_abs.c     10.7 (Sleepycat) 10/24/97";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#endif
+
+#include "db_int.h"
+
+/*
+ * __db_abspath --
+ *     Return if a path is an absolute path.
+ *
+ * PUBLIC: int __db_abspath __P((const char *));
+ */
+int
+__db_abspath(path)
+       const char *path;
+{
+       return (path[0] == '/');
+}
diff --git a/db2/os/os_dir.c b/db2/os/os_dir.c
new file mode 100644 (file)
index 0000000..10fb8b6
--- /dev/null
@@ -0,0 +1,100 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997
+ *     Sleepycat Software.  All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)os_dir.c     10.13 (Sleepycat) 10/28/97";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+#  include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+#  include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+#  include <ndir.h>
+# endif
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#endif
+
+#include "db_int.h"
+#include "common_ext.h"
+
+/*
+ * __os_dirlist --
+ *     Return a list of the files in a directory.
+ *
+ * PUBLIC: int __os_dirlist __P((const char *, char ***, int *));
+ */
+int
+__os_dirlist(dir, namesp, cntp)
+       const char *dir;
+       char ***namesp;
+       int *cntp;
+{
+       struct dirent *dp;
+       DIR *dirp;
+       int arraysz, cnt;
+       char **names;
+
+       if ((dirp = opendir(dir)) == NULL)
+               return (errno);
+       names = NULL;
+       for (arraysz = cnt = 0; (dp = readdir(dirp)) != NULL; ++cnt) {
+               if (cnt >= arraysz) {
+                       arraysz += 100;
+                       names = (char **)(names == NULL ?
+                           __db_malloc(arraysz * sizeof(names[0])) :
+                           __db_realloc(names, arraysz * sizeof(names[0])));
+                       if (names == NULL)
+                               goto nomem;
+               }
+               if ((names[cnt] = (char *)__db_strdup(dp->d_name)) == NULL)
+                       goto nomem;
+       }
+       (void)closedir(dirp);
+
+       *namesp = names;
+       *cntp = cnt;
+       return (0);
+
+nomem: if (names != NULL)
+               __os_dirfree(names, cnt);
+       return (ENOMEM);
+}
+
+/*
+ * __os_dirfree --
+ *     Free the list of files.
+ *
+ * PUBLIC: void __os_dirfree __P((char **, int));
+ */
+void
+__os_dirfree(names, cnt)
+       char **names;
+       int cnt;
+{
+       while (cnt > 0)
+               __db_free(names[--cnt]);
+       __db_free(names);
+}
similarity index 50%
rename from db2/os/db_os_fid.c
rename to db2/os/os_fid.c
index 960d580bad7286158a916416c5078902541e0b47..6820b887866423c6e28e3459222b2a12897e94ff 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_os_fid.c  10.8 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)os_fid.c     10.9 (Sleepycat) 10/24/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -22,8 +22,6 @@ static const char sccsid[] = "@(#)db_os_fid.c 10.8 (Sleepycat) 8/27/97";
 #endif
 
 #include "db_int.h"
-#include "db_page.h"
-#include "os_ext.h"
 #include "common_ext.h"
 
 /*
@@ -39,58 +37,11 @@ __db_fileid(dbenv, fname, timestamp, fidp)
        int timestamp;
        u_int8_t *fidp;
 {
+       struct stat sb;
        size_t i;
        time_t now;
        u_int8_t *p;
 
-#ifdef _WIN32
-       /*
-        * The documentation for GetFileInformationByHandle() states that the
-        * inode-type numbers are not constant between processes.  Actually,
-        * they are, they're the NTFS MFT indexes.  So, this works on NTFS,
-        * but perhaps not on other platforms, and perhaps not over a network.
-        * Can't think of a better solution right now.
-        */
-       int fd = 0;
-       HANDLE fh = 0;
-       BY_HANDLE_FILE_INFORMATION fi;
-       BOOL retval = FALSE;
-
-       /* Clear the buffer. */
-       memset(fidp, 0, DB_FILE_ID_LEN);
-
-       /* first we open the file, because we're not given a handle to it */
-       fd = open(fname,_O_RDONLY,_S_IREAD);
-       if (-1 == fd) {
-               /* If we can't open it, we're in trouble */
-               return (errno);
-       }
-
-       /* File open, get its info */
-       fh = (HANDLE)_get_osfhandle(fd);
-       if ((HANDLE)(-1) != fh) {
-               retval = GetFileInformationByHandle(fh,&fi);
-       }
-       close(fd);
-
-       /*
-        * We want the three 32-bit words which tell us the volume ID and
-        * the file ID.  We make a crude attempt to copy the bytes over to
-        * the callers buffer.
-        *
-        * DBDB: really we should ensure that the bytes get packed the same
-        * way on all compilers, platforms etc.
-        */
-       if ( ((HANDLE)(-1) != fh) && (TRUE == retval) ) {
-               memcpy(fidp, &fi.nFileIndexLow, sizeof(u_int32_t));
-               fidp += sizeof(u_int32_t);
-               memcpy(fidp, &fi.nFileIndexHigh, sizeof(u_int32_t));
-               fidp += sizeof(u_int32_t);
-               memcpy(fidp, &fi.dwVolumeSerialNumber, sizeof(u_int32_t));
-       }
-#else
-       struct stat sb;
-
        /* Clear the buffer. */
        memset(fidp, 0, DB_FILE_ID_LEN);
 
@@ -115,7 +66,7 @@ __db_fileid(dbenv, fname, timestamp, fidp)
        for (p = (u_int8_t *)&sb.st_dev +
            sizeof(sb.st_dev), i = 0; i < sizeof(sb.st_dev); ++i)
                *fidp++ = *--p;
-#endif
+
        if (timestamp) {
                (void)time(&now);
                for (p = (u_int8_t *)&now +
diff --git a/db2/os/os_fsync.c b/db2/os/os_fsync.c
new file mode 100644 (file)
index 0000000..7b001ce
--- /dev/null
@@ -0,0 +1,34 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997
+ *     Sleepycat Software.  All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)os_fsync.c   10.3 (Sleepycat) 10/25/97";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <errno.h>
+#include <unistd.h>
+#endif
+
+#include "db_int.h"
+
+/*
+ * __db_fsync --
+ *     Flush a file descriptor.
+ *
+ * PUBLIC: int __db_fsync __P((int));
+ */
+int
+__db_fsync(fd)
+       int fd;
+{
+       return (__os_fsync(fd) ? errno : 0);
+}
diff --git a/db2/os/os_func.c b/db2/os/os_func.c
new file mode 100644 (file)
index 0000000..afd40f4
--- /dev/null
@@ -0,0 +1,153 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997
+ *     Sleepycat Software.  All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)os_func.c    10.4 (Sleepycat) 10/28/97";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <errno.h>
+#endif
+
+#include "db_int.h"
+
+/*
+ * XXX
+ * We provide our own extern declarations so that we don't collide with
+ * systems that get them wrong, e.g., SunOS.
+ */
+#ifdef _WIN32
+#define fsync          _commit
+#define imported       __declspec(dllimport)
+#else
+#define imported
+#endif
+
+imported extern void    *calloc __P((size_t, size_t));
+imported extern int     close __P((int));
+imported extern void    free __P((void *));
+imported extern int     fsync __P((int));
+imported extern void    *malloc __P((size_t));
+imported extern int     open __P((const char *, int, ...));
+imported extern ssize_t         read __P((int, void *, size_t));
+imported extern char   *strdup __P((const char *));
+imported extern void    *realloc __P((void *, size_t));
+imported extern int     unlink __P((const char *));
+imported extern ssize_t         write __P((int, const void *, size_t));
+
+/*
+ * __db_jump --
+ *     This list of interfaces that applications can replace.  In some
+ *     cases, the user is permitted to replace the standard ANSI C or
+ *     POSIX 1003.1 call, e.g., calloc or read.  In others, we provide
+ *     a local interface to the functionality, e.g., __os_map.
+ */
+struct __db_jumptab __db_jump = {
+       calloc,                         /* DB_FUNC_CALLOC */
+       close,                          /* DB_FUNC_CLOSE */
+       __os_dirfree,                   /* DB_FUNC_DIRFREE */
+       __os_dirlist,                   /* DB_FUNC_DIRLIST */
+       __os_exists,                    /* DB_FUNC_EXISTS */
+       free,                           /* DB_FUNC_FREE */
+       fsync,                          /* DB_FUNC_FSYNC */
+       __os_ioinfo,                    /* DB_FUNC_IOINFO */
+       malloc,                         /* DB_FUNC_MALLOC */
+       __os_map,                       /* DB_FUNC_MAP */
+       open,                           /* DB_FUNC_OPEN */
+       read,                           /* DB_FUNC_READ */
+       realloc,                        /* DB_FUNC_REALLOC */
+       __os_seek,                      /* DB_FUNC_SEEK */
+       __os_sleep,                     /* DB_FUNC_SLEEP */
+       strdup,                         /* DB_FUNC_STRDUP */
+       unlink,                         /* DB_FUNC_UNLINK */
+       __os_unmap,                     /* DB_FUNC_UNMAP */
+       write,                          /* DB_FUNC_WRITE */
+       NULL                            /* DB_FUNC_YIELD */
+};
+
+/*
+ * db_jump_set --
+ *     Replace an interface.
+ */
+int
+db_jump_set(func, which)
+       void *func;
+       int which;
+{
+       switch (which) {
+       case DB_FUNC_CALLOC:
+               __db_calloc = (void *(*) __P((size_t, size_t)))func;
+               break;
+       case DB_FUNC_CLOSE:
+               __os_close = (int (*) __P((int)))func;
+               break;
+       case DB_FUNC_DIRFREE:
+               __db_dirfree = (void (*) __P((char **, int)))func;
+               break;
+       case DB_FUNC_DIRLIST:
+               __db_dirlist =
+                   (int (*) __P((const char *, char ***, int *)))func;
+               break;
+       case DB_FUNC_EXISTS:
+               __db_exists = (int (*) __P((const char *, int *)))func;
+               break;
+       case DB_FUNC_FREE:
+               __db_free = (void (*) __P((void *)))func;
+               break;
+       case DB_FUNC_FSYNC:
+               __os_fsync = (int (*) __P((int)))func;
+               break;
+       case DB_FUNC_IOINFO:
+               __db_ioinfo =
+                   (int (*) __P((const char *, int, off_t *, off_t *)))func;
+               break;
+       case DB_FUNC_MALLOC:
+               __db_malloc = (void *(*) __P((size_t)))func;
+               break;
+       case DB_FUNC_MAP:
+               __db_map = (int (*) __P((int, size_t, int, int, void **)))func;
+               break;
+       case DB_FUNC_OPEN:
+               __os_open = (int (*) __P((const char *, int, ...)))func;
+               break;
+       case DB_FUNC_READ:
+               __os_read = (ssize_t (*) __P((int, void *, size_t)))func;
+               break;
+       case DB_FUNC_REALLOC:
+               __db_realloc = (void *(*) __P((void *, size_t)))func;
+               break;
+       case DB_FUNC_SEEK:
+               __db_seek =
+                   (int (*) __P((int, size_t, db_pgno_t, u_long, int)))func;
+               break;
+       case DB_FUNC_SLEEP:
+               __db_sleep = (int (*) __P((u_long, u_long)))func;
+               break;
+       case DB_FUNC_STRDUP:
+               __db_strdup = (char *(*) __P((const char *)))func;
+               break;
+       case DB_FUNC_UNLINK:
+               __os_unlink = (int (*) __P((const char *)))func;
+               break;
+       case DB_FUNC_UNMAP:
+               __db_unmap = (int (*) __P((void *, size_t)))func;
+               break;
+       case DB_FUNC_WRITE:
+               __os_write = (ssize_t (*) __P((int, const void *, size_t)))func;
+               break;
+       case DB_FUNC_YIELD:
+               __db_yield = (int (*) __P((void)))func;
+               break;
+       default:
+               return (EINVAL);
+       }
+       return (0);
+}
diff --git a/db2/os/os_map.c b/db2/os/os_map.c
new file mode 100644 (file)
index 0000000..b155318
--- /dev/null
@@ -0,0 +1,71 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996, 1997
+ *     Sleepycat Software.  All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)os_map.c     10.7 (Sleepycat) 10/25/97";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <errno.h>
+#endif
+
+#include "db_int.h"
+
+/*
+ * __os_map --
+ *     Map in some shared memory backed by a file descriptor.
+ *
+ * PUBLIC: int __os_map __P((int, size_t, int, int, void **));
+ */
+int
+__os_map(fd, len, is_private, is_rdonly, addr)
+       int fd, is_private, is_rdonly;
+       size_t len;
+       void **addr;
+{
+       void *p;
+       int flags, prot;
+
+       flags = is_private ? MAP_PRIVATE : MAP_SHARED;
+#ifdef MAP_HASSEMAPHORE
+       flags |= MAP_HASSEMAPHORE;
+#endif
+       prot = PROT_READ | (is_rdonly ? 0 : PROT_WRITE);
+
+#ifndef MAP_FAILED                     /* XXX: Mmap(2) failure return. */
+#define        MAP_FAILED      -1
+#endif
+       if ((p =
+           mmap(NULL, len, prot, flags, fd, (off_t)0)) == (void *)MAP_FAILED)
+               return (errno);
+
+       *addr = p;
+       return (0);
+}
+
+/*
+ * __os_unmap --
+ *     Release the specified shared memory.
+ *
+ * PUBLIC: int __os_unmap __P((void *, size_t));
+ */
+int
+__os_unmap(addr, len)
+       void *addr;
+       size_t len;
+{
+       /*
+        * !!!
+        * The argument len is always the same length as was mapped.
+        */
+       return (munmap(addr, len) ? errno : 0);
+}
diff --git a/db2/os/os_oflags.c b/db2/os/os_oflags.c
new file mode 100644 (file)
index 0000000..3656eef
--- /dev/null
@@ -0,0 +1,48 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997
+ *     Sleepycat Software.  All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)os_oflags.c  10.2 (Sleepycat) 10/24/97";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <fcntl.h>
+#endif
+
+#include "db_int.h"
+
+/*
+ * __db_oflags --
+ *     Convert open(2) flags to DB flags.
+ *
+ * PUBLIC: int __db_oflags __P((int));
+ */
+int
+__db_oflags(oflags)
+       int oflags;
+{
+       int dbflags;
+
+       /*
+        * XXX
+        * Convert POSIX 1003.1 open(2) flags to DB flags.  Not an exact
+        * science as most POSIX implementations don't have a flag value
+        * for O_RDONLY, it's simply the lack of a write flag.
+        */
+       dbflags = 0;
+       if (oflags & O_CREAT)
+               dbflags |= DB_CREATE;
+       if (!(oflags & (O_RDWR | O_WRONLY)) || oflags & O_RDONLY)
+               dbflags |= DB_RDONLY;
+       if (oflags & O_TRUNC)
+               dbflags |= DB_TRUNCATE;
+       return (dbflags);
+}
similarity index 58%
rename from db2/os/db_os_open.c
rename to db2/os/os_open.c
index 1d67ef9508b68ba05e3d7dba93ec17062040dbef..05784e48100c4ff8679d4c225968db363d8c7346 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_os_open.c 10.14 (Sleepycat) 7/5/97";
+static const char sccsid[] = "@(#)os_open.c    10.19 (Sleepycat) 10/28/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -20,44 +20,15 @@ static const char sccsid[] = "@(#)db_os_open.c      10.14 (Sleepycat) 7/5/97";
 #endif
 
 #include "db_int.h"
-#include "os_ext.h"
 
 /*
- * __db_oflags --
- *     Convert open(2) flags to DB flags.
- *
- * PUBLIC: int __db_oflags __P((int));
- */
-int
-__db_oflags(oflags)
-       int oflags;
-{
-       int dbflags;
-
-       /*
-        * XXX
-        * Convert POSIX 1003.1 open(2) flags to DB flags.  Not an exact
-        * science as most POSIX implementations don't have a flag value
-        * for O_RDONLY, it's simply the lack of a write flag.
-        */
-       dbflags = 0;
-       if (oflags & O_CREAT)
-               dbflags |= DB_CREATE;
-       if (!(oflags & (O_RDWR | O_WRONLY)) || oflags & O_RDONLY)
-               dbflags |= DB_RDONLY;
-       if (oflags & O_TRUNC)
-               dbflags |= DB_TRUNCATE;
-       return (dbflags);
-}
-
-/*
- * __db_fdopen --
+ * __db_open --
  *     Open a file descriptor.
  *
- * PUBLIC: int __db_fdopen __P((const char *, int, int, int, int *));
+ * PUBLIC: int __db_open __P((const char *, int, int, int, int *));
  */
 int
-__db_fdopen(name, arg_flags, ok_flags, mode, fdp)
+__db_open(name, arg_flags, ok_flags, mode, fdp)
        const char *name;
        int arg_flags, ok_flags, mode, *fdp;
 {
@@ -95,13 +66,13 @@ __db_fdopen(name, arg_flags, ok_flags, mode, fdp)
                flags |= O_TRUNC;
 
        /* Open the file. */
-       if ((fd = open(name, flags, mode)) == -1)
+       if ((fd = __os_open(name, flags, mode)) == -1)
                return (errno);
 
 #ifndef _WIN32
        /* Delete any temporary file; done for Win32 by _O_TEMPORARY. */
        if (arg_flags & DB_TEMPORARY)
-               (void)unlink(name);
+               (void)__os_unlink(name);
 #endif
 
 #if !defined(_WIN32) && !defined(macintosh)
@@ -112,7 +83,7 @@ __db_fdopen(name, arg_flags, ok_flags, mode, fdp)
        if (fcntl(fd, F_SETFD, 1) == -1) {
                int ret = errno;
 
-               (void)__db_close(fd);
+               (void)__os_close(fd);
                return (ret);
        }
 #endif
@@ -120,19 +91,6 @@ __db_fdopen(name, arg_flags, ok_flags, mode, fdp)
        return (0);
 }
 
-/*
- * __db_fsync --
- *     Flush a file descriptor.
- *
- * PUBLIC: int __db_fsync __P((int));
- */
-int
-__db_fsync(fd)
-       int fd;
-{
-       return (fsync(fd) ? errno : 0);
-}
-
 /*
  * __db_close --
  *     Close a file descriptor.
@@ -143,5 +101,5 @@ int
 __db_close(fd)
        int fd;
 {
-       return (close(fd) ? errno : 0);
+       return (__os_close(fd) ? errno : 0);
 }
diff --git a/db2/os/os_rpath.c b/db2/os/os_rpath.c
new file mode 100644 (file)
index 0000000..44fd4ec
--- /dev/null
@@ -0,0 +1,42 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997
+ *     Sleepycat Software.  All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)os_rpath.c   10.2 (Sleepycat) 10/24/97";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <string.h>
+#endif
+
+#include "db_int.h"
+
+/*
+ * __db_rpath --
+ *     Return the last path separator in the path or NULL if none found.
+ *
+ * PUBLIC: char *__db_rpath __P((const char *));
+ */
+char *
+__db_rpath(path)
+       const char *path;
+{
+       const char *s, *last;
+
+       last = NULL;
+       if (PATH_SEPARATOR[1] != '\0') {
+               for (s = path; s[0] != '\0'; ++s)
+                       if (strchr(PATH_SEPARATOR, s[0]) != NULL)
+                               last = s;
+       } else
+               for (s = path; s[0] != '\0'; ++s)
+                       if (s[0] == PATH_SEPARATOR[0])
+                               last = s;
+       return ((char *)last);
+}
similarity index 85%
rename from db2/os/db_os_rw.c
rename to db2/os/os_rw.c
index 5a6c2196fd187df3d66ad0b7494c336d70af9d15..48f7fdc5b12e8c600788899a98e67699eafb7045 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_os_rw.c   10.4 (Sleepycat) 6/28/97";
+static const char sccsid[] = "@(#)os_rw.c      10.6 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -19,7 +19,6 @@ static const char sccsid[] = "@(#)db_os_rw.c  10.4 (Sleepycat) 6/28/97";
 #endif
 
 #include "db_int.h"
-#include "os_ext.h"
 
 /*
  * __db_read --
@@ -40,7 +39,7 @@ __db_read(fd, addr, len, nrp)
 
        for (taddr = addr,
            offset = 0; offset < len; taddr += nr, offset += nr) {
-               if ((nr = read(fd, taddr, len - offset)) < 0)
+               if ((nr = __os_read(fd, taddr, len - offset)) < 0)
                        return (errno);
                if (nr == 0)
                        break;
@@ -68,7 +67,7 @@ __db_write(fd, addr, len, nwp)
 
        for (taddr = addr,
            offset = 0; offset < len; taddr += nw, offset += nw)
-               if ((nw = write(fd, taddr, len - offset)) < 0)
+               if ((nw = __os_write(fd, taddr, len - offset)) < 0)
                        return (errno);
        *nwp = len;
        return (0);
diff --git a/db2/os/os_seek.c b/db2/os/os_seek.c
new file mode 100644 (file)
index 0000000..e27044b
--- /dev/null
@@ -0,0 +1,42 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997
+ *     Sleepycat Software.  All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)os_seek.c    10.6 (Sleepycat) 10/25/97";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <errno.h>
+#include <unistd.h>
+#endif
+
+#include "db_int.h"
+
+/*
+ * __os_seek --
+ *     Seek to a page/byte offset in the file.
+ *
+ * PUBLIC: int __os_seek __P((int, size_t, db_pgno_t, u_long, int));
+ */
+int
+__os_seek(fd, pgsize, pageno, relative, whence)
+       int fd;
+       size_t pgsize;
+       db_pgno_t pageno;
+       u_long relative;
+       int whence;
+{
+       off_t offset;
+
+       offset = pgsize * pageno + relative;
+
+       return (lseek(fd, offset, whence) == -1 ? errno : 0);
+}
similarity index 76%
rename from db2/os/db_os_sleep.c
rename to db2/os/os_sleep.c
index 5591789f51bb8127bd379a201a4e5dc750cd1c3c..2d2cb71f6d08bb952e91681c98f5c91eb43c446c 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_os_sleep.c        10.6 (Sleepycat) 6/28/97";
+static const char sccsid[] = "@(#)os_sleep.c   10.8 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -28,21 +28,18 @@ static const char sccsid[] = "@(#)db_os_sleep.c     10.6 (Sleepycat) 6/28/97";
 #endif
 
 #include "db_int.h"
-#include "os_ext.h"
 
 /*
- * __db_sleep --
+ * __os_sleep --
  *     Yield the processor for a period of time.
  *
- * PUBLIC: int __db_sleep __P((u_long, u_long));
+ * PUBLIC: int __os_sleep __P((u_long, u_long));
  */
 int
-__db_sleep(secs, usecs)
+__os_sleep(secs, usecs)
        u_long secs, usecs;             /* Seconds and microseconds. */
 {
-#ifndef _WIN32
        struct timeval t;
-#endif
 
        /* Don't require that the values be normalized. */
        for (; usecs >= 1000000; ++secs, usecs -= 1000000);
@@ -51,12 +48,7 @@ __db_sleep(secs, usecs)
         * It's important that we yield the processor here so that other
         * processes or threads are permitted to run.
         */
-#ifdef _WIN32
-       Sleep(secs * 1000 + usecs / 1000);
-       return (0);
-#else
        t.tv_sec = secs;
        t.tv_usec = usecs;
        return (select(0, NULL, NULL, NULL, &t) == -1 ? errno : 0);
-#endif
 }
similarity index 72%
rename from db2/os/db_os_stat.c
rename to db2/os/os_stat.c
index 7929b6b754f3478c24bf2c1f5a05f6b75ff1c67b..ee84ab0588cd04cf0508b2d825d485b980352c66 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_os_stat.c 10.6 (Sleepycat) 7/2/97";
+static const char sccsid[] = "@(#)os_stat.c    10.8 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -20,17 +20,16 @@ static const char sccsid[] = "@(#)db_os_stat.c      10.6 (Sleepycat) 7/2/97";
 #endif
 
 #include "db_int.h"
-#include "os_ext.h"
 #include "common_ext.h"
 
 /*
- * __db_exists --
+ * __os_exists --
  *     Return if the file exists.
  *
- * PUBLIC: int __db_exists __P((const char *, int *));
+ * PUBLIC: int __os_exists __P((const char *, int *));
  */
 int
-__db_exists(path, isdirp)
+__os_exists(path, isdirp)
        const char *path;
        int *isdirp;
 {
@@ -44,25 +43,22 @@ __db_exists(path, isdirp)
 }
 
 /*
- * __db_stat --
+ * __os_ioinfo --
  *     Return file size and I/O size; abstracted to make it easier
  *     to replace.
  *
- * PUBLIC: int __db_stat __P((DB_ENV *, const char *, int, off_t *, off_t *));
+ * PUBLIC: int __os_ioinfo __P((const char *, int, off_t *, off_t *));
  */
 int
-__db_stat(dbenv, path, fd, sizep, iop)
-       DB_ENV *dbenv;
+__os_ioinfo(path, fd, sizep, iop)
        const char *path;
        int fd;
        off_t *sizep, *iop;
 {
        struct stat sb;
 
-       if (fstat(fd, &sb) == -1) {
-               __db_err(dbenv, "%s: fstat: %s", path, strerror(errno));
+       if (fstat(fd, &sb) == -1)
                return (errno);
-       }
 
        /* Return the size of the file. */
        if (sizep != NULL)
similarity index 76%
rename from db2/os/db_os_unlink.c
rename to db2/os/os_unlink.c
index 872beba3cf60d837bf5887d6993f9cc62469df08..473ce77d395a0301dc7928fe6deb85d6dc6f6217 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)db_os_unlink.c       10.2 (Sleepycat) 6/28/97";
+static const char sccsid[] = "@(#)os_unlink.c  10.4 (Sleepycat) 10/28/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -19,7 +19,6 @@ static const char sccsid[] = "@(#)db_os_unlink.c      10.2 (Sleepycat) 6/28/97";
 #endif
 
 #include "db_int.h"
-#include "os_ext.h"
 
 /*
  * __db_unlink --
@@ -31,5 +30,5 @@ int
 __db_unlink(path)
        const char *path;
 {
-       return (unlink(path) == -1 ? errno : 0);
+       return (__os_unlink(path) == -1 ? errno : 0);
 }
index ec2b53dee7aa791add80906ab2a7cb4a560c09b6..473e5b9cb2210a1da2ed57ac69c88de2dfd7523a 100644 (file)
@@ -11,7 +11,7 @@
 static const char copyright[] =
 "@(#) Copyright (c) 1997\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_deadlock.c        10.15 (Sleepycat) 9/4/97";
+static const char sccsid[] = "@(#)db_deadlock.c        10.16 (Sleepycat) 10/14/97";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -53,13 +53,13 @@ main(argc, argv)
        DB_ENV *dbenv;
        u_int32_t atype;
        time_t now;
-       long seconds;
+       long usecs;
        int ch, flags, verbose;
        char *home, *logfile;
 
        atype = DB_LOCK_DEFAULT;
        home = logfile = NULL;
-       seconds = 0;
+       usecs = 0;
        flags = verbose = 0;
        while ((ch = getopt(argc, argv, "a:h:L:t:vw")) != EOF)
                switch (ch) {
@@ -85,7 +85,8 @@ main(argc, argv)
                        logfile = optarg;
                        break;
                case 't':
-                       get_long(optarg, 1, LONG_MAX, &seconds);
+                       get_long(optarg, 1, LONG_MAX, &usecs);
+                       usecs *= 1000000;
                        break;
                case 'v':
                        verbose = 1;
@@ -103,16 +104,17 @@ main(argc, argv)
        if (argc != 0)
                usage();
 
-       if (seconds == 0 && !LF_ISSET(DB_LOCK_CONFLICT)) {
+       if (usecs == 0 && !LF_ISSET(DB_LOCK_CONFLICT)) {
                warnx("at least one of -t and -w must be specified");
                usage();
        }
 
        /*
-        * We detect every second when we're running in DB_LOCK_CONFLICT mode.
+        * We detect every 100ms (100000 us) when we're running in
+        * DB_LOCK_CONFLICT mode.
         */
-       if (seconds == 0)
-               seconds = 1;
+       if (usecs == 0)
+               usecs = 100000;
 
        /* Initialize the deadlock detector by opening the lock manager. */
        dbenv = db_init(home, verbose);
@@ -125,14 +127,14 @@ main(argc, argv)
        while (!interrupted) {
                if (dbenv->db_verbose != 0) {
                        time(&now);
-                       __db_err(dbenv, "Running at %s", ctime(&now));
+                       __db_err(dbenv, "Running at %.24s", ctime(&now));
                }
 
                if ((errno = lock_detect(dbenv->lk_info, flags, atype)) != 0)
                        break;
 
-               /* Make a pass every "seconds" seconds. */
-               (void)__db_sleep(seconds, 0);
+               /* Make a pass every "usecs" usecs. */
+               (void)__db_sleep(0, usecs);
        }
 
        if (logfile != NULL)
index a0f60c69a60fcf4818696b4c26f98f0ab1c9db92..c09719059b4f0201cdb9795410564c2cbae95fae 100644 (file)
@@ -31,6 +31,8 @@ static const char sccsid[] = "@(#)db_dump.c   10.16 (Sleepycat) 8/27/97";
 #include "hash.h"
 #include "clib_ext.h"
 
+#undef stat
+
 void   configure __P((char *));
 DB_ENV *db_init __P((char *));
 void   dbt_dump __P((DBT *));
index a1ebfa8a112ff28a2613b8a27efab919fd4ce481..6597f10e10308d3c63e52304f9cb502624ba2afd 100644 (file)
@@ -11,7 +11,7 @@
 static const char copyright[] =
 "@(#) Copyright (c) 1997\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_load.c    10.13 (Sleepycat) 9/15/97";
+static const char sccsid[] = "@(#)db_load.c    10.14 (Sleepycat) 10/19/97";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -352,7 +352,7 @@ dbt_rprint(dbtp)
                                escape = 1;
                                continue;
                        }
-               if (++len >= dbtp->ulen - 10) {
+               if (len >= dbtp->ulen - 10) {
                        dbtp->ulen *= 2;
                        if ((dbtp->data =
                            (void *)realloc(dbtp->data, dbtp->ulen)) == NULL) {
@@ -361,6 +361,7 @@ dbt_rprint(dbtp)
                        }
                        p = (u_int8_t *)dbtp->data + len;
                }
+               ++len;
                *p++ = c1;
        }
        dbtp->size = len;
@@ -420,7 +421,7 @@ dbt_rdump(dbtp)
                }
                if ((c2 = getchar()) == EOF)
                        err(1, "unexpected end of key/data pair");
-               if (++len >= dbtp->ulen - 10) {
+               if (len >= dbtp->ulen - 10) {
                        dbtp->ulen *= 2;
                        if ((dbtp->data =
                            (void *)realloc(dbtp->data, dbtp->ulen)) == NULL) {
@@ -429,6 +430,7 @@ dbt_rdump(dbtp)
                        }
                        p = (u_int8_t *)dbtp->data + len;
                }
+               ++len;
                *p++ = digitize(c1) << 4 | digitize(c2);
        }
        dbtp->size = len;
index 55b9b49a795210b9dae7e19af6da839126ed1e52..5a39d320f88512180f98c6e44c0370ceb61fdf91 100644 (file)
@@ -11,7 +11,7 @@
 static const char copyright[] =
 "@(#) Copyright (c) 1997\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_recover.c 10.15 (Sleepycat) 9/21/97";
+static const char sccsid[] = "@(#)db_recover.c 10.16 (Sleepycat) 10/28/97";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -82,7 +82,7 @@ main(argc, argv)
                    (u_long)dbenv->tx_info->region->last_ckp.offset);
        }
 
-       exit (db_appexit(dbenv));
+       return (db_appexit(dbenv));
 }
 
 DB_ENV *
index 1a989f4df3732fdc7956ee44cefae28a7913dc8a..b1f1615fa9565d7521d77642960361930c8a2e87 100644 (file)
@@ -11,7 +11,7 @@
 static const char copyright[] =
 "@(#) Copyright (c) 1997\n\
        Sleepycat Software Inc.  All rights reserved.\n";
-static const char sccsid[] = "@(#)db_stat.c    8.20 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)db_stat.c    8.26 (Sleepycat) 11/2/97";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -29,18 +29,22 @@ static const char sccsid[] = "@(#)db_stat.c 8.20 (Sleepycat) 8/27/97";
 #include "db_int.h"
 #include "clib_ext.h"
 
+#undef stat
+
+#define        MB      1048576
 #define        DIVIDER "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
 
-typedef enum { T_NOTSET, T_DB, T_MPOOL, T_TXN } test_t;
+typedef enum { T_NOTSET, T_DB, T_LOG, T_MPOOL, T_TXN } test_t;
 
-void   bstat __P((DB *));
+void   btree_stats __P((DB *));
 DB_ENV *db_init __P((char *, test_t));
-void   hstat __P((DB *));
+void   hash_stats __P((DB *));
 int    main __P((int, char *[]));
-void   mstat __P((DB_ENV *));
+void   log_stats __P((DB_ENV *));
+void   mpool_stats __P((DB_ENV *));
 void   onint __P((int));
 void   prflags __P((u_int32_t, const FN *));
-void   tstat __P((DB_ENV *));
+void   txn_stats __P((DB_ENV *));
 int    txn_compare __P((const void *, const void *));
 void   usage __P((void));
 
@@ -63,7 +67,7 @@ main(argc, argv)
 
        ttype = T_NOTSET;
        db = home = NULL;
-       while ((ch = getopt(argc, argv, "d:h:mt")) != EOF)
+       while ((ch = getopt(argc, argv, "d:h:lmt")) != EOF)
                switch (ch) {
                case 'd':
                        db = optarg;
@@ -72,6 +76,9 @@ main(argc, argv)
                case 'h':
                        home = optarg;
                        break;
+               case 'l':
+                       ttype = T_LOG;
+                       break;
                case 'm':
                        ttype = T_MPOOL;
                        break;
@@ -100,10 +107,10 @@ main(argc, argv)
                switch (dbp->type) {
                case DB_BTREE:
                case DB_RECNO:
-                       bstat(dbp);
+                       btree_stats(dbp);
                        break;
                case DB_HASH:
-                       hstat(dbp);
+                       hash_stats(dbp);
                        break;
                case DB_UNKNOWN:
                        abort();                /* Impossible. */
@@ -111,11 +118,14 @@ main(argc, argv)
                }
                (void)dbp->close(dbp, 0);
                break;
+       case T_LOG:
+               log_stats(dbenv);
+               break;
        case T_MPOOL:
-               mstat(dbenv);
+               mpool_stats(dbenv);
                break;
        case T_TXN:
-               tstat(dbenv);
+               txn_stats(dbenv);
                break;
        case T_NOTSET:
                abort();                        /* Impossible. */
@@ -133,11 +143,11 @@ main(argc, argv)
 }
 
 /*
- * bstat --
+ * btree_stats --
  *     Display btree/recno statistics.
  */
 void
-bstat(dbp)
+btree_stats(dbp)
        DB *dbp;
 {
        static const FN fn[] = {
@@ -156,6 +166,8 @@ bstat(dbp)
     (t == 0 ? 0 :                                                      \
     (((double)((t * sp->bt_pagesize) - f) / (t * sp->bt_pagesize)) * 100))
 
+       printf("%#lx\tBtree magic number.\n", (u_long)sp->bt_magic);
+       printf("%lu\tBtree version number.\n", (u_long)sp->bt_version);
        prflags(sp->bt_flags, fn);
        if (dbp->type == DB_BTREE) {
 #ifdef NOT_IMPLEMENTED
@@ -213,22 +225,56 @@ printf("%lu\tNumber of bytes free in tree overflow pages (%.0f%% ff).\n",
 }
 
 /*
- * hstat --
+ * hash_stats --
  *     Display hash statistics.
  */
 void
-hstat(dbp)
+hash_stats(dbp)
        DB *dbp;
 {
        return;
 }
 
 /*
- * mstat --
+ * log_stats --
+ *     Display log statistics.
+ */
+void
+log_stats(dbenv)
+       DB_ENV *dbenv;
+{
+       DB_LOG_STAT *sp;
+
+       if (log_stat(dbenv->lg_info, &sp, NULL))
+               err(1, NULL);
+
+       printf("%#lx\tLog magic number.\n", (u_long)sp->st_magic);
+       printf("%lu\tLog version number.\n", (u_long)sp->st_version);
+       printf("%#o\tLog file mode.\n", sp->st_mode);
+       if (sp->st_lg_max % MB == 0)
+               printf("%luMb\tLog file size.\n", (u_long)sp->st_lg_max / MB);
+       else if (sp->st_lg_max % 1024 == 0)
+               printf("%luKb\tLog file size.\n", (u_long)sp->st_lg_max / 1024);
+       else
+               printf("%lu\tLog file size.\n", (u_long)sp->st_lg_max);
+       printf("%luMb\tLog bytes written (+%lu bytes).\n",
+           (u_long)sp->st_w_mbytes, (u_long)sp->st_w_bytes);
+       printf("%luMb\tLog bytes written since last checkpoint (+%lu bytes).\n",
+           (u_long)sp->st_wc_mbytes, (u_long)sp->st_wc_bytes);
+       printf("%lu\tTotal log file writes.\n", (u_long)sp->st_wcount);
+       printf("%lu\tTotal log file flushes.\n", (u_long)sp->st_scount);
+       printf("%lu\tThe number of region locks granted without waiting.\n",
+           (u_long)sp->st_region_nowait);
+       printf("%lu\tThe number of region locks granted after waiting.\n",
+           (u_long)sp->st_region_wait);
+}
+
+/*
+ * mpool_stats --
  *     Display mpool statistics.
  */
 void
-mstat(dbenv)
+mpool_stats(dbenv)
        DB_ENV *dbenv;
 {
        DB_MPOOL_FSTAT **fsp;
@@ -239,62 +285,75 @@ mstat(dbenv)
 
        printf("%lu\tCache size (%luK).\n",
            (u_long)gsp->st_cachesize, (u_long)gsp->st_cachesize / 1024);
-       printf("%lu\tRequested pages found in the cache", gsp->st_cache_hit);
+       printf("%lu\tRequested pages found in the cache",
+           (u_long)gsp->st_cache_hit);
        if (gsp->st_cache_hit + gsp->st_cache_miss != 0)
                printf(" (%.0f%%)", ((double)gsp->st_cache_hit /
                    (gsp->st_cache_hit + gsp->st_cache_miss)) * 100);
        printf(".\n");
        printf("%lu\tRequested pages mapped into the process' address space.\n",
-           gsp->st_map);
+           (u_long)gsp->st_map);
        printf("%lu\tRequested pages not found in the cache.\n",
-           gsp->st_cache_miss);
-       printf("%lu\tPages created in the cache.\n", gsp->st_page_create);
-       printf("%lu\tPages read into the cache.\n", gsp->st_page_in);
+           (u_long)gsp->st_cache_miss);
+       printf("%lu\tPages created in the cache.\n",
+           (u_long)gsp->st_page_create);
+       printf("%lu\tPages read into the cache.\n", (u_long)gsp->st_page_in);
        printf("%lu\tPages written from the cache to the backing file.\n",
-           gsp->st_page_out);
-       printf("%lu\tRead-only pages forced from the cache.\n",
-           gsp->st_ro_evict);
-       printf("%lu\tRead-write pages forced from the cache.\n",
-           gsp->st_rw_evict);
+           (u_long)gsp->st_page_out);
+       printf("%lu\tClean pages forced from the cache.\n",
+           (u_long)gsp->st_ro_evict);
+       printf("%lu\tDirty pages forced from the cache.\n",
+           (u_long)gsp->st_rw_evict);
+       printf("%lu\tDirty buffers written by trickle-sync thread.\n",
+           (u_long)gsp->st_page_trickle);
+       printf("%lu\tCurrent clean buffer count.\n",
+           (u_long)gsp->st_page_clean);
+       printf("%lu\tCurrent dirty buffer count.\n",
+           (u_long)gsp->st_page_dirty);
        printf("%lu\tNumber of hash buckets used for page location.\n",
-           gsp->st_hash_buckets);
+           (u_long)gsp->st_hash_buckets);
        printf("%lu\tTotal number of times hash chains searched for a page.\n",
-           gsp->st_hash_searches);
+           (u_long)gsp->st_hash_searches);
        printf("%lu\tThe longest hash chain searched for a page.\n",
-           gsp->st_hash_longest);
+           (u_long)gsp->st_hash_longest);
        printf(
            "%lu\tTotal number of hash buckets examined for page location.\n",
-           gsp->st_hash_examined);
+           (u_long)gsp->st_hash_examined);
+       printf("%lu\tThe number of region locks granted without waiting.\n",
+           (u_long)gsp->st_region_nowait);
+       printf("%lu\tThe number of region locks granted after waiting.\n",
+           (u_long)gsp->st_region_wait);
 
        for (; fsp != NULL && *fsp != NULL; ++fsp) {
                printf("%s\n", DIVIDER);
                printf("%s\n", (*fsp)->file_name);
                printf("%lu\tPage size.\n", (u_long)(*fsp)->st_pagesize);
                printf("%lu\tRequested pages found in the cache",
-                   (*fsp)->st_cache_hit);
+                   (u_long)(*fsp)->st_cache_hit);
                if ((*fsp)->st_cache_hit + (*fsp)->st_cache_miss != 0)
                        printf(" (%.0f%%)", ((double)(*fsp)->st_cache_hit /
                            ((*fsp)->st_cache_hit + (*fsp)->st_cache_miss)) *
                            100);
                printf(".\n");
        printf("%lu\tRequested pages mapped into the process' address space.\n",
-                   (*fsp)->st_map);
+                   (u_long)(*fsp)->st_map);
                printf("%lu\tRequested pages not found in the cache.\n",
-                   (*fsp)->st_cache_miss);
+                   (u_long)(*fsp)->st_cache_miss);
                printf("%lu\tPages created in the cache.\n",
-                   (*fsp)->st_page_create);
-               printf("%lu\tPages read into the cache.\n", (*fsp)->st_page_in);
+                   (u_long)(*fsp)->st_page_create);
+               printf("%lu\tPages read into the cache.\n",
+                   (u_long)(*fsp)->st_page_in);
        printf("%lu\tPages written from the cache to the backing file.\n",
-                   (*fsp)->st_page_out);
+                   (u_long)(*fsp)->st_page_out);
        }
 }
 
 /*
- * tstat --
+ * txn_stats --
  *     Display transaction statistics.
  */
 void
-tstat(dbenv)
+txn_stats(dbenv)
        DB_ENV *dbenv;
 {
        DB_TXN_STAT *tstat;
@@ -311,7 +370,7 @@ tstat(dbenv)
        p = tstat->st_pending_ckp.file == 0 ?
            "No pending checkpoint LSN." :
            "File/offset for last pending checkpoint LSN.";
-       printf("%lu/%lu\t%s.\n",
+       printf("%lu/%lu\t%s\n",
            (u_long)tstat->st_pending_ckp.file,
            (u_long)tstat->st_pending_ckp.offset, p);
        if (tstat->st_time_ckp == 0)
@@ -391,27 +450,58 @@ db_init(home, ttype)
        DB_ENV *dbenv;
        int flags;
 
+       if ((dbenv = (DB_ENV *)malloc(sizeof(DB_ENV))) == NULL) {
+               errno = ENOMEM;
+               err(1, NULL);
+       }
+
+       /*
+        * Try and use the shared regions when reporting statistics on the
+        * DB databases, so our information is as up-to-date as possible,
+        * even if the mpool cache hasn't been flushed.  If that fails, we
+        * turn off the DB_INIT_MPOOL flag and try again.
+        */
        flags = DB_USE_ENVIRON;
        switch (ttype) {
+       case T_DB:
        case T_MPOOL:
                flags |= DB_INIT_MPOOL;
                break;
+       case T_LOG:
+               flags |= DB_INIT_LOG;
+               break;
        case T_TXN:
                flags |= DB_INIT_TXN;
                break;
-       default:
-               break;
+       case T_NOTSET:
+               abort();
+               /* NOTREACHED */
        }
 
-       if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) {
-               errno = ENOMEM;
-               err(1, NULL);
+       /*
+        * If it works, we're done.  Set the error output options so that
+        * future errors are correctly reported.
+        */
+       memset(dbenv, 0, sizeof(*dbenv));
+       if ((errno = db_appinit(home, NULL, dbenv, flags)) == 0) {
+               dbenv->db_errfile = stderr;
+               dbenv->db_errpfx = progname;
+               return (dbenv);
        }
+
+       /* Turn off the DB_INIT_MPOOL flag if it's a database. */
+       if (ttype == T_DB)
+               flags &= ~DB_INIT_MPOOL;
+
+       /* Set the error output options -- this time we want a message. */
+       memset(dbenv, 0, sizeof(*dbenv));
        dbenv->db_errfile = stderr;
        dbenv->db_errpfx = progname;
 
+       /* Try again, and it's fatal if we fail. */
        if ((errno = db_appinit(home, NULL, dbenv, flags)) != 0)
                err(1, "db_appinit");
+
        return (dbenv);
 }
 
@@ -430,6 +520,6 @@ onint(signo)
 void
 usage()
 {
-       fprintf(stderr, "usage: db_stat [-mt] [-d file] [-h home]\n");
+       fprintf(stderr, "usage: db_stat [-mlt] [-d file] [-h home]\n");
        exit (1);
 }
index 9a0d626c3ef5f293860418cd8c582c2391f7c026..55423f04700b14b7d1303c8dc2c3948056d5f395 100644 (file)
@@ -43,7 +43,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)txn.c        10.30 (Sleepycat) 9/23/97";
+static const char sccsid[] = "@(#)txn.c        10.35 (Sleepycat) 11/2/97";
 #endif /* not lint */
 
 
@@ -187,7 +187,7 @@ retry1:     if ((ret = __db_ropen(dbenv, DB_APP_NONE, path, DEFAULT_TXN_FILE,
        }
 
        /* Now, create the transaction manager structure and set its fields. */
-       if ((tmgrp = (DB_TXNMGR *)malloc(sizeof(DB_TXNMGR))) == NULL) {
+       if ((tmgrp = (DB_TXNMGR *)__db_malloc(sizeof(DB_TXNMGR))) == NULL) {
                __db_err(dbenv, "txn_open: %s", strerror(ENOMEM));
                ret = ENOMEM;
                goto out;
@@ -205,7 +205,7 @@ retry1:     if ((ret = __db_ropen(dbenv, DB_APP_NONE, path, DEFAULT_TXN_FILE,
        TAILQ_INIT(&tmgrp->txn_chain);
        if (LF_ISSET(DB_THREAD)) {
                LOCK_TXNREGION(tmgrp);
-               if ((ret = __db_shalloc(tmgrp->mem, sizeof(db_mutex_t), 
+               if ((ret = __db_shalloc(tmgrp->mem, sizeof(db_mutex_t),
                    MUTEX_ALIGNMENT, &tmgrp->mutexp)) == 0)
                        __db_mutex_init(tmgrp->mutexp, -1);
                UNLOCK_TXNREGION(tmgrp);
@@ -225,7 +225,7 @@ out:        if (txn_regionp != NULL)
                        __db_shalloc_free(tmgrp->mem, tmgrp->mutexp);
                        UNLOCK_TXNREGION(tmgrp);
                }
-               free(tmgrp);
+               __db_free(tmgrp);
        }
        return (ret);
 }
@@ -254,7 +254,7 @@ txn_begin(tmgrp, parent, txnpp)
        if ((ret = __db_shalloc(tmgrp->mem, sizeof(TXN_DETAIL), 0, &txnp)) != 0
            && ret == ENOMEM && (ret = __txn_grow_region(tmgrp)) == 0)
                ret = __db_shalloc(tmgrp->mem, sizeof(TXN_DETAIL), 0, &txnp);
-               
+
        if (ret != 0)
                goto err;
 
@@ -262,7 +262,7 @@ txn_begin(tmgrp, parent, txnpp)
        if (tmgrp->region->last_txnid == TXN_INVALID)
                return (EINVAL);
 
-       if ((retp = (DB_TXN *)malloc(sizeof(DB_TXN))) == NULL) {
+       if ((retp = (DB_TXN *)__db_malloc(sizeof(DB_TXN))) == NULL) {
                __db_err(tmgrp->dbenv, "txn_begin : %s", strerror(ENOMEM));
                ret = ENOMEM;
                goto err1;
@@ -297,7 +297,7 @@ txn_begin(tmgrp, parent, txnpp)
                    txnp, links, __txn_detail);
                __db_shalloc_free(tmgrp->mem, txnp);
                UNLOCK_TXNREGION(tmgrp);
-               free (retp);
+               __db_free(retp);
                return (ret);
        }
 
@@ -433,7 +433,7 @@ txn_close(tmgrp)
                ret = t_ret;
 
        if (ret == 0)
-               free (tmgrp);
+               __db_free(tmgrp);
 
        return (ret);
 }
@@ -561,7 +561,7 @@ __txn_undo(txnp)
                        ret =
                            mgr->recover(logp, &rdbt, &key_lsn, TXN_UNDO, NULL);
                        if (F_ISSET(logp, DB_AM_THREAD) && rdbt.data != NULL) {
-                               free(rdbt.data);
+                               __db_free(rdbt.data);
                                rdbt.data = NULL;
                        }
                }
@@ -590,7 +590,7 @@ txn_checkpoint(mgr, kbytes, minutes)
        TXN_DETAIL *txnp;
        DB_LSN ckp_lsn, last_ckp;
        DB_LOG *dblp;
-       u_int32_t bytes_written;
+       u_int32_t kbytes_written;
        time_t last_ckp_time, now;
        int ret;
 
@@ -616,10 +616,12 @@ txn_checkpoint(mgr, kbytes, minutes)
        if (kbytes != 0) {
                dblp = mgr->dbenv->lg_info;
                LOCK_LOGREGION(dblp);
-               bytes_written = dblp->lp->written;
+               kbytes_written =
+                   dblp->lp->stat.st_wc_mbytes * 1024 +
+                   dblp->lp->stat.st_wc_bytes / 1024;
                ckp_lsn = dblp->lp->lsn;
                UNLOCK_LOGREGION(dblp);
-               if (bytes_written >= (u_int32_t)(kbytes * 1024))
+               if (kbytes_written >= (u_int32_t)kbytes)
                        goto do_ckp;
        }
 
@@ -726,12 +728,14 @@ __txn_grow_region(tp)
        DB_TXNMGR *tp;
 {
        size_t incr;
+       off_t mutex_offset;
        u_int32_t oldmax;
        u_int8_t *curaddr;
        int ret;
 
        oldmax = tp->region->maxtxns;
        incr = oldmax * sizeof(DB_TXN);
+       mutex_offset = (u_int8_t *)tp->mutexp - (u_int8_t *)tp->region;
 
        if ((ret = __db_rgrow(tp->dbenv, tp->fd, incr)) != 0)
                return (ret);
@@ -744,6 +748,7 @@ __txn_grow_region(tp)
        curaddr = (u_int8_t *)tp->region + tp->reg_size;
        tp->mem = &tp->region[1];
        tp->reg_size += incr;
+       tp->mutexp = (db_mutex_t *)((u_int8_t *)tp->region + mutex_offset);
 
        *((size_t *)curaddr) = incr - sizeof(size_t);
        curaddr += sizeof(size_t);
@@ -776,7 +781,7 @@ txn_stat(mgr, statp, db_malloc)
         */
        nbytes = sizeof(DB_TXN_STAT) + sizeof(DB_TXN_ACTIVE) * (nactive + 200);
        if (db_malloc == NULL)
-               stats = (DB_TXN_STAT *)malloc(nbytes);
+               stats = (DB_TXN_STAT *)__db_malloc(nbytes);
        else
                stats = (DB_TXN_STAT *)db_malloc(nbytes);
 
index baef7333c7b36de6ee222f2889da7292110162c1..9edbc03eab87b3d5e142d6689bf7f6a2061f547f 100644 (file)
@@ -46,7 +46,7 @@ int __txn_regop_log(logp, txnid, ret_lsnp, flags,
                lsnp = &txnid->last_lsn;
        logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
            + sizeof(opcode);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -65,7 +65,7 @@ int __txn_regop_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -103,7 +103,7 @@ __txn_regop_print(notused1, dbtp, lsnp, notused3, notused4)
            (u_long)argp->prev_lsn.offset);
        printf("\topcode: %lu\n", (u_long)argp->opcode);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -118,7 +118,7 @@ __txn_regop_read(recbuf, argpp)
        __txn_regop_args *argp;
        u_int8_t *bp;
 
-       argp = (__txn_regop_args *)malloc(sizeof(__txn_regop_args) +
+       argp = (__txn_regop_args *)__db_malloc(sizeof(__txn_regop_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
@@ -167,7 +167,7 @@ int __txn_ckp_log(logp, txnid, ret_lsnp, flags,
        logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
            + sizeof(*ckp_lsn)
            + sizeof(*last_ckp);
-       if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+       if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
                return (ENOMEM);
 
        bp = logrec.data;
@@ -194,7 +194,7 @@ int __txn_ckp_log(logp, txnid, ret_lsnp, flags,
        ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
        if (txnid != NULL)
                txnid->last_lsn = *ret_lsnp;
-       free(logrec.data);
+       __db_free(logrec.data);
        return (ret);
 }
 
@@ -235,7 +235,7 @@ __txn_ckp_print(notused1, dbtp, lsnp, notused3, notused4)
        printf("\tlast_ckp: [%lu][%lu]\n",
            (u_long)argp->last_ckp.file, (u_long)argp->last_ckp.offset);
        printf("\n");
-       free(argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -250,7 +250,7 @@ __txn_ckp_read(recbuf, argpp)
        __txn_ckp_args *argp;
        u_int8_t *bp;
 
-       argp = (__txn_ckp_args *)malloc(sizeof(__txn_ckp_args) +
+       argp = (__txn_ckp_args *)__db_malloc(sizeof(__txn_ckp_args) +
            sizeof(DB_TXN));
        if (argp == NULL)
                return (ENOMEM);
index c172d874d978432ec7432b72718e5e41853fe19f..679cffb567c0af9fb576c21f1bd2c7e69da5010b 100644 (file)
@@ -40,7 +40,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)txn_rec.c    10.5 (Sleepycat) 8/27/97";
+static const char sccsid[] = "@(#)txn_rec.c    10.6 (Sleepycat) 10/25/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -97,7 +97,7 @@ __txn_regop_recover(logp, dbtp, lsnp, redo, info)
        }
 
        *lsnp = argp->prev_lsn;
-       free (argp);
+       __db_free(argp);
        return (0);
 }
 
@@ -126,6 +126,6 @@ __txn_ckp_recover(logp, dbtp, lsnp, redo, info)
                return (ret);
 
        *lsnp = argp->last_ckp;
-       free(argp);
+       __db_free(argp);
        return (DB_TXN_CKP);
 }
index 37a526069ffc7fddac22f8c7800d27fea49e837f..be9bdd0c42361bd8abac617169066289019eb080 100644 (file)
@@ -1 +1,13 @@
 #include <io/sys/stat.h>
+
+/* The `stat', `fstat', `lstat' functions have to be handled special since
+   even while not compiling the library with optimization calls to these
+   functions in the shared library must reference the `xstat' etc functions.
+   We have to use macros but we cannot define them in the normal headers
+   since on user level we must use real functions.  */
+#define stat(fname, buf) __xstat (_STAT_VER, fname, buf)
+#define fstat(fd, buf) __fxstat (_STAT_VER, fd, buf)
+#define lstat(fname, buf)  __lxstat (_STAT_VER, fname, buf)
+#define stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf)
+#define fstat64(fd, buf) __fxstat64 (_STAT_VER, fd, buf)
+#define lstat64(fname, buf)  __lxstat64 (_STAT_VER, fname, buf)
index f342239db9020d60454238c71c6bd5b48bdea550..503da847a0529bc7aeb2b28f489fdb7e34e75981 100644 (file)
@@ -36,6 +36,7 @@
 #ifndef _PROTOCOLS_ROUTED_H
 #define        _PROTOCOLS_ROUTED_H 1
 
+#include <sys/socket.h>
 /*
  * Routing Information Protocol
  *
index 5bec984d1fdea3003662c9714bfb2d22b752c306..fa22b43bda851b2ddd9a3700636668107dbd4e35 100644 (file)
@@ -55,6 +55,7 @@
  */
 
 #include <sys/types.h>
+#include <sys/socket.h>
 
 /*
  * Client->server request message format.
index a2c9fb8ce458ce13b627e23d8855c31124f266e4..dc880ab3257af4e3bbcaf49398c9585c3fa3c23d 100644 (file)
@@ -36,6 +36,8 @@
 #ifndef        _PROTOCOLS_TIMED_H
 #define        _PROTOCOLS_TIMED_H 1
 
+#include <rpc/types.h>
+
 /*
  * Time Synchronization Protocol
  */
index df558daa5819be9d299272b175e1b4a06f48faa2..45e60d6b32e95f3689fe0985b92a6b541ffafd1e 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -36,6 +36,7 @@
    functions in the shared library can adapt without needing to recompile
    all callers.  */
 
+#undef fstat
 int
 __fstat (int fd, struct stat *buf)
 {
index 376a262a106cfa56da48dacef11f807a7825d489..2d677a15eded5aa6533d624e837d7fd513ce0e44 100644 (file)
@@ -36,6 +36,7 @@
    functions in the shared library can adapt without needing to recompile
    all callers.  */
 
+#undef fstat64
 int
 fstat64 (int fd, struct stat64 *buf)
 {
index 255c53f5291128a0e4935f1ae6c343c90e5cb21b..2ddb295c0365afb7560d72889eb7e867f0af730d 100644 (file)
--- a/io/fts.c
+++ b/io/fts.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)fts.c     8.2 (Berkeley) 1/2/94";
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
-#include <sys/stat.h>
+#include <include/sys/stat.h>
 #include <fcntl.h>
 #include <dirent.h>
 #include <errno.h>
index a7b537f446a453b246b4acb4f32f300789d23485..b8c82fa969c189985e117818280aff3f026e95a2 100644 (file)
--- a/io/ftw.c
+++ b/io/ftw.c
@@ -26,7 +26,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/param.h>
-#include <sys/stat.h>
+#include <include/sys/stat.h>
 
 /* #define NDEBUG 1 */
 #include <assert.h>
index 508c850d4b33a9888133e41b4dbb6fddf00c6b70..0ae6ecd51aedecb85bc3d7218b25273ac3df506c 100644 (file)
@@ -108,8 +108,7 @@ LD_LIBRARY_PATH=$objpfx $ldso $testprogram --chdir $tmpdir |
     sort > $testout
 
 # perhaps $tmp involves some symlinks...
-pwdprogram=`which pwd`
-tmpreal=`( cd $tmp ; $pwdprogram )`
+tmpreal=`cd $tmp; /bin/pwd 2>/dev/null || /usr/bin/pwd`
 
 cat <<EOF | cmp $testout - || exit 1
 base = "$tmp/", file = "ftwtest.d", flag = FTW_D, cwd = $tmpreal, level = 0
index 6823fafcb26dc0876d8aae7cb20db3b896813934..cc6dd9545cd0589a07dbc3889bd4b20d6a6491d1 100644 (file)
@@ -17,7 +17,7 @@
    Boston, MA 02111-1307, USA.  */
 
 #include <unistd.h>
-#include <sys/stat.h>
+#include <include/sys/stat.h>
 #include <stdlib.h>
 #include <string.h>
 
index 9510eac23777364b47cabdce7e93c34c8f533183..7ad7b90d4c5a799ef5f2ad903bbee2b9efc9fcf1 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -36,6 +36,7 @@
    functions in the shared library can adapt without needing to recompile
    all callers.  */
 
+#undef lstat
 int
 __lstat (const char *file, struct stat *buf)
 {
index ef2b15691721d3ff5a0a0ad7b1d7293877ec6221..079b3fa28a84fa649e65cf8662af14d7b44d7880 100644 (file)
@@ -36,6 +36,7 @@
    functions in the shared library can adapt without needing to recompile
    all callers.  */
 
+#undef lstat64
 int
 lstat64 (const char *file, struct stat64 *buf)
 {
index c4d1f53257745f8dd8160d8c7afac8074191fee7..b3631e32c7fb8b8956a6c0b5a03d91b9968caeee 100644 (file)
--- a/io/stat.c
+++ b/io/stat.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -36,6 +36,7 @@
    functions in the shared library can adapt without needing to recompile
    all callers.  */
 
+#undef stat
 int
 __stat (const char *file, struct stat *buf)
 {
index 09eb38ae9165dca4160366db76de628153bab665..16b0b11052e3f917bc07b4714773a1c3f5ae90a1 100644 (file)
@@ -36,6 +36,7 @@
    functions in the shared library can adapt without needing to recompile
    all callers.  */
 
+#undef stat64
 int
 stat64 (const char *file, struct stat64 *buf)
 {
index 2e9e62ad61fef879b18dc8fe880aa2567f8cdbb6..7c91f6f6de15975d9af6bd7e6dad2e1339b2b744 100644 (file)
@@ -57,9 +57,9 @@
 #  include <sys/cdefs.h>
 # else
 #  ifdef __STDC__
-#   define __P(protos) protos
+#   define __P(p) p
 #  else
-#   define __P(protos) ()
+#   define __P(p) ()
 #  endif
 # endif
 #endif /*!__P*/
index da796ecbe43a9001370a8e3a8e9dc8893aa0e33e..5ba8a30da609c3b4e506044acb9849072fa97592 100644 (file)
@@ -189,13 +189,16 @@ extern int fcloseall __P ((void));
 
 /* Open a file and create a new stream for it.  */
 #ifndef __USE_FILE_OFFSET64
-extern FILE *fopen __P ((__const char *__filename, __const char *__modes));
+extern FILE *fopen __P ((__const char *__restrict __filename,
+                        __const char *__restrict __modes));
 #else
-extern FILE *fopen __P ((__const char *__filename, __const char *__modes))
+extern FILE *fopen __P ((__const char *__restrict __filename,
+                        __const char *__restrict __modes))
      __asm__ ("fopen64");
 #endif
 #ifdef __USE_LARGEFILE64
-extern FILE *fopen64 __P ((__const char *__filename, __const char *__modes));
+extern FILE *fopen64 __P ((__const char *__restrict __filename,
+                          __const char *__restrict __modes));
 #endif
 /* Open a file, replacing an existing stream with it. */
 #ifndef __USE_FILE_OFFSET64
index 31d638c2a263bfd7fdfd19c344c6397a74a9ec36..d0863f98dfe02b5609c06e247dd254491e0c72aa 100644 (file)
@@ -41,15 +41,15 @@ these situations.  There is a special value for infinity.
 @comment math.h
 @comment ISO
 @deftypevr Macro float_t INFINITY
-A expression representing the infinite value.  @code{INFINITY} values are
-produce by mathematical operations like @code{1.0 / 0.0}.  It is
+An expression representing the infinite value.  @code{INFINITY} values are
+produced by mathematical operations like @code{1.0 / 0.0}.  It is
 possible to continue the computations with this value since the basic
 operations as well as the mathematical library functions are prepared to
 handle values like this.
 
 Beside @code{INFINITY} also the value @code{-INFINITY} is representable
 and it is handled differently if needed.  It is possible to test a
-variables for infinite value using a simple comparison but the
+value for infiniteness using a simple comparison but the
 recommended way is to use the the @code{isinf} function.
 
 This macro was introduced in the @w{ISO C 9X} standard.
@@ -357,7 +357,8 @@ cut along the negative real axis.
 @deftypefunx {complex long double} cprojl (complex long double @var{z})
 Return the projection of the complex value @var{z} on the Riemann
 sphere.  Values with a infinite complex part (even if the real part
-is NaN) are projected to positive infinite on the real axis.  If the real part is infinite, the result is equivalent to
+is NaN) are projected to positive infinite on the real axis.  If the
+real part is infinite, the result is equivalent to
 
 @smallexample
 INFINITY + I * copysign (0.0, cimag (z))
@@ -1060,13 +1061,13 @@ format supports this; and to the largest representable value otherwise.
 If the input string is @code{"nan"} or
 @code{"nan(@var{n-char-sequence})"} the return value of @code{strtod} is
 the representation of the NaN (not a number) value (if the
-floating-point formats supports this.  The form with the
-@var{n-char-sequence} enables in an implementation specific way to
-specify the form of the NaN value.  When using the @w{IEEE 754}
+floating-point format supports this).  In the second form the part
+@var{n-char-sequence} allows to specify the form of the NaN value in an
+implementation specific way.  When using the @w{IEEE 754}
 floating-point format, the NaN value can have a lot of forms since only
 at least one bit in the mantissa must be set.  In the GNU C library
 implementation of @code{strtod} the @var{n-char-sequence} is interpreted
-as a number (as recognized by @code{strtol}, @pxref{Parsing of Integers})
+as a number (as recognized by @code{strtol}, @pxref{Parsing of Integers}).
 The mantissa of the return value corresponds to this given number.
 
 Since the value zero which is returned in the error case is also a valid
index 2b97dfbf66b8b02d8df3b0797b93f09cb91bfe45..8e8db4a88a19365ee138257b515a1672f9995b5b 100644 (file)
@@ -75,7 +75,7 @@ Returns true if @var{c} is an alphabetic character (a letter).  If
 @code{isalpha} is also true.
 
 In some locales, there may be additional characters for which
-@code{isalpha} is true--letters which are neither upper case nor lower
+@code{isalpha} is true---letters which are neither upper case nor lower
 case.  But in the standard @code{"C"} locale, there are no such
 additional characters.
 @end deftypefun
index 6d4185b52c0c2fafd16e0d3fc1074fd449fc9965..e2a6b34ae200d8c58a0182c587c3144b4f5f2e4c 100644 (file)
@@ -189,14 +189,14 @@ build the GNU C library:
 
 @itemize @bullet
 @item
-@code{make} 3.76.1
+@code{make} 3.75
 
 You need the latest version of GNU @code{make}.  Modifying the GNU C
 Library to work with other @code{make} programs would be so hard that we
 recommend you port GNU @code{make} instead.  @strong{Really.}  We
-recommend version GNU @code{make} version 3.75, 3.76.1 or later.
-Version 3.76 is known to have a bug which only shows up in big projects
-like GNU @code{libc}.
+recommend version GNU @code{make} version 3.75.  Versions 3.76 and
+3.76.1 are known to have bugs which only show up in big projects like
+GNU @code{libc}.
 
 @item
 GCC 2.7.2.3
@@ -538,11 +538,11 @@ include the file @code{<stub-tag.h>} into your file.  This causes the
 function to be listed in the installed @code{<gnu/stubs.h>}, and
 makes GNU ld warn when the function is used.
 
-Some rare functions are only useful on specific systems and
-aren't defined at all on others; these do not appear anywhere
-in the system-independent source code or makefiles (including the
-@file{generic}), only in the system-dependent @file{Makefile} in the
-specific system's subdirectory.
+Some rare functions are only useful on specific systems and aren't
+defined at all on others; these do not appear anywhere in the
+system-independent source code or makefiles (including the
+@file{generic} directory), only in the system-dependent @file{Makefile}
+in the specific system's subdirectory.
 
 If you come across a file that is in one of the main source directories
 (@file{string}, @file{stdio}, etc.), and you want to write a machine- or
index 0fc5e81c759733a30a5c581726b393adfa8803c4..bd5658dd67de8771e6c60f83b8ceb905dc710d83 100644 (file)
@@ -477,7 +477,7 @@ is easily available non-directories will be rejected but no extra
 work will be done to determine the information for each file.  I.e.,
 the caller must still be able to filter directories out.
 
-This functionality is only available witht eh GNU @code{glob}
+This functionality is only available with the GNU @code{glob}
 implementation.  It is mainly used internally to increase the
 performance but might be useful for a user as well and therefore is
 documented here.
index 43230154f61513994d1c59b2d5f347f3eb95178f..56edf2d24c7a8905cb89d652054b478ff80f307d 100644 (file)
@@ -62,6 +62,10 @@ possible to create the shell process, and otherwise is the status of the
 shell process.  @xref{Process Completion}, for details on how this
 status code can be interpreted.
 
+If the @var{command} argument is a null pointer a non-zero return value
+indicates that a command processor is available and this function can be
+used at all.
+
 This function is a cancelation point in multi-threaded programs.  This
 is a problem if the thread allocates some resources (like memory, file
 descriptors, semaphores or whatever) at the time @code{system} is
index 96c3de4fec7d8272b91ae2eef05b38d285fe58fe..40d9f227b48e239e36a14b5191c2f29a093ec82d 100644 (file)
@@ -1140,6 +1140,13 @@ promotions.  For arguments of other integer types, you can use these
 modifiers:
 
 @table @samp
+@item hh
+Specifies that the argument is a @code{signed char} or @code{unsigned
+char}, as appropriate.  A @code{char} argument is converted to an
+@code{int} or @code{unsigned int} by the default argument promotions
+anyway, but the @samp{h} modifier says to convert it back to a
+@code{char} again.
+
 @item h
 Specifies that the argument is a @code{short int} or @code{unsigned
 short int}, as appropriate.  A @code{short} argument is converted to an
@@ -2596,6 +2603,10 @@ other integer conversions.  You can use the following type modifiers to
 specify other sizes of integer:
 
 @table @samp
+@item hh
+Specifies that the argument is a @code{signed char *} or @code{unsigned
+char *}.
+
 @item h
 Specifies that the argument is a @code{short int *} or @code{unsigned
 short int *}.
index ea62e26447b9001252873ea17b614a4b9f0586ca..0417a63bd8fa9b358247b37dc6b98ab5af4ceaaf 100644 (file)
@@ -1111,8 +1111,8 @@ the only speeds that typical serial lines can support.
 @smallexample
 B0  B50  B75  B110  B134  B150  B200
 B300  B600  B1200  B1800  B2400  B4800
-B9600  B19200  B38400 B57600 B115200
-B230400 B460800
+B9600  B19200  B38400  B57600  B115200
+B230400  B460800
 @end smallexample
 
 @vindex EXTA
index fe4c4ce5450247a4ab3631a008be97e6fdf585fe..f4b1d4640c1070b7b9fa10183767573e3352531e 100644 (file)
@@ -38,7 +38,7 @@ __BEGIN_DECLS
 /* Narrowest imaginary unit.  This depends on the floating-point
    evaluation method.
    XXX This probably has to go into a gcc related file.  */
-#define _Imaginary_I   (1.0iF)
+#define _Complex_I     (1.0iF)
 
 /* Another more descriptive name is `I'.  */
 #undef I
index c80ed7d2619da146ab061a52e495dd883f7d551c..c77cbee85555392a510c4288f410bf4cc5a689ab 100644 (file)
@@ -856,6 +856,8 @@ asin_test (void)
 #endif
 
   check ("asin (0) == 0", FUNC(asin) (0), 0);
+  check ("asin (0.5) ==  pi/6", FUNC(asin) (0.5), M_PI_6);
+  check ("asin (1.0) ==  pi/2", FUNC(asin) (1.0), M_PI_2);
 }
 
 
@@ -2297,6 +2299,7 @@ sqrt_test (void)
   x = random_value (0, 10000);
   check_ext ("sqrt (x*x) == x", FUNC(sqrt) (x*x), x, x);
   check ("sqrt (4) == 2", FUNC(sqrt) (4), 2);
+  check ("sqrt (0.25) == 0.5", FUNC(sqrt) (0.25), 0.5);
 
 }
 
@@ -4638,16 +4641,16 @@ lrint_test (void)
      the rounding method and test the critical cases.  So far, only
      unproblematic numbers are tested.  */
 
-  check_long ("lrint(0) = 0", lrint (0.0), 0);
-  check_long ("lrint(-0) = 0", lrint (minus_zero), 0);
-  check_long ("lrint(0.2) = 0", lrint (0.2), 0);
-  check_long ("lrint(-0.2) = 0", lrint (-0.2), 0);
+  check_long ("lrint(0) = 0", FUNC(lrint) (0.0), 0);
+  check_long ("lrint(-0) = 0", FUNC(lrint) (minus_zero), 0);
+  check_long ("lrint(0.2) = 0", FUNC(lrint) (0.2), 0);
+  check_long ("lrint(-0.2) = 0", FUNC(lrint) (-0.2), 0);
 
-  check_long ("lrint(1.4) = 1", lrint (1.4), 1);
-  check_long ("lrint(-1.4) = -1", lrint (-1.4), -1);
+  check_long ("lrint(1.4) = 1", FUNC(lrint) (1.4), 1);
+  check_long ("lrint(-1.4) = -1", FUNC(lrint) (-1.4), -1);
 
-  check_long ("lrint(8388600.3) = 8388600", lrint (8388600.3), 8388600);
-  check_long ("lrint(-8388600.3) = -8388600", lrint (-8388600.3),
+  check_long ("lrint(8388600.3) = 8388600", FUNC(lrint) (8388600.3), 8388600);
+  check_long ("lrint(-8388600.3) = -8388600", FUNC(lrint) (-8388600.3),
              -8388600);
 }
 
@@ -4659,18 +4662,50 @@ llrint_test (void)
      the rounding method and test the critical cases.  So far, only
      unproblematic numbers are tested.  */
 
-  check_longlong ("llrint(0) = 0", llrint (0.0), 0);
-  check_longlong ("llrint(-0) = 0", llrint (minus_zero), 0);
-  check_longlong ("llrint(0.2) = 0", llrint (0.2), 0);
-  check_longlong ("llrint(-0.2) = 0", llrint (-0.2), 0);
+  check_longlong ("llrint(0) = 0", FUNC(llrint) (0.0), 0);
+  check_longlong ("llrint(-0) = 0", FUNC(llrint) (minus_zero), 0);
+  check_longlong ("llrint(0.2) = 0", FUNC(llrint) (0.2), 0);
+  check_longlong ("llrint(-0.2) = 0", FUNC(llrint) (-0.2), 0);
 
-  check_longlong ("llrint(1.4) = 1", llrint (1.4), 1);
-  check_longlong ("llrint(-1.4) = -1", llrint (-1.4), -1);
+  check_longlong ("llrint(1.4) = 1", FUNC(llrint) (1.4), 1);
+  check_longlong ("llrint(-1.4) = -1", FUNC(llrint) (-1.4), -1);
 
-  check_longlong ("llrint(8388600.3) = 8388600", llrint (8388600.3),
+  check_longlong ("llrint(8388600.3) = 8388600", FUNC(llrint) (8388600.3),
                  8388600);
-  check_longlong ("llrint(-8388600.3) = -8388600", llrint (-8388600.3),
+  check_longlong ("llrint(-8388600.3) = -8388600", FUNC(llrint) (-8388600.3),
                  -8388600);
+
+  /* Test boundary conditions.  */
+  /* 0x1FFFFF */
+  check_longlong ("llrint(2097151.0) = 2097151", FUNC(llrint) (2097151.0),
+                 2097151LL);
+  /* 0x800000 */
+  check_longlong ("llrint(8388608.0) = 8388608", FUNC(llrint) (8388608.0),
+                 8388608LL);
+  /* 0x1000000 */
+  check_longlong ("llrint(16777216.0) = 16777216",
+                 FUNC(llrint) (16777216.0), 16777216LL);
+  /* 0x20000000000 */
+  check_longlong ("llrint(2199023255552.0) = 2199023255552",
+                 FUNC(llrint) (2199023255552.0), 2199023255552LL);
+  /* 0x40000000000 */
+  check_longlong ("llrint(4398046511104.0) = 4398046511104",
+                 FUNC(llrint) (4398046511104.0), 4398046511104LL);
+  /* 0x10000000000000 */
+  check_longlong ("llrint(4503599627370496.0) = 4503599627370496",
+                 FUNC(llrint) (4503599627370496.0), 4503599627370496LL);
+  /* 0x10000080000000 */
+  check_longlong ("llrint(4503601774854144.0) = 4503601774854144",
+                 FUNC(llrint) (4503601774854144.0), 4503601774854144LL);
+  /* 0x20000000000000 */
+  check_longlong ("llrint(9007199254740992.0) = 9007199254740992",
+                 FUNC(llrint) (9007199254740992.0), 9007199254740992LL);
+  /* 0x80000000000000 */
+  check_longlong ("llrint(36028797018963968.0) = 36028797018963968",
+                 FUNC(llrint) (36028797018963968.0), 36028797018963968LL);
+  /* 0x100000000000000 */
+  check_longlong ("llrint(72057594037927936.0) = 72057594037927936",
+                 FUNC(llrint) (72057594037927936.0), 72057594037927936LL);
 }
 
 
@@ -4705,8 +4740,8 @@ lround_test (void)
   check_long ("lround(-0.8) = -1", FUNC(lround) (-0.8), -1);
   check_long ("lround(1.5) = 2", FUNC(lround) (1.5), 2);
   check_long ("lround(-1.5) = -2", FUNC(lround) (-1.5), -2);
-  check_long ("lround(22514.5) = 22514", FUNC(lround) (1.5), 2);
-  check_long ("lround(-22514.5) = -22514", FUNC(lround) (-1.5), -2);
+  check_long ("lround(22514.5) = 22515", FUNC(lround) (22514.5), 22515);
+  check_long ("lround(-22514.5) = -22515", FUNC(lround) (-22514.5), -22515);
 #ifndef TEST_FLOAT
   check_long ("lround(2097152.5) = 2097153", FUNC(lround) (2097152.5),
              2097153);
@@ -4729,8 +4764,9 @@ llround_test (void)
   check_longlong ("llround(-0.8) = -1", FUNC(llround) (-0.8), -1);
   check_longlong ("llround(1.5) = 2", FUNC(llround) (1.5), 2);
   check_longlong ("llround(-1.5) = -2", FUNC(llround) (-1.5), -2);
-  check_longlong ("llround(22514.5) = 22514", FUNC(llround) (1.5), 2);
-  check_longlong ("llround(-22514.5) = -22514", FUNC(llround) (-1.5), -2);
+  check_longlong ("llround(22514.5) = 22515", FUNC(llround) (22514.5), 22515);
+  check_longlong ("llround(-22514.5) = -22515", FUNC(llround) (-22514.5),
+                 -22515);
 #ifndef TEST_FLOAT
   check_longlong ("llround(2097152.5) = 2097153",
                  FUNC(llround) (2097152.5), 2097153);
@@ -4741,6 +4777,38 @@ llround_test (void)
   check_longlong ("llround(-34359738368.5) = -34359738369",
                  FUNC(llround) (-34359738368.5), -34359738369ll);
 #endif
+
+  /* Test boundary conditions.  */
+  /* 0x1FFFFF */
+  check_longlong ("llround(2097151.0) = 2097151", FUNC(llround) (2097151.0),
+                 2097151LL);
+  /* 0x800000 */
+  check_longlong ("llround(8388608.0) = 8388608", FUNC(llround) (8388608.0),
+                 8388608LL);
+  /* 0x1000000 */
+  check_longlong ("llround(16777216.0) = 16777216",
+                 FUNC(llround) (16777216.0), 16777216LL);
+  /* 0x20000000000 */
+  check_longlong ("llround(2199023255552.0) = 2199023255552",
+                 FUNC(llround) (2199023255552.0), 2199023255552LL);
+  /* 0x40000000000 */
+  check_longlong ("llround(4398046511104.0) = 4398046511104",
+                 FUNC(llround) (4398046511104.0), 4398046511104LL);
+  /* 0x10000000000000 */
+  check_longlong ("llround(4503599627370496.0) = 4503599627370496",
+                 FUNC(llround) (4503599627370496.0), 4503599627370496LL);
+  /* 0x10000080000000 */
+  check_longlong ("llrint(4503601774854144.0) = 4503601774854144",
+                 FUNC(llrint) (4503601774854144.0), 4503601774854144LL);
+  /* 0x20000000000000 */
+  check_longlong ("llround(9007199254740992.0) = 9007199254740992",
+                 FUNC(llround) (9007199254740992.0), 9007199254740992LL);
+  /* 0x80000000000000 */
+  check_longlong ("llround(36028797018963968.0) = 36028797018963968",
+                 FUNC(llround) (36028797018963968.0), 36028797018963968LL);
+  /* 0x100000000000000 */
+  check_longlong ("llround(72057594037927936.0) = 72057594037927936",
+                 FUNC(llround) (72057594037927936.0), 72057594037927936LL);
 }
 
 
index aa5aeaaafd1d81bfaa4dd3e8ee6869d50c488b05..edd82a3d1e53d39ddc659b7cfdfaf72ab165d581 100644 (file)
@@ -7,11 +7,15 @@
 void print_trig_stuff __P ((void));
 
 int
-main (void)
+main (int argc, char *argv[])
 {
   const char str[] = "123.456";
   double x,h,li,lr,a,lrr;
 
+  if (signbit (argc < 1 ? -0.0 : 0.0))
+    /* I don't make this an error for now.  --drepper */
+    fputs ("\n*** Your compiler has a bug.  Consider upgrading\n\n", stderr);
+
   x = atof (str);
 
   printf ("%g %g\n", x, pow (10.0, 3.0));
index 4c7d957b37c9c1212d2043e1cfdadabf5bf64d36..b0ce202d359fe89c5e423e4b85d1c052d84ad05c 100644 (file)
 #define log(Val) __TGMATH_UNARY_REAL_IMAG (Val, log, clog)
 
 /* Base-ten logarithm of X.  */
-#define log10(Val) __TGMATH_UNARY_REAL_IMAG (Val, log10, __clog10)
+#ifdef __USE_GNU
+# define log10(Val) __TGMATH_UNARY_REAL_IMAG (Val, log10, __clog10)
+#else
+# define log10(Val) __TGMATH_UNARY_REAL_ONLY (Val, log10)
+#endif
 
 /* Return exp(X) - 1.  */
 #define expm1(Val) __TGMATH_UNARY_REAL_ONLY (Val, expm1)
index 98404d22c3eada8a08e8fbe4c03e13ae7a5e4179..2a08bb454c369d5410e9c529fdbeb4189aa7f3ab 100644 (file)
@@ -26,8 +26,9 @@ GLIBC_2.0 {
     # This functions are needed by the NIS+ tools and rpc.nisd,
     # they should never be used in a normal user program !
     __nis_default_access; __nis_default_group; __nis_default_owner;
-    __nis_default_ttl;    __free_fdresult; __nis_finddirectory;
+    __nis_default_ttl;    __free_fdresult;     __nis_finddirectory;
     __nis_hash;                  readColdStartFile;   writeColdStartFile;
+    __do_niscall2;
 
     # Many programs expect this, but every user program should
     # have it's own version, since the interface is different on
index 1495271c282d4299c7c94343e57075560d91fa12..cea508e5b65eac5b76adc725e24d227f4ad8f912 100644 (file)
@@ -27,7 +27,8 @@
 #include <arpa/inet.h>
 #include "nis_intern.h"
 
-static struct timeval TIMEOUT = {10, 0};
+static struct timeval RPCTIMEOUT = {10, 0};
+static struct timeval UDPTIMEOUT = {5, 0};
 
 unsigned long
 inetstr2int (const char *str)
@@ -135,7 +136,7 @@ __bind_connect (dir_binding *dbp)
   dbp->socket = RPC_ANYSOCK;
   if (dbp->use_udp)
     dbp->clnt = clntudp_create (&dbp->addr, NIS_PROG, NIS_VERSION,
-                                TIMEOUT, &dbp->socket);
+                                UDPTIMEOUT, &dbp->socket);
   else
     dbp->clnt = clnttcp_create (&dbp->addr, NIS_PROG, NIS_VERSION,
                                 &dbp->socket, 0, 0);
@@ -143,7 +144,7 @@ __bind_connect (dir_binding *dbp)
   if (dbp->clnt == NULL)
     return NIS_RPCERROR;
 
-  clnt_control (dbp->clnt, CLSET_TIMEOUT, (caddr_t)&TIMEOUT);
+  clnt_control (dbp->clnt, CLSET_TIMEOUT, (caddr_t)&RPCTIMEOUT);
   /* If the program exists, close the socket */
   if (fcntl (dbp->socket, F_SETFD, 1) == -1)
     perror (_("fcntl: F_SETFD"));
@@ -302,7 +303,7 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
   do
     {
     again:
-      result = clnt_call (dbp->clnt, prog, xargs, req, xres, resp, TIMEOUT);
+      result = clnt_call (dbp->clnt, prog, xargs, req, xres, resp, RPCTIMEOUT);
 
       if (result != RPC_SUCCESS)
        {
index 48c1950dd74408b20f15d5a04158037f2b499c66..054b462053fcb57fa404442be75a222fcdd16e98 100644 (file)
@@ -21,6 +21,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <rpc/rpc.h>
 #include <rpc/pmap_clnt.h>
 #include <string.h>
 #include <memory.h>
index c0ddbdffdf2031094092590110bec94fbc665d63..a460d8a8efbc8875a095028bba85828dc079ea66 100644 (file)
 #include <rpcsvc/nis.h>
 #include <nsswitch.h>
 
+/* Comment out the following line for the production version.  */
+/* #define NDEBUG 1 */
+#include <assert.h>
+
 #include "nss-nisplus.h"
 #include "nisplus-parser.h"
 
@@ -41,7 +45,7 @@ static size_t grptablelen = 0;
 #define ENTNAME grent
 #define STRUCTURE group
 #define EXTERN_PARSER
-#include "../../nss/nss_files/files-parse.c"
+#include <nss/nss_files/files-parse.c>
 
 /* Structure for remembering -group members ... */
 #define BLACKLIST_INITIAL_SIZE 512
@@ -85,15 +89,22 @@ _nss_first_init (void)
 
   if (grptable == NULL)
     {
-      char buf [20 + strlen (nis_local_directory ())];
-      char *p;
+      static const char key[] = "group.org_dir.";
+      const char *local_dir = nis_local_directory ();
+      size_t len_local_dir = strlen (local_dir);
 
-      p = stpcpy (buf, "group.org_dir.");
-      p = stpcpy (p, nis_local_directory ());
-      grptable = strdup (buf);
+      grptable = malloc (sizeof (key) + len_local_dir);
       if (grptable == NULL)
         return NSS_STATUS_TRYAGAIN;
-      grptablelen = strlen (grptable);
+
+      grptablelen = ((char *) mempcpy (mempcpy (grptable,
+                                               key, sizeof (key) - 1),
+                                      local_dir, len_local_dir + 1)
+                    - grptable) - 1;
+
+      /* *Maybe* (I'm no NIS expert) we have to duplicate the `local_dir'
+        value since it might change during our work.  So add a test here.  */
+      assert (grptablelen == sizeof (key) + len_local_dir);
     }
 
   return NSS_STATUS_SUCCESS;
@@ -370,8 +381,8 @@ getgrent_next_nisplus (struct group *result, ent_t *ent, char *buffer,
 
 /* This function handle the +group entrys in /etc/group */
 static enum nss_status
-getgrent_next_file_plusgroup (struct group *result, char *buffer,
-                             size_t buflen)
+getgrnam_plusgroup (const char *name, struct group *result, char *buffer,
+                   size_t buflen)
 {
   struct parser_data *data = (void *) buffer;
   int parse_res;
@@ -379,9 +390,9 @@ getgrent_next_file_plusgroup (struct group *result, char *buffer,
   if (use_nisplus) /* Do the NIS+ query here */
     {
       nis_result *res;
-      char buf[strlen (result->gr_name) + 24 + grptablelen];
+      char buf[strlen (name) + 24 + grptablelen];
 
-      sprintf(buf, "[name=%s],%s", &result->gr_name[1], grptable);
+      sprintf(buf, "[name=%s],%s", name, grptable);
       res = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
       if (niserr2nss (res->status) != NSS_STATUS_SUCCESS)
         {
@@ -407,9 +418,8 @@ getgrent_next_file_plusgroup (struct group *result, char *buffer,
       if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
         return NSS_STATUS_TRYAGAIN;
 
-      if (yp_match (domain, "group.byname", &result->gr_name[1],
-                    strlen (result->gr_name) - 1, &outval, &outvallen)
-          != YPERR_SUCCESS)
+      if (yp_match (domain, "group.byname", name, strlen (name),
+                   &outval, &outvallen) != YPERR_SUCCESS)
         return NSS_STATUS_TRYAGAIN;
       p = strncpy (buffer, outval,
                    buflen < (size_t) outvallen ? buflen : (size_t) outvallen);
@@ -430,7 +440,6 @@ getgrent_next_file_plusgroup (struct group *result, char *buffer,
     return NSS_STATUS_RETURN;
 }
 
-
 static enum nss_status
 getgrent_next_file (struct group *result, ent_t *ent,
                    char *buffer, size_t buflen)
@@ -495,7 +504,11 @@ getgrent_next_file (struct group *result, ent_t *ent,
        {
           enum nss_status status;
 
-          status = getgrent_next_file_plusgroup (result, buffer, buflen);
+         /* Store the group in the blacklist for the "+" at the end of
+            /etc/group */
+         blacklist_store_name (&result->gr_name[1], ent);
+         status = getgrnam_plusgroup (&result->gr_name[1], result, buffer,
+                                      buflen);
           if (status == NSS_STATUS_SUCCESS) /* We found the entry. */
             break;
           else
@@ -556,6 +569,104 @@ _nss_compat_getgrent_r (struct group *grp, char *buffer, size_t buflen)
   return status;
 }
 
+/* Searches in /etc/group and the NIS/NIS+ map for a special group */
+static enum nss_status
+internal_getgrnam_r (const char *name, struct group *result, ent_t *ent,
+                    char *buffer, size_t buflen)
+{
+  struct parser_data *data = (void *) buffer;
+  while (1)
+    {
+      fpos_t pos;
+      int parse_res = 0;
+      char *p;
+
+      do
+       {
+         fgetpos (ent->stream, &pos);
+         p = fgets (buffer, buflen, ent->stream);
+         if (p == NULL)
+           {
+             if (feof (ent->stream))
+               return NSS_STATUS_NOTFOUND;
+             else
+               {
+                 __set_errno (ERANGE);
+                 return NSS_STATUS_TRYAGAIN;
+               }
+           }
+
+         /* Terminate the line for any case.  */
+         buffer[buflen - 1] = '\0';
+
+         /* Skip leading blanks.  */
+         while (isspace (*p))
+           ++p;
+       }
+      while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */
+      /* Parse the line.  If it is invalid, loop to
+         get the next line of the file to parse.  */
+            !(parse_res = _nss_files_parse_grent (p, result, data, buflen)));
+
+      if (parse_res == -1)
+       {
+         /* The parser ran out of space.  */
+         fsetpos (ent->stream, &pos);
+         __set_errno (ERANGE);
+         return NSS_STATUS_TRYAGAIN;
+       }
+
+      /* This is a real entry.  */
+      if (result->gr_name[0] != '+' && result->gr_name[0] != '-')
+       {
+         if (strcmp (result->gr_name, name) == 0)
+           return NSS_STATUS_SUCCESS;
+         else
+           continue;
+       }
+
+      /* -group */
+      if (result->gr_name[0] == '-' && result->gr_name[1] != '\0'
+         && result->gr_name[1] != '@')
+       {
+         if (strcmp (&result->gr_name[1], name) == 0)
+           return NSS_STATUS_NOTFOUND;
+         else
+           continue;
+       }
+
+      /* +group */
+      if (result->gr_name[0] == '+' && result->gr_name[1] != '\0'
+         && result->gr_name[1] != '@')
+       {
+         if (strcmp (name, &result->gr_name[1]) == 0)
+           {
+             enum nss_status status;
+
+             status = getgrnam_plusgroup (name, result, buffer, buflen);
+             if (status == NSS_STATUS_RETURN)
+               /* We couldn't parse the entry */
+               continue;
+             else
+               return status;
+           }
+       }
+      /* +:... */
+      if (result->gr_name[0] == '+' && result->gr_name[1] == '\0')
+       {
+         enum nss_status status;
+
+         status = getgrnam_plusgroup (name, result, buffer, buflen);
+         if (status == NSS_STATUS_RETURN)
+           /* We couldn't parse the entry */
+           continue;
+         else
+           return status;
+       }
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
 
 enum nss_status
 _nss_compat_getgrnam_r (const char *name, struct group *grp,
@@ -576,15 +687,172 @@ _nss_compat_getgrnam_r (const char *name, struct group *grp,
   if (status != NSS_STATUS_SUCCESS)
     return status;
 
-  while ((status = internal_getgrent_r (grp, &ent, buffer, buflen))
-        == NSS_STATUS_SUCCESS)
-    if (strcmp (grp->gr_name, name) == 0)
-      break;
+  status = internal_getgrnam_r (name, grp, &ent, buffer, buflen);
 
   internal_endgrent (&ent);
+
   return status;
 }
 
+/* This function handle the + entry in /etc/group */
+static enum nss_status
+getgrgid_plusgroup (gid_t gid, struct group *result, char *buffer,
+                   size_t buflen)
+{
+  struct parser_data *data = (void *) buffer;
+  int parse_res;
+
+  if (use_nisplus) /* Do the NIS+ query here */
+    {
+      nis_result *res;
+      char buf[1024 + grptablelen];
+
+      sprintf(buf, "[gid=%d],%s", gid, grptable);
+      res = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+      if (niserr2nss (res->status) != NSS_STATUS_SUCCESS)
+        {
+          enum nss_status status =  niserr2nss (res->status);
+
+          nis_freeresult (res);
+          return status;
+        }
+      if ((parse_res = _nss_nisplus_parse_grent (res, 0, result, buffer,
+                                                buflen)) == -1)
+       {
+         __set_errno (ERANGE);
+         nis_freeresult (res);
+         return NSS_STATUS_TRYAGAIN;
+       }
+      nis_freeresult (res);
+    }
+  else /* Use NIS */
+    {
+      char buf[1024];
+      char *domain, *outval, *p;
+      int outvallen;
+
+      if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
+        return NSS_STATUS_TRYAGAIN;
+
+      snprintf (buf, sizeof (buf), "%d", gid);
+
+      if (yp_match (domain, "group.bygid", buf, strlen (buf),
+                   &outval, &outvallen) != YPERR_SUCCESS)
+        return NSS_STATUS_TRYAGAIN;
+      p = strncpy (buffer, outval,
+                   buflen < (size_t) outvallen ? buflen : (size_t) outvallen);
+      free (outval);
+      while (isspace (*p))
+        p++;
+      if ((parse_res = _nss_files_parse_grent (p, result, data, buflen)) == -1)
+       {
+         __set_errno (ERANGE);
+         return NSS_STATUS_TRYAGAIN;
+       }
+    }
+
+  if (parse_res)
+    /* We found the entry.  */
+    return NSS_STATUS_SUCCESS;
+  else
+    return NSS_STATUS_RETURN;
+}
+
+/* Searches in /etc/group and the NIS/NIS+ map for a special group id */
+static enum nss_status
+internal_getgrgid_r (gid_t gid, struct group *result, ent_t *ent,
+                    char *buffer, size_t buflen)
+{
+  struct parser_data *data = (void *) buffer;
+  while (1)
+    {
+      fpos_t pos;
+      int parse_res = 0;
+      char *p;
+
+      do
+       {
+         fgetpos (ent->stream, &pos);
+         p = fgets (buffer, buflen, ent->stream);
+         if (p == NULL)
+           {
+             if (feof (ent->stream))
+               return NSS_STATUS_NOTFOUND;
+             else
+               {
+                 __set_errno (ERANGE);
+                 return NSS_STATUS_TRYAGAIN;
+               }
+           }
+
+         /* Terminate the line for any case.  */
+         buffer[buflen - 1] = '\0';
+
+         /* Skip leading blanks.  */
+         while (isspace (*p))
+           ++p;
+       }
+      while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */
+      /* Parse the line.  If it is invalid, loop to
+         get the next line of the file to parse.  */
+            !(parse_res = _nss_files_parse_grent (p, result, data, buflen)));
+
+      if (parse_res == -1)
+       {
+         /* The parser ran out of space.  */
+         fsetpos (ent->stream, &pos);
+         __set_errno (ERANGE);
+         return NSS_STATUS_TRYAGAIN;
+       }
+
+      /* This is a real entry.  */
+      if (result->gr_name[0] != '+' && result->gr_name[0] != '-')
+       {
+         if (result->gr_gid == gid)
+           return NSS_STATUS_SUCCESS;
+         else
+           continue;
+       }
+
+      /* -group */
+      if (result->gr_name[0] == '-' && result->gr_name[1] != '\0'
+         && result->gr_name[1] != '@')
+       {
+          blacklist_store_name (&result->gr_name[1], ent);
+          continue;
+       }
+
+      /* +group */
+      if (result->gr_name[0] == '+' && result->gr_name[1] != '\0'
+         && result->gr_name[1] != '@')
+       {
+         enum nss_status status;
+
+         /* Store the group in the blacklist for the "+" at the end of
+             /etc/group */
+          blacklist_store_name (&result->gr_name[1], ent);
+         status = getgrnam_plusgroup (&result->gr_name[1], result, buffer,
+                                     buflen);
+         if (status == NSS_STATUS_SUCCESS && result->gr_gid == gid)
+           break;
+         else
+           continue;
+       }
+      /* +:... */
+      if (result->gr_name[0] == '+' && result->gr_name[1] == '\0')
+       {
+         enum nss_status status;
+
+         status = getgrgid_plusgroup (gid, result, buffer, buflen);
+         if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */
+           return NSS_STATUS_NOTFOUND;
+         else
+           return status;
+       }
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
 
 enum nss_status
 _nss_compat_getgrgid_r (gid_t gid, struct group *grp,
@@ -602,12 +870,10 @@ _nss_compat_getgrgid_r (gid_t gid, struct group *grp,
   if (status != NSS_STATUS_SUCCESS)
     return status;
 
-  while ((status = internal_getgrent_r (grp, &ent, buffer, buflen))
-        == NSS_STATUS_SUCCESS)
-    if (grp->gr_gid == gid && grp->gr_name[0] != '+' && grp->gr_name[0] != '-')
-      break;
+  status = internal_getgrgid_r (gid, grp, &ent, buffer, buflen);
 
   internal_endgrent (&ent);
+
   return status;
 }
 
index 681258d2e6d43b7f773d722b5dfdee93690eab1a..0216522d36fec20bd4f983c8dc494712a6de8c60 100644 (file)
 #include <rpcsvc/nis.h>
 #include <nsswitch.h>
 
+/* Comment out the following line for the production version.  */
+/* #define NDEBUG 1 */
+#include <assert.h>
+
 #include "netgroup.h"
 #include "nss-nisplus.h"
 #include "nisplus-parser.h"
@@ -43,7 +47,7 @@ static size_t pwdtablelen = 0;
 #define ENTNAME pwent
 #define STRUCTURE passwd
 #define EXTERN_PARSER
-#include "../../nss/nss_files/files-parse.c"
+#include <nss/nss_files/files-parse.c>
 
 /* Structure for remembering -@netgroup and -user members ... */
 #define BLACKLIST_INITIAL_SIZE 512
@@ -211,15 +215,22 @@ internal_setpwent (ent_t *ent)
 
   if (pwdtable == NULL)
     {
-      char buf [20 + strlen (nis_local_directory ())];
-      char *p;
+      static const char key[] = "passwd.org_dir.";
+      const char *local_dir = nis_local_directory ();
+      size_t len_local_dir = strlen (local_dir);
 
-      p = stpcpy (buf, "passwd.org_dir.");
-      p = stpcpy (p, nis_local_directory ());
-      pwdtable = strdup (buf);
+      pwdtable = malloc (sizeof (key) + len_local_dir);
       if (pwdtable == NULL)
-       return NSS_STATUS_TRYAGAIN;
-      pwdtablelen = strlen (pwdtable);
+        return NSS_STATUS_TRYAGAIN;
+
+      pwdtablelen = ((char *) mempcpy (mempcpy (pwdtable,
+                                               key, sizeof (key) - 1),
+                                      local_dir, len_local_dir + 1)
+                    - pwdtable) - 1;
+
+      /* *Maybe* (I'm no NIS expert) we have to duplicate the `local_dir'
+        value since it might change during our work.  So add a test here.  */
+      assert (pwdtablelen == sizeof (key) + len_local_dir);
     }
 
   ent->blacklist.current = 0;
@@ -334,8 +345,8 @@ _nss_compat_endpwent (void)
 }
 
 static enum nss_status
-getpwent_next_nis_netgr (struct passwd *result, ent_t *ent, char *group,
-                        char *buffer, size_t buflen)
+getpwent_next_nis_netgr (const char *name, struct passwd *result, ent_t *ent,
+                        char *group, char *buffer, size_t buflen)
 {
   struct parser_data *data = (void *) buffer;
   char *ypdomain, *host, *user, *domain, *outval, *p, *p2;
@@ -379,6 +390,11 @@ getpwent_next_nis_netgr (struct passwd *result, ent_t *ent, char *group,
       if (domain != NULL && strcmp (ypdomain, domain) != 0)
        continue;
 
+      /* If name != NULL, we are called from getpwnam */
+      if (name != NULL)
+       if (strcmp (user, name) != 0)
+         continue;
+
       if (yp_match (ypdomain, "passwd.byname", user,
                    strlen (user), &outval, &outvallen)
          != YPERR_SUCCESS)
@@ -404,6 +420,9 @@ getpwent_next_nis_netgr (struct passwd *result, ent_t *ent, char *group,
 
       if (parse_res)
        {
+         /* Store the User in the blacklist for the "+" at the end of
+            /etc/passwd */
+         blacklist_store_name (result->pw_name, ent);
          copy_pwd_changes (result, &ent->pwd, p2, p2len);
          break;
        }
@@ -413,8 +432,9 @@ getpwent_next_nis_netgr (struct passwd *result, ent_t *ent, char *group,
 }
 
 static enum nss_status
-getpwent_next_nisplus_netgr (struct passwd *result, ent_t *ent, char *group,
-                            char *buffer, size_t buflen)
+getpwent_next_nisplus_netgr (const char *name, struct passwd *result,
+                            ent_t *ent, char *group, char *buffer,
+                            size_t buflen)
 {
   char *ypdomain, *host, *user, *domain, *p2;
   int status, parse_res;
@@ -459,6 +479,11 @@ getpwent_next_nisplus_netgr (struct passwd *result, ent_t *ent, char *group,
       if (domain != NULL && strcmp (ypdomain, domain) != 0)
        continue;
 
+      /* If name != NULL, we are called from getpwnam */
+      if (name != NULL)
+       if (strcmp (user, name) != 0)
+         continue;
+
       p2len = pwd_need_buflen (&ent->pwd);
       if (p2len > buflen)
        {
@@ -488,6 +513,9 @@ getpwent_next_nisplus_netgr (struct passwd *result, ent_t *ent, char *group,
 
       if (parse_res)
        {
+         /* Store the User in the blacklist for the "+" at the end of
+            /etc/passwd */
+         blacklist_store_name (result->pw_name, ent);
          copy_pwd_changes (result, &ent->pwd, p2, p2len);
          break;
        }
@@ -496,16 +524,6 @@ getpwent_next_nisplus_netgr (struct passwd *result, ent_t *ent, char *group,
   return NSS_STATUS_SUCCESS;
 }
 
-static enum nss_status
-getpwent_next_netgr (struct passwd *result, ent_t *ent, char *group,
-                    char *buffer, size_t buflen)
-{
-  if (use_nisplus)
-    return getpwent_next_nisplus_netgr (result, ent, group, buffer, buflen);
-  else
-    return getpwent_next_nis_netgr (result, ent, group, buffer, buflen);
-}
-
 static enum nss_status
 getpwent_next_nisplus (struct passwd *result, ent_t *ent, char *buffer,
                       size_t buflen)
@@ -683,8 +701,8 @@ getpwent_next_nis (struct passwd *result, ent_t *ent, char *buffer,
 
 /* This function handle the +user entrys in /etc/passwd */
 static enum nss_status
-getpwent_next_file_plususer (struct passwd *result, char *buffer,
-                            size_t buflen)
+getpwnam_plususer (const char *name, struct passwd *result, char *buffer,
+                  size_t buflen)
 {
   struct parser_data *data = (void *) buffer;
   struct passwd pwd;
@@ -708,9 +726,9 @@ getpwent_next_file_plususer (struct passwd *result, char *buffer,
   if (use_nisplus) /* Do the NIS+ query here */
     {
       nis_result *res;
-      char buf[strlen (result->pw_name) + 24 + pwdtablelen];
+      char buf[strlen (name) + 24 + pwdtablelen];
 
-      sprintf(buf, "[name=%s],%s", &result->pw_name[1], pwdtable);
+      sprintf(buf, "[name=%s],%s", name, pwdtable);
       res = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
       if (niserr2nss (res->status) != NSS_STATUS_SUCCESS)
        {
@@ -730,23 +748,24 @@ getpwent_next_file_plususer (struct passwd *result, char *buffer,
     }
   else /* Use NIS */
     {
-      char *domain;
-      char *outval;
+      char *domain, *outval, *ptr;
       int outvallen;
 
       if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
        return NSS_STATUS_TRYAGAIN;
 
-      if (yp_match (domain, "passwd.byname", &result->pw_name[1],
-                   strlen (result->pw_name) - 1, &outval, &outvallen)
+      if (yp_match (domain, "passwd.byname", name, strlen (name),
+                   &outval, &outvallen)
          != YPERR_SUCCESS)
        return NSS_STATUS_TRYAGAIN;
-      p = strncpy (buffer, outval,
-                  buflen < (size_t) outvallen ? buflen : (size_t) outvallen);
+      ptr = strncpy (buffer, outval, buflen < (size_t) outvallen ?
+                    buflen : (size_t) outvallen);
+      buffer[buflen < (size_t) outvallen ? buflen : (size_t) outvallen] = '\0';
       free (outval);
-      while (isspace (*p))
-       p++;
-      if ((parse_res = _nss_files_parse_pwent (p, result, data, buflen)) == -1)
+      while (isspace (*ptr))
+       ptr++;
+      if ((parse_res = _nss_files_parse_pwent (ptr, result, data, buflen))
+         == -1)
        {
          __set_errno (ERANGE);
          return NSS_STATUS_TRYAGAIN;
@@ -841,8 +860,14 @@ getpwent_next_file (struct passwd *result, ent_t *ent,
          ent->first = TRUE;
          copy_pwd_changes (&ent->pwd, result, NULL, 0);
 
-         status = getpwent_next_netgr (result, ent, &result->pw_name[2],
-                                       buffer, buflen);
+         if (use_nisplus)
+           status =  getpwent_next_nisplus_netgr (NULL, result, ent,
+                                                  &result->pw_name[2],
+                                                  buffer, buflen);
+         else
+           status =  getpwent_next_nis_netgr (NULL, result, ent,
+                                              &result->pw_name[2],
+                                              buffer, buflen);
          if (status == NSS_STATUS_RETURN)
            continue;
          else
@@ -863,7 +888,11 @@ getpwent_next_file (struct passwd *result, ent_t *ent,
        {
          enum nss_status status;
 
-         status = getpwent_next_file_plususer (result, buffer, buflen);
+         /* Store the User in the blacklist for the "+" at the end of
+            /etc/passwd */
+         blacklist_store_name (&result->pw_name[1], ent);
+         status = getpwnam_plususer (&result->pw_name[1], result, buffer,
+                                     buflen);
          if (status == NSS_STATUS_SUCCESS) /* We found the entry. */
            break;
          else
@@ -901,26 +930,30 @@ internal_getpwent_r (struct passwd *pw, ent_t *ent, char *buffer,
 
       /* We are searching members in a netgroup */
       /* Since this is not the first call, we don't need the group name */
-      status = getpwent_next_netgr (pw, ent, NULL, buffer, buflen);
+      if (use_nisplus)
+       status = getpwent_next_nisplus_netgr (NULL, pw, ent, NULL, buffer,
+                                             buflen);
+      else
+       status = getpwent_next_nis_netgr (NULL, pw, ent, NULL, buffer, buflen);
       if (status == NSS_STATUS_RETURN)
        return getpwent_next_file (pw, ent, buffer, buflen);
       else
        return status;
     }
-  else if (ent->nis)
-    {
-      if (use_nisplus)
-       return getpwent_next_nisplus (pw, ent, buffer, buflen);
-      else
-       return getpwent_next_nis (pw, ent, buffer, buflen);
-    }
   else
-    return getpwent_next_file (pw, ent, buffer, buflen);
+    if (ent->nis)
+      {
+       if (use_nisplus)
+         return getpwent_next_nisplus (pw, ent, buffer, buflen);
+       else
+         return getpwent_next_nis (pw, ent, buffer, buflen);
+      }
+    else
+      return getpwent_next_file (pw, ent, buffer, buflen);
 }
 
 enum nss_status
-_nss_compat_getpwent_r (struct passwd *pwd, char *buffer,
-                       size_t buflen)
+_nss_compat_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen)
 {
   enum nss_status status = NSS_STATUS_SUCCESS;
 
@@ -944,6 +977,158 @@ _nss_compat_getpwent_r (struct passwd *pwd, char *buffer,
   return status;
 }
 
+/* Searches in /etc/passwd and the NIS/NIS+ map for a special user */
+static enum nss_status
+internal_getpwnam_r (const char *name, struct passwd *result, ent_t *ent,
+                    char *buffer, size_t buflen)
+{
+  struct parser_data *data = (void *) buffer;
+
+  while (1)
+    {
+      fpos_t pos;
+      char *p;
+      int parse_res;
+
+      do
+       {
+         fgetpos (ent->stream, &pos);
+         p = fgets (buffer, buflen, ent->stream);
+         if (p == NULL)
+           {
+             if (feof (ent->stream))
+               return NSS_STATUS_NOTFOUND;
+             else
+               {
+                 __set_errno (ERANGE);
+                 return NSS_STATUS_TRYAGAIN;
+               }
+           }
+
+         /* Terminate the line for any case.  */
+         buffer[buflen - 1] = '\0';
+
+         /* Skip leading blanks.  */
+         while (isspace (*p))
+           ++p;
+       }
+      while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines.  */
+            /* Parse the line.  If it is invalid, loop to
+               get the next line of the file to parse.  */
+            !(parse_res = _nss_files_parse_pwent (p, result, data, buflen)));
+
+      if (parse_res == -1)
+       {
+         /* The parser ran out of space.  */
+         fsetpos (ent->stream, &pos);
+         __set_errno (ERANGE);
+         return NSS_STATUS_TRYAGAIN;
+       }
+
+      /* This is a real entry.  */
+      if (result->pw_name[0] != '+' && result->pw_name[0] != '-')
+       {
+         if (strcmp (result->pw_name, name) == 0)
+           return NSS_STATUS_SUCCESS;
+         else
+           continue;
+       }
+
+      /* -@netgroup */
+      if (result->pw_name[0] == '-' && result->pw_name[1] == '@'
+         && result->pw_name[2] != '\0')
+       {
+         char buf2[1024];
+         char *user, *host, *domain;
+         struct __netgrent netgrdata;
+
+         bzero (&netgrdata, sizeof (struct __netgrent));
+         __internal_setnetgrent (&result->pw_name[2], &netgrdata);
+         while (__internal_getnetgrent_r (&host, &user, &domain,
+                                          &netgrdata, buf2, sizeof (buf2)))
+           {
+             if (user != NULL && user[0] != '-')
+               if (strcmp (user, name) == 0)
+                 return NSS_STATUS_NOTFOUND;
+           }
+         __internal_endnetgrent (&netgrdata);
+         continue;
+       }
+
+      /* +@netgroup */
+      if (result->pw_name[0] == '+' && result->pw_name[1] == '@'
+         && result->pw_name[2] != '\0')
+       {
+         char buf[strlen (result->pw_name)];
+         int status;
+
+         strcpy (buf, &result->pw_name[2]);
+         ent->netgroup = TRUE;
+         ent->first = TRUE;
+         copy_pwd_changes (&ent->pwd, result, NULL, 0);
+
+         do
+           {
+             if (use_nisplus)
+               status = getpwent_next_nisplus_netgr (name, result, ent, buf,
+                                                     buffer, buflen);
+             else
+               status = getpwent_next_nis_netgr (name, result, ent, buf,
+                                                 buffer, buflen);
+             if (status == NSS_STATUS_RETURN)
+               continue;
+
+             if (status == NSS_STATUS_SUCCESS &&
+                 strcmp (result->pw_name, name) == 0)
+               return NSS_STATUS_SUCCESS;
+           } while (status == NSS_STATUS_SUCCESS);
+         continue;
+       }
+
+      /* -user */
+      if (result->pw_name[0] == '-' && result->pw_name[1] != '\0'
+         && result->pw_name[1] != '@')
+       {
+         if (strcmp (&result->pw_name[1], name) == 0)
+           return NSS_STATUS_NOTFOUND;
+         else
+           continue;
+       }
+
+      /* +user */
+      if (result->pw_name[0] == '+' && result->pw_name[1] != '\0'
+         && result->pw_name[1] != '@')
+       {
+         if (strcmp (name, &result->pw_name[1]) == 0)
+           {
+             enum nss_status status;
+
+             status = getpwnam_plususer (name, result, buffer, buflen);
+             if (status == NSS_STATUS_RETURN)
+               /* We couldn't parse the entry */
+               return NSS_STATUS_NOTFOUND;
+             else
+               return status;
+           }
+       }
+
+      /* +:... */
+      if (result->pw_name[0] == '+' && result->pw_name[1] == '\0')
+       {
+         enum nss_status status;
+
+         status = getpwnam_plususer (name, result, buffer, buflen);
+         if (status == NSS_STATUS_SUCCESS) /* We found the entry. */
+           break;
+         else
+           if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */
+             return NSS_STATUS_NOTFOUND;
+           else
+             return status;
+       }
+    }
+  return NSS_STATUS_SUCCESS;
+}
 
 enum nss_status
 _nss_compat_getpwnam_r (const char *name, struct passwd *pwd,
@@ -970,15 +1155,244 @@ _nss_compat_getpwnam_r (const char *name, struct passwd *pwd,
   if (status != NSS_STATUS_SUCCESS)
     return status;
 
-  while ((status = internal_getpwent_r (pwd, &ent, buffer, buflen))
-        == NSS_STATUS_SUCCESS)
-    if (strcmp (pwd->pw_name, name) == 0)
-      break;
+  status = internal_getpwnam_r (name, pwd, &ent, buffer, buflen);
 
   internal_endpwent (&ent);
+
   return status;
 }
 
+/* This function handle the + entry in /etc/passwd for getpwuid */
+static enum nss_status
+getpwuid_plususer (uid_t uid, struct passwd *result, char *buffer,
+                  size_t buflen)
+{
+  struct parser_data *data = (void *) buffer;
+  struct passwd pwd;
+  int parse_res;
+  char *p;
+  size_t plen;
+
+  memset (&pwd, '\0', sizeof (struct passwd));
+
+  copy_pwd_changes (&pwd, result, NULL, 0);
+
+  plen = pwd_need_buflen (&pwd);
+  if (plen > buflen)
+    {
+      __set_errno (ERANGE);
+      return NSS_STATUS_TRYAGAIN;
+    }
+  p = buffer + (buflen - plen);
+  buflen -= plen;
+
+  if (use_nisplus) /* Do the NIS+ query here */
+    {
+      nis_result *res;
+      char buf[1024 + pwdtablelen];
+
+      sprintf(buf, "[uid=%d],%s", uid, pwdtable);
+      res = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+      if (niserr2nss (res->status) != NSS_STATUS_SUCCESS)
+       {
+         enum nss_status status =  niserr2nss (res->status);
+
+         nis_freeresult (res);
+         return status;
+       }
+      if ((parse_res = _nss_nisplus_parse_pwent (res, result, buffer,
+                                                buflen)) == -1)
+       {
+         nis_freeresult (res);
+         __set_errno (ERANGE);
+         return NSS_STATUS_TRYAGAIN;
+       }
+      nis_freeresult (res);
+    }
+  else /* Use NIS */
+    {
+      char buf[1024];
+      char *domain, *outval, *ptr;
+      int outvallen;
+
+      if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
+       return NSS_STATUS_TRYAGAIN;
+
+      sprintf (buf, "%d", uid);
+      if (yp_match (domain, "passwd.byuid", buf, strlen (buf),
+                   &outval, &outvallen)
+         != YPERR_SUCCESS)
+       return NSS_STATUS_TRYAGAIN;
+      ptr = strncpy (buffer, outval, buflen < (size_t) outvallen ?
+                    buflen : (size_t) outvallen);
+      buffer[buflen < (size_t) outvallen ? buflen : (size_t) outvallen] = '\0';
+      free (outval);
+      while (isspace (*ptr))
+       ptr++;
+      if ((parse_res = _nss_files_parse_pwent (ptr, result, data, buflen))
+         == -1)
+       {
+         __set_errno (ERANGE);
+         return NSS_STATUS_TRYAGAIN;
+       }
+    }
+
+  if (parse_res > 0)
+    {
+      copy_pwd_changes (result, &pwd, p, plen);
+      give_pwd_free (&pwd);
+      /* We found the entry.  */
+      return NSS_STATUS_SUCCESS;
+    }
+  else
+    {
+      /* Give buffer the old len back */
+      buflen += plen;
+      give_pwd_free (&pwd);
+    }
+  return NSS_STATUS_RETURN;
+}
+
+/* Searches in /etc/passwd and the NIS/NIS+ map for a special user id */
+static enum nss_status
+internal_getpwuid_r (uid_t uid, struct passwd *result, ent_t *ent,
+                    char *buffer, size_t buflen)
+{
+  struct parser_data *data = (void *) buffer;
+
+  while (1)
+    {
+      fpos_t pos;
+      char *p;
+      int parse_res;
+
+      do
+       {
+         fgetpos (ent->stream, &pos);
+         p = fgets (buffer, buflen, ent->stream);
+         if (p == NULL)
+           return NSS_STATUS_NOTFOUND;
+
+         /* Terminate the line for any case.  */
+         buffer[buflen - 1] = '\0';
+
+         /* Skip leading blanks.  */
+         while (isspace (*p))
+           ++p;
+       }
+      while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines.  */
+            /* Parse the line.  If it is invalid, loop to
+               get the next line of the file to parse.  */
+            !(parse_res = _nss_files_parse_pwent (p, result, data, buflen)));
+
+      if (parse_res == -1)
+       {
+         /* The parser ran out of space.  */
+         fsetpos (ent->stream, &pos);
+         __set_errno (ERANGE);
+         return NSS_STATUS_TRYAGAIN;
+       }
+
+      /* This is a real entry.  */
+      if (result->pw_name[0] != '+' && result->pw_name[0] != '-')
+       {
+         if (result->pw_uid == uid)
+           return NSS_STATUS_SUCCESS;
+         else
+           continue;
+       }
+
+      /* -@netgroup */
+      if (result->pw_name[0] == '-' && result->pw_name[1] == '@'
+         && result->pw_name[2] != '\0')
+       {
+         char buf2[1024];
+         char *user, *host, *domain;
+         struct __netgrent netgrdata;
+
+         bzero (&netgrdata, sizeof (struct __netgrent));
+         __internal_setnetgrent (&result->pw_name[2], &netgrdata);
+         while (__internal_getnetgrent_r (&host, &user, &domain,
+                                          &netgrdata, buf2, sizeof (buf2)))
+           {
+              if (user != NULL && user[0] != '-')
+                blacklist_store_name (user, ent);
+           }
+         __internal_endnetgrent (&netgrdata);
+         continue;
+       }
+
+      /* +@netgroup */
+      if (result->pw_name[0] == '+' && result->pw_name[1] == '@'
+         && result->pw_name[2] != '\0')
+       {
+         char buf[strlen (result->pw_name)];
+         int status;
+
+         strcpy (buf, &result->pw_name[2]);
+         ent->netgroup = TRUE;
+         ent->first = TRUE;
+         copy_pwd_changes (&ent->pwd, result, NULL, 0);
+
+         do
+           {
+             if (use_nisplus)
+               status = getpwent_next_nisplus_netgr (NULL, result, ent, buf,
+                                                     buffer, buflen);
+             else
+               status = getpwent_next_nis_netgr (NULL, result, ent, buf,
+                                                 buffer, buflen);
+             if (status == NSS_STATUS_RETURN)
+               continue;
+
+             if (status == NSS_STATUS_SUCCESS && uid == result->pw_uid)
+               return NSS_STATUS_SUCCESS;
+           } while (status == NSS_STATUS_SUCCESS);
+         continue;
+       }
+
+      /* -user */
+      if (result->pw_name[0] == '-' && result->pw_name[1] != '\0'
+         && result->pw_name[1] != '@')
+       {
+          blacklist_store_name (&result->pw_name[1], ent);
+          continue;
+       }
+
+      /* +user */
+      if (result->pw_name[0] == '+' && result->pw_name[1] != '\0'
+         && result->pw_name[1] != '@')
+       {
+         enum nss_status status;
+
+         /* Store the User in the blacklist for the "+" at the end of
+             /etc/passwd */
+          blacklist_store_name (&result->pw_name[1], ent);
+         status = getpwnam_plususer (&result->pw_name[1], result, buffer,
+                                     buflen);
+         if (status == NSS_STATUS_SUCCESS && result->pw_uid == uid)
+           break;
+         else
+           continue;
+       }
+
+      /* +:... */
+      if (result->pw_name[0] == '+' && result->pw_name[1] == '\0')
+       {
+         enum nss_status status;
+
+         status = getpwuid_plususer (uid, result, buffer, buflen);
+         if (status == NSS_STATUS_SUCCESS) /* We found the entry. */
+           break;
+         else
+           if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */
+             return NSS_STATUS_NOTFOUND;
+           else
+             return status;
+       }
+    }
+  return NSS_STATUS_SUCCESS;
+}
 
 enum nss_status
 _nss_compat_getpwuid_r (uid_t uid, struct passwd *pwd,
@@ -1002,12 +1416,10 @@ _nss_compat_getpwuid_r (uid_t uid, struct passwd *pwd,
   if (status != NSS_STATUS_SUCCESS)
     return status;
 
-  while ((status = internal_getpwent_r (pwd, &ent, buffer, buflen))
-        == NSS_STATUS_SUCCESS)
-    if (pwd->pw_uid == uid && pwd->pw_name[0] != '+' && pwd->pw_name[0] != '-')
-      break;
+  status = internal_getpwuid_r (uid, pwd, &ent, buffer, buflen);
 
   internal_endpwent (&ent);
+
   return status;
 }
 
index 431380dac658b729a5e929d54290eaf6afc8d80a..c33d5aa3393b5475090507a5ff44e5d22a78f56c 100644 (file)
 #include <rpcsvc/nis.h>
 #include <nsswitch.h>
 
+/* Comment out the following line for the production version.  */
+/* #define NDEBUG 1 */
+#include <assert.h>
+
 #include "netgroup.h"
 #include "nss-nisplus.h"
 #include "nisplus-parser.h"
@@ -43,7 +47,7 @@ static size_t pwdtablelen = 0;
 #define ENTNAME spent
 #define STRUCTURE spwd
 #define EXTERN_PARSER
-#include "../../nss/nss_files/files-parse.c"
+#include <nss/nss_files/files-parse.c>
 
 /* Structure for remembering -@netgroup and -user members ... */
 #define BLACKLIST_INITIAL_SIZE 512
@@ -163,15 +167,22 @@ internal_setspent (ent_t *ent)
 
   if (pwdtable == NULL)
     {
-      char buf [20 + strlen (nis_local_directory ())];
-      char *p;
+      static const char key[] = "passwd.org_dir.";
+      const char *local_dir = nis_local_directory ();
+      size_t len_local_dir = strlen (local_dir);
 
-      p = stpcpy (buf, "passwd.org_dir.");
-      p = stpcpy (p, nis_local_directory ());
-      pwdtable = strdup (buf);
+      pwdtable = malloc (sizeof (key) + len_local_dir);
       if (pwdtable == NULL)
         return NSS_STATUS_TRYAGAIN;
-      pwdtablelen = strlen (pwdtable);
+
+      pwdtablelen = ((char *) mempcpy (mempcpy (pwdtable,
+                                               key, sizeof (key) - 1),
+                                      local_dir, len_local_dir + 1)
+                    - pwdtable) - 1;
+
+      /* *Maybe* (I'm no NIS expert) we have to duplicate the `local_dir'
+        value since it might change during our work.  So add a test here.  */
+      assert (pwdtablelen == sizeof (key) + len_local_dir);
     }
 
   ent->blacklist.current = 0;
@@ -287,8 +298,8 @@ _nss_compat_endspent (void)
 
 
 static enum nss_status
-getspent_next_nis_netgr (struct spwd *result, ent_t *ent, char *group,
-                        char *buffer, size_t buflen)
+getspent_next_nis_netgr (const char *name, struct spwd *result, ent_t *ent,
+                        char *group, char *buffer, size_t buflen)
 {
   struct parser_data *data = (void *) buffer;
   char *ypdomain, *host, *user, *domain, *outval, *p, *p2;
@@ -332,6 +343,11 @@ getspent_next_nis_netgr (struct spwd *result, ent_t *ent, char *group,
       if (domain != NULL && strcmp (ypdomain, domain) != 0)
        continue;
 
+      /* If name != NULL, we are called from getpwnam */
+      if (name != NULL)
+       if (strcmp (user, name) != 0)
+         continue;
+
       if (yp_match (ypdomain, "shadow.byname", user,
                    strlen (user), &outval, &outvallen)
          != YPERR_SUCCESS)
@@ -357,6 +373,9 @@ getspent_next_nis_netgr (struct spwd *result, ent_t *ent, char *group,
 
       if (parse_res)
        {
+         /* Store the User in the blacklist for the "+" at the end of
+            /etc/passwd */
+         blacklist_store_name (result->sp_namp, ent);
          copy_spwd_changes (result, &ent->pwd, p2, p2len);
          break;
        }
@@ -366,8 +385,9 @@ getspent_next_nis_netgr (struct spwd *result, ent_t *ent, char *group,
 }
 
 static enum nss_status
-getspent_next_nisplus_netgr (struct spwd *result, ent_t *ent, char *group,
-                             char *buffer, size_t buflen)
+getspent_next_nisplus_netgr (const char *name, struct spwd *result,
+                            ent_t *ent, char *group, char *buffer,
+                            size_t buflen)
 {
   char *ypdomain, *host, *user, *domain, *p2;
   int status, parse_res;
@@ -412,6 +432,11 @@ getspent_next_nisplus_netgr (struct spwd *result, ent_t *ent, char *group,
       if (domain != NULL && strcmp (ypdomain, domain) != 0)
         continue;
 
+      /* If name != NULL, we are called from getpwnam */
+      if (name != NULL)
+       if (strcmp (user, name) != 0)
+         continue;
+
       p2len = spwd_need_buflen (&ent->pwd);
       if (p2len > buflen)
         {
@@ -440,7 +465,10 @@ getspent_next_nisplus_netgr (struct spwd *result, ent_t *ent, char *group,
 
       if (parse_res)
         {
-          copy_spwd_changes (result, &ent->pwd, p2, p2len);
+         /* Store the User in the blacklist for the "+" at the end of
+            /etc/passwd */
+         blacklist_store_name (result->sp_namp, ent);
+         copy_spwd_changes (result, &ent->pwd, p2, p2len);
           break;
         }
     }
@@ -448,16 +476,6 @@ getspent_next_nisplus_netgr (struct spwd *result, ent_t *ent, char *group,
   return NSS_STATUS_SUCCESS;
 }
 
-static enum nss_status
-getspent_next_netgr (struct spwd *result, ent_t *ent, char *group,
-                     char *buffer, size_t buflen)
-{
-  if (use_nisplus)
-    return getspent_next_nisplus_netgr (result, ent, group, buffer, buflen);
-  else
-    return getspent_next_nis_netgr (result, ent, group, buffer, buflen);
-}
-
 static enum nss_status
 getspent_next_nisplus (struct spwd *result, ent_t *ent, char *buffer,
                        size_t buflen)
@@ -635,8 +653,8 @@ getspent_next_nis (struct spwd *result, ent_t *ent,
 
 /* This function handle the +user entrys in /etc/shadow */
 static enum nss_status
-getspent_next_file_plususer (struct spwd *result, char *buffer,
-                             size_t buflen)
+getspnam_plususer (const char *name, struct spwd *result, char *buffer,
+                  size_t buflen)
 {
   struct parser_data *data = (void *) buffer;
   struct spwd pwd;
@@ -660,9 +678,9 @@ getspent_next_file_plususer (struct spwd *result, char *buffer,
   if (use_nisplus) /* Do the NIS+ query here */
     {
       nis_result *res;
-      char buf[strlen (result->sp_namp) + 24 + pwdtablelen];
+      char buf[strlen (name) + 24 + pwdtablelen];
 
-      sprintf(buf, "[name=%s],%s", &result->sp_namp[1], pwdtable);
+      sprintf(buf, "[name=%s],%s", name, pwdtable);
       res = nis_list(buf, 0, NULL, NULL);
       if (niserr2nss (res->status) != NSS_STATUS_SUCCESS)
         {
@@ -681,24 +699,28 @@ getspent_next_file_plususer (struct spwd *result, char *buffer,
     }
   else /* Use NIS */
     {
-      char *domain;
-      char *outval;
+      char *domain, *outval, *ptr;
       int outvallen;
 
       if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
         return NSS_STATUS_TRYAGAIN;
 
-      if (yp_match (domain, "passwd.byname", &result->sp_namp[1],
-                    strlen (result->sp_namp) - 1, &outval, &outvallen)
+      if (yp_match (domain, "shadow.byname", name, strlen (name),
+                   &outval, &outvallen)
           != YPERR_SUCCESS)
         return NSS_STATUS_TRYAGAIN;
-      p = strncpy (buffer, outval,
-                   buflen < (size_t) outvallen ? buflen : (size_t) outvallen);
+      ptr = strncpy (buffer, outval, buflen < (size_t) outvallen ?
+                    buflen : (size_t) outvallen);
+      buffer[buflen < (size_t) outvallen ? buflen : (size_t) outvallen] = '\0';
       free (outval);
-      while (isspace (*p))
-        p++;
-      if ((parse_res = _nss_files_parse_spent (p, result, data, buflen)) == -1)
-       return NSS_STATUS_TRYAGAIN;
+      while (isspace (*ptr))
+        ptr++;
+      if ((parse_res = _nss_files_parse_spent (ptr, result, data, buflen))
+         == -1)
+       {
+         __set_errno (ERANGE);
+         return NSS_STATUS_TRYAGAIN;
+       }
     }
 
   if (parse_res)
@@ -790,8 +812,14 @@ getspent_next_file (struct spwd *result, ent_t *ent,
          ent->first = TRUE;
          copy_spwd_changes (&ent->pwd, result, NULL, 0);
 
-         status = getspent_next_netgr (result, ent, &result->sp_namp[2],
-                                       buffer, buflen);
+         if (use_nisplus)
+           status = getspent_next_nisplus_netgr (NULL, result, ent,
+                                                 &result->sp_namp[2],
+                                                 buffer, buflen);
+         else
+           status = getspent_next_nis_netgr (NULL, result, ent,
+                                             &result->sp_namp[2],
+                                             buffer, buflen);
          if (status == NSS_STATUS_RETURN)
            continue;
          else
@@ -812,7 +840,11 @@ getspent_next_file (struct spwd *result, ent_t *ent,
        {
           enum nss_status status;
 
-          status = getspent_next_file_plususer (result, buffer, buflen);
+         /* Store the User in the blacklist for the "+" at the end of
+            /etc/passwd */
+         blacklist_store_name (&result->sp_namp[1], ent);
+          status = getspnam_plususer (&result->sp_namp[1], result, buffer,
+                                     buflen);
           if (status == NSS_STATUS_SUCCESS) /* We found the entry. */
             break;
           else
@@ -850,21 +882,26 @@ internal_getspent_r (struct spwd *pw, ent_t *ent,
 
       /* We are searching members in a netgroup */
       /* Since this is not the first call, we don't need the group name */
-      status = getspent_next_netgr (pw, ent, NULL, buffer, buflen);
+      if (use_nisplus)
+       status = getspent_next_nisplus_netgr (NULL, pw, ent, NULL, buffer,
+                                             buflen);
+      else
+       status = getspent_next_nis_netgr (NULL, pw, ent, NULL, buffer, buflen);
       if (status == NSS_STATUS_RETURN)
        return getspent_next_file (pw, ent, buffer, buflen);
       else
        return status;
     }
-  else if (ent->nis)
-    {
-      if (use_nisplus)
-       return getspent_next_nisplus (pw, ent, buffer, buflen);
-      else
-       return getspent_next_nis (pw, ent, buffer, buflen);
-    }
   else
-    return getspent_next_file (pw, ent, buffer, buflen);
+    if (ent->nis)
+      {
+       if (use_nisplus)
+         return getspent_next_nisplus (pw, ent, buffer, buflen);
+       else
+         return getspent_next_nis (pw, ent, buffer, buflen);
+      }
+    else
+      return getspent_next_file (pw, ent, buffer, buflen);
 }
 
 enum nss_status
@@ -892,6 +929,147 @@ _nss_compat_getspent_r (struct spwd *pwd, char *buffer, size_t buflen)
   return status;
 }
 
+/* Searches in /etc/passwd and the NIS/NIS+ map for a special user */
+static enum nss_status
+internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent,
+                    char *buffer, size_t buflen)
+{
+  struct parser_data *data = (void *) buffer;
+
+  while (1)
+    {
+      fpos_t pos;
+      char *p;
+      int parse_res;
+
+      do
+       {
+         fgetpos (ent->stream, &pos);
+         p = fgets (buffer, buflen, ent->stream);
+         if (p == NULL)
+           return NSS_STATUS_NOTFOUND;
+
+         /* Terminate the line for any case.  */
+         buffer[buflen - 1] = '\0';
+
+         /* Skip leading blanks.  */
+         while (isspace (*p))
+           ++p;
+       }
+      while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines.  */
+            /* Parse the line.  If it is invalid, loop to
+               get the next line of the file to parse.  */
+            !(parse_res = _nss_files_parse_spent (p, result, data, buflen)));
+
+      if (parse_res == -1)
+       {
+         /* The parser ran out of space.  */
+         fsetpos (ent->stream, &pos);
+         __set_errno (ERANGE);
+         return NSS_STATUS_TRYAGAIN;
+       }
+
+      /* This is a real entry.  */
+      if (result->sp_namp[0] != '+' && result->sp_namp[0] != '-')
+       {
+         if (strcmp (result->sp_namp, name) == 0)
+           return NSS_STATUS_SUCCESS;
+         else
+           continue;
+       }
+
+      /* -@netgroup */
+      if (result->sp_namp[0] == '-' && result->sp_namp[1] == '@'
+         && result->sp_namp[2] != '\0')
+       {
+         char buf2[1024];
+         char *user, *host, *domain;
+         struct __netgrent netgrdata;
+
+         bzero (&netgrdata, sizeof (struct __netgrent));
+         __internal_setnetgrent (&result->sp_namp[2], &netgrdata);
+         while (__internal_getnetgrent_r (&host, &user, &domain,
+                                          &netgrdata, buf2, sizeof (buf2)))
+           {
+             if (user != NULL && user[0] != '-')
+               if (strcmp (user, name) == 0)
+                 return NSS_STATUS_NOTFOUND;
+           }
+         __internal_endnetgrent (&netgrdata);
+         continue;
+       }
+
+      /* +@netgroup */
+      if (result->sp_namp[0] == '+' && result->sp_namp[1] == '@'
+         && result->sp_namp[2] != '\0')
+       {
+         char buf[strlen (result->sp_namp)];
+         int status;
+
+         strcpy (buf, &result->sp_namp[2]);
+         ent->netgroup = TRUE;
+         ent->first = TRUE;
+         copy_spwd_changes (&ent->pwd, result, NULL, 0);
+
+         do
+           {
+             if (use_nisplus)
+               status = getspent_next_nisplus_netgr (name, result, ent, buf,
+                                                     buffer, buflen);
+             else
+               status = getspent_next_nis_netgr (name, result, ent, buf,
+                                                 buffer, buflen);
+             if (status == NSS_STATUS_RETURN)
+               continue;
+
+             if (status == NSS_STATUS_SUCCESS &&
+                 strcmp (result->sp_namp, name) == 0)
+               return NSS_STATUS_SUCCESS;
+           } while (status == NSS_STATUS_SUCCESS);
+         continue;
+       }
+
+      /* -user */
+      if (result->sp_namp[0] == '-' && result->sp_namp[1] != '\0'
+         && result->sp_namp[1] != '@')
+       {
+         if (strcmp (&result->sp_namp[1], name) == 0)
+           return NSS_STATUS_NOTFOUND;
+         else
+           continue;
+       }
+
+      /* +user */
+      if (result->sp_namp[0] == '+' && result->sp_namp[1] != '\0'
+         && result->sp_namp[1] != '@')
+       {
+         if (strcmp (name, &result->sp_namp[1]) == 0)
+           {
+             enum nss_status status;
+
+             status = getspnam_plususer (name, result, buffer, buflen);
+             if (status == NSS_STATUS_RETURN)
+               /* We couldn't parse the entry */
+               return NSS_STATUS_NOTFOUND;
+             else
+               return status;
+           }
+       }
+
+      /* +:... */
+      if (result->sp_namp[0] == '+' && result->sp_namp[1] == '\0')
+       {
+         enum nss_status status;
+
+         status = getspnam_plususer (name, result, buffer, buflen);
+         if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */
+           return NSS_STATUS_NOTFOUND;
+         else
+           return status;
+       }
+    }
+  return NSS_STATUS_SUCCESS;
+}
 
 enum nss_status
 _nss_compat_getspnam_r (const char *name, struct spwd *pwd,
@@ -914,12 +1092,10 @@ _nss_compat_getspnam_r (const char *name, struct spwd *pwd,
   if (status != NSS_STATUS_SUCCESS)
     return status;
 
-  while ((status = internal_getspent_r (pwd, &ent, buffer, buflen))
-        == NSS_STATUS_SUCCESS)
-    if (strcmp (pwd->sp_namp, name) == 0)
-      break;
+  status = internal_getspnam_r (name, pwd, &ent, buffer, buflen);
 
   internal_endspent (&ent);
+
   return status;
 }
 
index c8db8a8813940b0aa8213a5e7473d9a84b168bc2..5bef8d17d205a328ab15454015be1f135671a05b 100644 (file)
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include <fcntl.h>
 #include <string.h>
 #include <unistd.h>
-#include <fcntl.h>
-#include <bits/libc-lock.h>
-#include <rpc/auth.h>
 #include <rpc/rpc.h>
 #include <rpcsvc/nis.h>
 #include <rpcsvc/yp.h>
 #include <rpcsvc/ypclnt.h>
 #include <rpcsvc/ypupd.h>
+#include <bits/libc-lock.h>
 
 struct dom_binding
   {
@@ -39,7 +38,8 @@ struct dom_binding
   };
 typedef struct dom_binding dom_binding;
 
-static struct timeval TIMEOUT = {25, 0};
+static struct timeval RPCTIMEOUT = {25, 0};
+static struct timeval UDPTIMEOUT = {5, 0};
 static int const MAXTRIES = 5;
 static char __ypdomainname[NIS_MAXNAMELEN + 1] = "\0";
 __libc_lock_define_initialized (static, ypbindlist_lock)
@@ -47,28 +47,28 @@ static dom_binding *__ypbindlist = NULL;
 
 
 static int
-__yp_bind (const char *domain, dom_binding ** ypdb)
+__yp_bind (const char *domain, dom_binding **ypdb)
 {
   struct sockaddr_in clnt_saddr;
   struct ypbind_resp ypbr;
-  dom_binding *ysd;
+  dom_binding *ysd = NULL;
   int clnt_sock;
   CLIENT *client;
   int is_new = 0;
   int try;
 
-  if (ypdb != NULL)
-    *ypdb = NULL;
-
   if ((domain == NULL) || (strlen (domain) == 0))
     return YPERR_BADARGS;
 
-  ysd = __ypbindlist;
-  while (ysd != NULL)
+  if (ypdb != NULL)
     {
-      if (strcmp (domain, ysd->dom_domain) == 0)
-        break;
-      ysd = ysd->dom_pnext;
+      ysd = *ypdb;
+      while (ysd != NULL)
+       {
+         if (strcmp (domain, ysd->dom_domain) == 0)
+           break;
+         ysd = ysd->dom_pnext;
+       }
     }
 
   if (ysd == NULL)
@@ -128,7 +128,7 @@ __yp_bind (const char *domain, dom_binding ** ypdb)
           if (clnt_call (client, YPBINDPROC_DOMAIN,
                          (xdrproc_t) xdr_domainname, (caddr_t) &domain,
                          (xdrproc_t) xdr_ypbind_resp,
-                         (caddr_t) &ypbr, TIMEOUT) != RPC_SUCCESS)
+                         (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS)
             {
               clnt_destroy (client);
              close (clnt_sock);
@@ -142,28 +142,12 @@ __yp_bind (const char *domain, dom_binding ** ypdb)
 
           if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
             {
-              switch (ypbr.ypbind_resp_u.ypbind_error)
-                {
-                case YPBIND_ERR_ERR:
-                  fputs (_("YPBINDPROC_DOMAIN: Internal error\n"), stderr);
-                  break;
-                case YPBIND_ERR_NOSERV:
-                  fprintf (stderr,
-                           _("YPBINDPROC_DOMAIN: No server for domain %s\n"),
-                           domain);
-                  break;
-                case YPBIND_ERR_RESC:
-                  fputs (_("YPBINDPROC_DOMAIN: Resource allocation failure\n"),
-                         stderr);
-                  break;
-                default:
-                  fputs (_("YPBINDPROC_DOMAIN: Unknown error\n"), stderr);
-                  break;
-                }
-              if (is_new)
-                free (ysd);
-              return YPERR_DOMAIN;
-            }
+             fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"),
+                      ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
+             if (is_new)
+               free (ysd);
+             return YPERR_DOMAIN;
+           }
           memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
           ysd->dom_server_addr.sin_family = AF_INET;
           memcpy (&ysd->dom_server_addr.sin_port,
@@ -184,7 +168,7 @@ __yp_bind (const char *domain, dom_binding ** ypdb)
        }
       ysd->dom_socket = RPC_ANYSOCK;
       ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
-                                        TIMEOUT, &ysd->dom_socket);
+                                        UDPTIMEOUT, &ysd->dom_socket);
       if (ysd->dom_client == NULL)
         ysd->dom_vers = -1;
 
@@ -195,15 +179,12 @@ __yp_bind (const char *domain, dom_binding ** ypdb)
   if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
     perror (_("fcntl: F_SETFD"));
 
-  if (is_new)
+  if (is_new && ypdb != NULL)
     {
-      ysd->dom_pnext = __ypbindlist;
-      __ypbindlist = ysd;
+      ysd->dom_pnext = *ypdb;
+      *ypdb = ysd;
     }
 
-  if (NULL != ypdb)
-    *ypdb = ysd;
-
   return YPERR_SUCCESS;
 }
 
@@ -220,36 +201,67 @@ do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
           caddr_t req, xdrproc_t xres, caddr_t resp)
 {
   dom_binding *ydb = NULL;
+  bool_t use_ypbindlist = FALSE;
   int try, result;
 
   try = 0;
   result = YPERR_YPERR;
 
-  while (try < MAXTRIES && result != RPC_SUCCESS)
+  __libc_lock_lock (ypbindlist_lock);
+  if (__ypbindlist != NULL)
     {
-      __libc_lock_lock (ypbindlist_lock);
+      ydb = __ypbindlist;
+      while (ydb != NULL)
+        {
+          if (strcmp (domain, ydb->dom_domain) == 0)
+            break;
+          ydb = ydb->dom_pnext;
+        }
+      if (ydb != NULL)
+       use_ypbindlist = TRUE;
+      else
+       __libc_lock_unlock (ypbindlist_lock);
+    }
+  else
+    __libc_lock_unlock (ypbindlist_lock);
 
+  while (try < MAXTRIES && result != RPC_SUCCESS)
+    {
       if (__yp_bind (domain, &ydb) != 0)
        {
-         __libc_lock_unlock (ypbindlist_lock);
+         if (use_ypbindlist)
+           __libc_lock_unlock (ypbindlist_lock);
          return YPERR_DOMAIN;
        }
 
       result = clnt_call (ydb->dom_client, prog,
-                         xargs, req, xres, resp, TIMEOUT);
+                         xargs, req, xres, resp, RPCTIMEOUT);
 
       if (result != RPC_SUCCESS)
        {
          clnt_perror (ydb->dom_client, "do_ypcall: clnt_call");
          ydb->dom_vers = -1;
-         __yp_unbind (ydb);
+         if (!use_ypbindlist)
+           {
+             __yp_unbind (ydb);
+             free (ydb);
+             ydb = NULL;
+           }
          result = YPERR_RPC;
        }
-
-      __libc_lock_unlock (ypbindlist_lock);
-
       try++;
     }
+  if (use_ypbindlist)
+    {
+      __libc_lock_unlock (ypbindlist_lock);
+      use_ypbindlist = FALSE;
+    }
+  else
+    {
+      __yp_unbind (ydb);
+      free (ydb);
+      ydb = NULL;
+    }
 
   return result;
 }
@@ -261,7 +273,7 @@ yp_bind (const char *indomain)
 
   __libc_lock_lock (ypbindlist_lock);
 
-  status = __yp_bind (indomain, NULL);
+  status = __yp_bind (indomain, &__ypbindlist);
 
   __libc_lock_unlock (ypbindlist_lock);
 
@@ -597,7 +609,7 @@ yp_all (const char *indomain, const char *inmap,
        const struct ypall_callback *incallback)
 {
   struct ypreq_nokey req;
-  dom_binding *ydb;
+  dom_binding *ydb = NULL;
   int try, result;
   struct sockaddr_in clnt_sin;
   CLIENT *clnt;
@@ -613,11 +625,8 @@ yp_all (const char *indomain, const char *inmap,
 
   while (try < MAXTRIES && result != RPC_SUCCESS)
     {
-      __libc_lock_lock (ypbindlist_lock);
-
       if (__yp_bind (indomain, &ydb) != 0)
        {
-         __libc_lock_unlock (ypbindlist_lock);
          return YPERR_DOMAIN;
        }
 
@@ -629,7 +638,6 @@ yp_all (const char *indomain, const char *inmap,
       if (clnt == NULL)
        {
          puts (_("yp_all: clnttcp_create failed"));
-         __libc_lock_unlock (ypbindlist_lock);
          return YPERR_PMAP;
        }
       req.domain = (char *) indomain;
@@ -640,7 +648,7 @@ yp_all (const char *indomain, const char *inmap,
 
       result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey,
                          (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
-                         (caddr_t) &status, TIMEOUT);
+                         (caddr_t) &status, RPCTIMEOUT);
 
       clnt_destroy (clnt);
       close (clnt_sock);
@@ -648,13 +656,12 @@ yp_all (const char *indomain, const char *inmap,
        {
          clnt_perror (ydb->dom_client, "yp_all: clnt_call");
          __yp_unbind (ydb);
+         free (ydb);
          result = YPERR_RPC;
        }
       else
        result = YPERR_SUCCESS;
 
-      __libc_lock_unlock (ypbindlist_lock);
-
       if (status != YP_NOMORE)
        return ypprot_err (status);
       try++;
@@ -854,7 +861,7 @@ yp_update (char *domain, char *map, unsigned ypop,
 
 again:
   r = clnt_call (clnt, ypop, xdr_argument, (caddr_t) &args,
-                (xdrproc_t) xdr_u_int, (caddr_t) &res, TIMEOUT);
+                (xdrproc_t) xdr_u_int, (caddr_t) &res, RPCTIMEOUT);
 
   if (r == RPC_AUTHERROR)
     {
index f1fecdb2759b3ce805012714827325e63b29d004..30f381320e1713f8d8a328c11f907e6abb39e768 100644 (file)
@@ -275,7 +275,10 @@ parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec,
       {
       case L_('h'):
        /* int's are short int's.  */
-       spec->info.is_short = 1;
+       if (spec->info.is_short == 0)
+         spec->info.is_short = 1;
+       else
+         spec->info.is_short = 2;
        break;
       case L_('l'):
        /* int's are long int's.  */
index d97476b13a0ae4eb225fe55605a9278313883099..de30c9a20ca597a287841e278995a2df96567438 100644 (file)
@@ -26,7 +26,7 @@
 #include <bits/libc-lock.h>
 #include <sys/param.h>
 #include "_itoa.h"
-#include "../locale/localeinfo.h"
+#include <locale/localeinfo.h>
 
 /* This code is shared between the standard stdio implementation found
    in GNU C library and the libio implementation originally found in
@@ -364,8 +364,39 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       REF (form_wcharacter),   /* for 'C' */                                 \
       REF (form_floathex)      /* for 'A', 'a' */                            \
     };                                                                       \
-    /* Step 3: after processing first 'l' modifier.  */                              \
-    static const void *step3_jumps[27] =                                     \
+    /* Step 3a: after processing first 'h' modifier.  */                     \
+    static const void *step3a_jumps[27] =                                    \
+    {                                                                        \
+      REF (form_unknown),                                                    \
+      REF (form_unknown),      /* for ' ' */                                 \
+      REF (form_unknown),      /* for '+' */                                 \
+      REF (form_unknown),      /* for '-' */                                 \
+      REF (form_unknown),      /* for '<hash>' */                            \
+      REF (form_unknown),      /* for '0' */                                 \
+      REF (form_unknown),      /* for '\'' */                                \
+      REF (form_unknown),      /* for '*' */                                 \
+      REF (form_unknown),      /* for '1'...'9' */                           \
+      REF (form_unknown),      /* for '.' */                                 \
+      REF (mod_halfhalf),      /* for 'h' */                                 \
+      REF (form_unknown),      /* for 'l' */                                 \
+      REF (form_unknown),      /* for 'L', 'q' */                            \
+      REF (form_unknown),      /* for 'Z' */                                 \
+      REF (form_percent),      /* for '%' */                                 \
+      REF (form_integer),      /* for 'd', 'i' */                            \
+      REF (form_unsigned),     /* for 'u' */                                 \
+      REF (form_octal),                /* for 'o' */                                 \
+      REF (form_hexa),         /* for 'X', 'x' */                            \
+      REF (form_unknown),      /* for 'E', 'e', 'f', 'G', 'g' */             \
+      REF (form_unknown),      /* for 'c' */                                 \
+      REF (form_unknown),      /* for 's', 'S' */                            \
+      REF (form_unknown),      /* for 'p' */                                 \
+      REF (form_number),       /* for 'n' */                                 \
+      REF (form_unknown),      /* for 'm' */                                 \
+      REF (form_unknown),      /* for 'C' */                                 \
+      REF (form_unknown)       /* for 'A', 'a' */                            \
+    };                                                                       \
+    /* Step 3b: after processing first 'l' modifier.  */                     \
+    static const void *step3b_jumps[27] =                                    \
     {                                                                        \
       REF (form_unknown),                                                    \
       REF (form_unknown),      /* for ' ' */                                 \
@@ -463,7 +494,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
          if (fspec == NULL)                                                  \
            if (is_long)                                                      \
              signed_number = va_arg (ap, long int);                          \
-           else        /* `short int' will be promoted to `int'.  */         \
+           else  /* `char' and `short int' will be promoted to `int'.  */    \
              signed_number = va_arg (ap, int);                               \
          else                                                                \
            if (is_long)                                                      \
@@ -496,7 +527,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
                                                                              \
     LABEL (unsigned_number):     /* Unsigned number of base BASE.  */        \
                                                                              \
-      /* ANSI specifies the `+' and ` ' flags only for signed                \
+      /* ISO specifies the `+' and ` ' flags only for signed                 \
         conversions.  */                                                     \
       is_negative = 0;                                                       \
       showsign = 0;                                                          \
@@ -547,6 +578,9 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
          else                                                                \
            if (is_long)                                                      \
              number.word = args_value[fspec->data_arg].pa_u_long_int;        \
+           else if (is_char)                                                 \
+             number.word = (unsigned char)                                   \
+               args_value[fspec->data_arg].pa_char;                          \
            else if (!is_short)                                               \
              number.word = args_value[fspec->data_arg].pa_u_int;             \
            else                                                              \
@@ -989,6 +1023,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       int is_long_double = 0; /* Argument is long double/ long long int.  */
       int is_short = 0;        /* Argument is long int.  */
       int is_long = 0; /* Argument is short int.  */
+      int is_char = 0; /* Argument is promoted (unsigned) char.  */
       int width = 0;   /* Width of output; 0 means none specified.  */
       int prec = -1;   /* Precision of output; -1 means none specified.  */
       char pad = ' ';  /* Padding character.  */
@@ -1097,16 +1132,21 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
        prec = 0;
       JUMP (*f, step2_jumps);
 
-      /* Process 'h' modifier.  No other modifier is allowed to
-        follow.  */
+      /* Process 'h' modifier.  There might another 'h' following.  */
     LABEL (mod_half):
       is_short = 1;
+      JUMP (*++f, step3a_jumps);
+
+      /* Process 'hh' modifier.  */
+    LABEL (mod_halfhalf):
+      is_short = 0;
+      is_char = 1;
       JUMP (*++f, step4_jumps);
 
-      /* Process 'l' modifier.  There might another 'l' follow.  */
+      /* Process 'l' modifier.  There might another 'l' following.  */
     LABEL (mod_long):
       is_long = 1;
-      JUMP (*++f, step3_jumps);
+      JUMP (*++f, step3b_jumps);
 
       /* Process 'L', 'q', or 'll' modifier.  No other modifier is
         allowed to follow.  */
@@ -1320,7 +1360,8 @@ do_positional:
        int showsign = specs[nspecs_done].info.showsign;
        int group = specs[nspecs_done].info.group;
        int is_long_double = specs[nspecs_done].info.is_long_double;
-       int is_short = specs[nspecs_done].info.is_short;
+       int is_short = specs[nspecs_done].info.is_short == 1;
+       int is_char = specs[nspecs_done].info.is_short == 2;
        int is_long = specs[nspecs_done].info.is_long;
        int width = specs[nspecs_done].info.width;
        int prec = specs[nspecs_done].info.prec;
index bce319eeaf3dae09432a27935a42c05c7adf132f..b9fc87679be3dfa2625e98f3d31b088e52b9dcb9 100644 (file)
@@ -44,8 +44,9 @@
 # define WIDTH         0x040   /* width was given */
 # define GROUP         0x080   /* ': group numbers */
 # define MALLOC                0x100   /* a: malloc strings */
+# define CHAR          0x200   /* hh: char */
 
-# define TYPEMOD       (LONG|LONGDBL|SHORT)
+# define TYPEMOD       (LONG|LONGDBL|SHORT|CHAR)
 
 
 #ifdef USE_IN_LIBIO
@@ -400,13 +401,19 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
          {
          case 'h':
            /* int's are short int's.  */
-           if (flags & TYPEMOD)
+           if (flags & (LONG|LONGDBL|CHAR))
              /* Signal illegal format element.  */
              conv_error ();
-           flags |= SHORT;
+           if (flags & SHORT)
+             {
+               flags &= ~SHORT;
+               flags |= CHAR;
+             }
+           else
+             flags |= SHORT;
            break;
          case 'l':
-           if (flags & (SHORT|LONGDBL))
+           if (flags & (SHORT|LONGDBL|CHAR))
              conv_error ();
            else if (flags & LONG)
              {
@@ -883,6 +890,8 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
                  else if (flags & SHORT)
                    *ARG (unsigned short int *)
                      = (unsigned short int) num.ul;
+                 else if (flags & CHAR)
+                   *ARG (unsigned char *) = (unsigned char) num.ul;
                  else
                    *ARG (unsigned int *) = (unsigned int) num.ul;
                }
@@ -894,6 +903,8 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
                    *ARG (long int *) = num.l;
                  else if (flags & SHORT)
                    *ARG (short int *) = (short int) num.l;
+                 else if (flags & CHAR)
+                   *ARG (signed char *) = (signed char) num.ul;
                  else
                    *ARG (int *) = (int) num.l;
                }
index b5b85aa26ede941165bfd789780da1bf89b264df..1ed1e2521bd15102a6be30e1fbab45b93cefe97d 100644 (file)
@@ -33,14 +33,16 @@ DEFINE_HOOK (__libc_atexit, (void))
 void
 exit (int status)
 {
-  const struct exit_function_list *l;
-
-  for (l = __exit_funcs; l != NULL; l = l->next)
+  /* We do it this way to handle recursive calls to exit () made by
+     the functions registered with `atexit' and `on_exit'. We call
+     everyone on the list and use the status value in the last
+     exit (). */
+  for (; __exit_funcs; __exit_funcs = __exit_funcs->next)
     {
-      size_t i = l->idx;
-      while (i-- > 0)
+      while ((__exit_funcs->idx)-- > 0)
        {
-         const struct exit_function *const f = &l->fns[i];
+         const struct exit_function *const f =
+           &__exit_funcs->fns[__exit_funcs->idx];
          switch (f->flavor)
            {
            case ef_free:
index d35dc2d5acac93b946b95be8e34ed20601e7d066..cd78ef0df406db4f02aa8d0c03a8a42ca70b72b3 100644 (file)
@@ -712,10 +712,18 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
                {
                  FLOAT result;
 
-                 /* Overflow or underflow.  */
-                 __set_errno (ERANGE);
-                 result = (exp_negative ? 0.0 :
-                           negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL);
+                 /* We have to take care for special situation: a joker
+                    might have written "0.0e100000" which is in fact
+                    zero.  */
+                 if (lead_zero == -1)
+                   result = negative ? -0.0 : 0.0;
+                 else
+                   {
+                     /* Overflow or underflow.  */
+                     __set_errno (ERANGE);
+                     result = (exp_negative ? 0.0 :
+                               negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL);
+                   }
 
                  /* Accept all following digits as part of the exponent.  */
                  do
@@ -756,7 +764,7 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
     *endptr = (STRING_TYPE *) cp;
 
   if (dig_no == 0)
-    return 0.0;
+    return negative ? -0.0 : 0.0;
 
   if (lead_zero)
     {
index c239d50ae84215e468d3ea14247aafc0d1faf587..d06ec4d581a1f9f3ef8fcad32d616982c83038bd 100644 (file)
@@ -136,7 +136,7 @@ main (int argc, char ** argv)
   errno = 0;
   if (realpath ("", buf) != NULL || errno != ENOENT)
     {
-      printf ("%s: expected return value NULL and set errno to ENOENT",
+      printf ("%s: expected return value NULL and set errno to ENOENT"
              " for realpath(\"\",...)\n", argv[0]);
       ++errors;
     }
index 5d732a1b114e26dcd51959dca38d7db4c7725dc2..bef4be109e9e7581510ba1842bddea31feb90041 100644 (file)
@@ -41,6 +41,7 @@
 #include <features.h>
 #include <rpc/types.h>
 #include <rpc/xdr.h>
+#include <rpc/clnt.h>
 
 __BEGIN_DECLS
 
index 622c2c9de446e501a21a186cfcff8ef924c246b0..d1cb464b41733e3c06fb470435d670e2eadce6f8 100644 (file)
@@ -23,6 +23,7 @@
 #define        __Emath_defined 1
 
 # define EDOM  XXX     <--- fill in what is actually needed
+# define EILSEQ        XXX     <--- fill in what is actually needed
 # define ERANGE        XXX     <--- fill in what is actually needed
 #endif
 
index f58c65b7f64f1e16788a0d3d898440c1cd0adf98..d4c5c87b15fdfc984359323622e9a7fcb113620e 100644 (file)
@@ -91,7 +91,6 @@ setenv (name, value, replace)
   if (__environ == NULL || *ep == NULL)
     {
       char **new_environ;
-      char *tmp;
 
       if (__environ == last_environ && __environ != NULL)
        /* We allocated this space; we can extend it.  */
@@ -120,9 +119,11 @@ setenv (name, value, replace)
                size * sizeof (char *));
 
 #ifdef _LIBC
-      tmp = __mempcpy (new_environ[size], name, namelen);
-      *tmp++ = '=';
-      __mempcpy (tmp, value, vallen);
+      {
+       char *tmp = __mempcpy (new_environ[size], name, namelen);
+       *tmp++ = '=';
+       __mempcpy (tmp, value, vallen);
+      }
 #else
       memcpy (new_environ[size], name, namelen);
       new_environ[size][namelen] = '=';
diff --git a/sysdeps/i386/i586/memcpy.S b/sysdeps/i386/i586/memcpy.S
new file mode 100644 (file)
index 0000000..9116c8d
--- /dev/null
@@ -0,0 +1,108 @@
+/* Highly optimized version for i586.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <sysdep.h>
+#include "asm-syntax.h"
+
+/*
+   INPUT PARAMETERS:
+   dst          (sp + 4)
+   src          (sp + 8)
+   len         (sp + 12)
+*/
+
+
+        .text
+ENTRY (memcpy)
+       pushl   %edi
+       pushl   %esi
+
+       movl    12(%esp), %edi  /* dst */
+       movl    16(%esp), %esi  /* src */
+       movl    20(%esp), %ecx  /* len */
+       movl    %edi, %eax
+
+       /* We need this in any case.  */
+       cld
+
+       /* Cutoff for the big loop is a size of 32 bytes since otherwise
+          the loop will never be entered.  */
+       cmpl    $32, %ecx
+       jbe     L(1)
+
+       negl    %eax
+       andl    $3, %eax
+       subl    %eax, %ecx
+       xchgl   %eax, %ecx
+
+       rep; movsb
+
+       movl    %eax, %ecx
+       subl    $32, %ecx
+       js      L(2)
+
+       /* Read ahead to make sure we write in the cache since the stupid
+          i586 designers haven't implemented read-on-write-miss.  */
+       movl    (%edi), %eax
+L(3):  movl    28(%edi), %edx
+
+       /* Now correct the loop counter.  Please note that in the following
+          code the flags are not changed anymore.  */
+       subl    $32, %ecx
+
+       movl    (%esi), %eax
+       movl    4(%esi), %edx
+       movl    %eax, (%edi)
+       movl    %edx, 4(%edi)
+       movl    8(%esi), %eax
+       movl    12(%esi), %edx
+       movl    %eax, 8(%edi)
+       movl    %edx, 12(%edi)
+       movl    16(%esi), %eax
+       movl    20(%esi), %edx
+       movl    %eax, 16(%edi)
+       movl    %edx, 20(%edi)
+       movl    24(%esi), %eax
+       movl    28(%esi), %edx
+       movl    %eax, 24(%edi)
+       movl    %edx, 28(%edi)
+
+       leal    32(%esi), %esi
+       leal    32(%edi), %edi
+
+       jns     L(3)
+
+       /* Correct extra loop counter modification.  */
+L(2):  addl    $32, %ecx
+#ifndef memcpy
+       movl    12(%esp), %eax  /* dst */
+#endif
+
+L(1):  rep; movsb
+
+#ifdef memcpy
+       movl    %edi, %eax
+#endif
+
+       popl    %esi
+       popl    %edi
+
+       ret
+END (memcpy)
diff --git a/sysdeps/i386/i586/mempcpy.S b/sysdeps/i386/i586/mempcpy.S
new file mode 100644 (file)
index 0000000..03dc078
--- /dev/null
@@ -0,0 +1,4 @@
+#define memcpy __mempcpy
+#include <sysdeps/i386/i586/memcpy.S>
+
+weak_alias (__mempcpy, mempcpy)
index fb96a369b9e2b61de84b0cc5b36ec447a63a7d96..01bed355349fc5b355bc42e648c88af984a2f1c7 100644 (file)
@@ -1,5 +1,5 @@
 /* memset/bzero -- set memory area to CH/0
-   Highly optimized version for ix85, x>=5.
+   Highly optimized version for ix86, x>=5.
    Copyright (C) 1996, 1997 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Torbjorn Granlund, <tege@matematik.su.se>
index b62a1c9914ff94181f52d6573c0eff9a0006e53b..09d06a9158ac979ca3a7db0f76e234430eaddccc 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Developed at SunPro, a Sun Microsystems, Inc. business.
  * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice 
+ * software is freely granted, provided that this notice
  * is preserved.
  * ====================================================
  */
@@ -15,12 +15,12 @@ static char rcsid[] = "$NetBSD: e_asin.c,v 1.9 1995/05/12 04:57:22 jtc Exp $";
 #endif
 
 /* __ieee754_asin(x)
- * Method :                  
+ * Method :
  *     Since  asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ...
  *     we approximate asin(x) on [0,0.5] by
  *             asin(x) = x + x*x^2*R(x^2)
  *     where
- *             R(x^2) is a rational approximation of (asin(x)-x)/x^3 
+ *             R(x^2) is a rational approximation of (asin(x)-x)/x^3
  *     and its remez error is bounded by
  *             |(asin(x)-x)/x^3 - R(x^2)| < 2^(-58.75)
  *
@@ -49,9 +49,9 @@ static char rcsid[] = "$NetBSD: e_asin.c,v 1.9 1995/05/12 04:57:22 jtc Exp $";
 #include "math_private.h"
 
 #ifdef __STDC__
-static const double 
+static const double
 #else
-static double 
+static double
 #endif
 one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
 huge =  1.000e+300,
@@ -86,17 +86,18 @@ qS4 =  7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
            GET_LOW_WORD(lx,x);
            if(((ix-0x3ff00000)|lx)==0)
                    /* asin(1)=+-pi/2 with inexact */
-               return x*pio2_hi+x*pio2_lo;     
-           return (x-x)/(x-x);         /* asin(|x|>1) is NaN */   
+               return x*pio2_hi+x*pio2_lo;
+           return (x-x)/(x-x);         /* asin(|x|>1) is NaN */
        } else if (ix<0x3fe00000) {     /* |x|<0.5 */
            if(ix<0x3e400000) {         /* if |x| < 2**-27 */
                if(huge+x>one) return x;/* return x with inexact if x!=0*/
-           } else 
+           } else {
                t = x*x;
                p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
                q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
                w = p/q;
                return x+x*w;
+           }
        }
        /* 1> |x|>= 0.5 */
        w = one-fabs(x);
@@ -115,6 +116,6 @@ qS4 =  7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
            p  = 2.0*s*r-(pio2_lo-2.0*c);
            q  = pio4_hi-2.0*w;
            t  = pio4_hi-(p-q);
-       }    
-       if(hx>0) return t; else return -t;    
+       }
+       if(hx>0) return t; else return -t;
 }
index 21157d84e1c585b4571267e9b7b202681b444cba..5270f31144fbe5b372dcc0f2e59a02c9655843f3 100644 (file)
@@ -8,7 +8,7 @@
  *
  * Developed at SunPro, a Sun Microsystems, Inc. business.
  * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice 
+ * software is freely granted, provided that this notice
  * is preserved.
  * ====================================================
  */
@@ -21,9 +21,9 @@ static char rcsid[] = "$NetBSD: e_asinf.c,v 1.5 1995/05/12 04:57:25 jtc Exp $";
 #include "math_private.h"
 
 #ifdef __STDC__
-static const float 
+static const float
 #else
-static float 
+static float
 #endif
 one =  1.0000000000e+00, /* 0x3F800000 */
 huge =  1.000e+30,
@@ -55,18 +55,19 @@ qS4 =  7.7038154006e-02; /* 0x3d9dc62e */
        ix = hx&0x7fffffff;
        if(ix==0x3f800000) {
                /* asin(1)=+-pi/2 with inexact */
-           return x*pio2_hi+x*pio2_lo; 
+           return x*pio2_hi+x*pio2_lo;
        } else if(ix> 0x3f800000) {     /* |x|>= 1 */
-           return (x-x)/(x-x);         /* asin(|x|>1) is NaN */   
+           return (x-x)/(x-x);         /* asin(|x|>1) is NaN */
        } else if (ix<0x3f000000) {     /* |x|<0.5 */
            if(ix<0x32000000) {         /* if |x| < 2**-27 */
                if(huge+x>one) return x;/* return x with inexact if x!=0*/
-           } else 
+           } else {
                t = x*x;
                p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
                q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
                w = p/q;
                return x+x*w;
+           }
        }
        /* 1> |x|>= 0.5 */
        w = one-fabsf(x);
@@ -87,6 +88,6 @@ qS4 =  7.7038154006e-02; /* 0x3d9dc62e */
            p  = (float)2.0*s*r-(pio2_lo-(float)2.0*c);
            q  = pio4_hi-(float)2.0*w;
            t  = pio4_hi-(p-q);
-       }    
-       if(hx>0) return t; else return -t;    
+       }
+       if(hx>0) return t; else return -t;
 }
index 72d3eac17264be8952eaa14805b51aae8d4a13f2..aff7a3d9765c3aa3411969ff8f1845d5943c4fc0 100644 (file)
@@ -71,10 +71,10 @@ pi_lo   = -5.01655761266833202345176e-20L;/* 0xBFBE, 0xECE675D1, 0xFC8F8CBB */
        int32_t k,m,hx,hy,ix,iy;
        u_int32_t sx,sy,lx,ly;
 
-       EXTRACT_LDOUBLE_WORDS(sx,hx,lx,x);
+       GET_LDOUBLE_WORDS(sx,hx,lx,x);
        ix = sx&0x7fff;
        lx |= hx & 0x7fffffff;
-       EXTRACT_LDOUBLE_WORDS(sy,hy,ly,y);
+       GET_LDOUBLE_WORDS(sy,hy,ly,y);
        iy = sy&0x7fff;
        ly |= hy & 0x7fffffff;
        if(((2*ix|((lx|-lx)>>31))>0xfffe)||
index 3b2cd7c5e5ee489a10ede13c74565688c81a55a9..e721a6e8cdff659d504af0900f962d02d94b0d5e 100644 (file)
@@ -47,8 +47,8 @@ static long double zero = 0.0;
        u_int32_t sx,sex,sep,x0,x1,p0,p1;
        long double p_half;
 
-       EXTRACT_LDOUBLE_WORDS(sex,x0,x1,x);
-       EXTRACT_LDOUBLE_WORDS(sep,p0,p1,p);
+       GET_LDOUBLE_WORDS(sex,x0,x1,x);
+       GET_LDOUBLE_WORDS(sep,p0,p1,p);
        sx = sex&0x8000;
        sep &= 0x7fff;
        sex &= 0x7fff;
index 773be32995d9288a143498108e047cfb964d9d77..d53f3954baa2f48ac2596661fdb193ed9b96cd42 100644 (file)
@@ -51,8 +51,8 @@ static long double huge = 1.0e4930;
        if(j0<31) {
            if(j0<0) {  /* raise inexact if x != 0 */
                if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
-                   if(sx) {es=0x8000;i0=0;i1=0;}
-                   else if((i0|i1)!=0) { es=0x3fff;i0=0;i1=0;}
+                   if(sx) {se=0x8000;i0=0;i1=0;}
+                   else if((i0|i1)!=0) { se=0x3fff;i0=0;i1=0;}
                }
            } else {
                i = (0x7fffffff)>>j0;
index 0eb0bec9b84d32366306480400d103357fd98561..fb0c37e801bde023b5136b205c2529150a4c7902 100644 (file)
@@ -53,7 +53,7 @@ static long double huge = 1.0e4930;
                if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
                    if(sx==0) {se=0;i0=i1=0;}
                    else if(((se&0x7fff)|i0|i1)!=0)
-                       { se=0xbfff;i0;i1=0;}
+                       { se=0xbfff;i0=i1=0;}
                }
            } else {
                i = (0x7fffffff)>>j0;
@@ -62,6 +62,7 @@ static long double huge = 1.0e4930;
                    if(sx) {
                        if (j0>0) i0 += (0x80000000)>>j0;
                        else ++se;
+                   }
                    i0 &= (~i); i1=0;
                }
            }
index a50ba96952a2f6b73316bade524ec86bd8c902c8..8e70bcff36aca050eb2bdff3a0a65c83c4aba9c8 100644 (file)
@@ -55,27 +55,27 @@ __llrint (double x)
          w = two52[sx] + x;
          t = w - two52[sx];
          EXTRACT_WORDS (i0, i1, t);
-         i0 = i & 0xfffff;
-         i0 |= 0x100000;
          j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
+         i0 &= 0xfffff;
+         i0 |= 0x100000;
 
          result = i0 >> (20 - j0);
        }
     }
-  else if (j0 < (int32_t) (8 * sizeof (long long int)))
+  else if (j0 < (int32_t) (8 * sizeof (long long int)) - 1)
     {
       if (j0 >= 52)
-       result = ((long long int) i0 << (j0 - 20)) | (i1 << (j0 - 52));
+       result = (((long long int) i0 << 32) | i1) << (j0 - 52);
       else
        {
          w = two52[sx] + x;
          t = w - two52[sx];
          EXTRACT_WORDS (i0, i1, t);
-         i0 = i & 0xfffff;
-         i0 |= 0x100000;
          j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
+         i0 &= 0xfffff;
+         i0 |= 0x100000;
 
-         result = ((long long int) i0 << (j0 - 20)) | (j >> (52 - j0));
+         result = ((long long int) i0 << (j0 - 20)) | (i1 >> (52 - j0));
        }
     }
   else
index f73afd0fd2612306bb632814c222c3fd86a04a35..83cb7fdd374097c80d8ec8fdc181f766231495a9 100644 (file)
@@ -47,7 +47,7 @@ __llrintf (float x)
   i0 = i & 0x7fffff;
   i0 |= 0x800000;
 
-  if (j0 < (int32_t) (sizeof (long long int) * 8))
+  if (j0 < (int32_t) (sizeof (long long int) * 8) - 1)
     {
       if (j0 < -1)
        return 0;
index d3b9b12d768678727c19328d8575d0762af90c43..2aeaa1e1023a99831e7054829f663a22459d4a4b 100644 (file)
@@ -45,12 +45,12 @@ __llrintl (long double x)
   sx = (se >> 15) & 1;
   j0 = (se & 0x7fff) - 0x3fff;
 
-  if (j0 < (int32_t) (8 * sizeof (long long int)))
+  if (j0 < (int32_t) (8 * sizeof (long long int)) - 1)
     {
       if (j0 < -1)
        return 0;
       else if (j0 >= 63)
-       result = ((long long int) i0 << (j0 - 31)) | (i1 << (j0 - 63));
+       result = (((long long int) i0 << 32) | i1) << (j0 - 63);
       else
        {
          w = two63[sx] + x;
index 1deb630e9630b3b6763663060d29b2416b2765d1..92ce10fc42199f0793f16b48216b93eca9b525ef 100644 (file)
@@ -48,17 +48,20 @@ __llround (double x)
          result = i0 >> (20 - j0);
        }
     }
-  else if (j0 < (int32_t) (8 * sizeof (long long int)))
+  else if (j0 < (int32_t) (8 * sizeof (long long int)) - 1)
     {
       if (j0 >= 52)
-       result = ((long long int) i0 << (j0 - 20)) | (i1 << (j0 - 52));
+       result = (((long long int) i0 << 32) | i1) << (j0 - 52);
       else
        {
          u_int32_t j = i1 + (0x80000000 >> (j0 - 20));
          if (j < i1)
            ++i0;
 
-         result = ((long long int) i0 << (j0 - 20)) | (j >> (52 - j0));
+         if (j0 == 20)
+           result = (long long int) i0;
+         else
+           result = ((long long int) i0 << (j0 - 20)) | (j >> (52 - j0));
        }
     }
   else
index 87ed1a31174855ab6e7673680687ed644f83b3e4..9aad81fd455aad4ec5405bb3ee32f6eb399d6df4 100644 (file)
@@ -37,12 +37,12 @@ __llroundf (float x)
   i &= 0x7fffff;
   i |= 0x800000;
 
-  if (j0 < (int32_t) (8 * sizeof (long long int)))
+  if (j0 < (int32_t) (8 * sizeof (long long int)) - 1)
     {
       if (j0 < 0)
        return j0 < -1 ? 0 : sign;
       else if (j0 >= 23)
-       result = (long int) i << (j0 - 23);
+       result = (long long int) i << (j0 - 23);
       else
        {
          i += 0x400000 >> j0;
index 959b1e3fe9c21a780f83e739a6e3d209d7386445..4a537c871e7292f3f1347ea36284d64a331a8423 100644 (file)
@@ -52,17 +52,20 @@ __llroundl (long double x)
          result = j >> (31 - j0);
        }
     }
-  else if (j0 < (int32_t) (8 * sizeof (long long int)))
+  else if (j0 < (int32_t) (8 * sizeof (long long int)) - 1)
     {
       if (j0 >= 63)
-       result = ((long long int) i0 << (j0 - 31)) | (i1 << (j0 - 63));
+       result = (((long long int) i0 << 32) | i1) << (j0 - 63);
       else
        {
          u_int32_t j = i1 + (0x80000000 >> (j0 - 31));
          if (j < i1)
            ++i0;
 
-         result = ((long long int) i0 << (j0 - 31)) | (j >> (63 - j0));
+         if (j0 == 31)
+           result = (long long int) i0;
+         else
+           result = ((long long int) i0 << (j0 - 31)) | (j >> (63 - j0));
        }
     }
   else
index 0ccd06a061e5d007c63b21fc80a7b953c17574e7..8fe7d24e14a776e635f058cbdc77e0dc6eeab24b 100644 (file)
@@ -62,7 +62,7 @@ __lrint (double x)
          result = i0 >> (20 - j0);
        }
     }
-  else if (j0 < (int32_t) (8 * sizeof (long int)))
+  else if (j0 < (int32_t) (8 * sizeof (long int)) - 1)
     {
       if (j0 >= 52)
        result = ((long int) i0 << (j0 - 20)) | (i1 << (j0 - 52));
@@ -75,7 +75,7 @@ __lrint (double x)
          i0 |= 0x100000;
          j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
 
-         result = ((long int) i0 << (j0 - 20)) | (j >> (52 - j0));
+         result = ((long int) i0 << (j0 - 20)) | (i1 >> (52 - j0));
        }
     }
   else
index 6d74b362f580ebebde2a16f624386bd87a6f1969..d80d81a718ff925b98483b21d9bc654731b9da1a 100644 (file)
@@ -47,7 +47,7 @@ __lrintf (float x)
   i0 = i & 0x7fffff;
   i0 |= 0x800000;
 
-  if (j0 < (int32_t) (sizeof (long int) * 8))
+  if (j0 < (int32_t) (sizeof (long int) * 8) - 1)
     {
       if (j0 < -1)
        return 0;
index 5a41427f72764dc7adda362083b910358c2ed92a..673cf3d9dbc60aa78015c2e68e0864bb87abea83 100644 (file)
@@ -59,7 +59,7 @@ __lrintl (long double x)
          result = i0 >> (31 - j0);
        }
     }
-  else if (j0 < (int32_t) (8 * sizeof (long int)))
+  else if (j0 < (int32_t) (8 * sizeof (long int)) - 1)
     {
       if (j0 >= 63)
        result = ((long int) i0 << (j0 - 31)) | (i1 << (j0 - 63));
index a6468ba78a9ef42478c1fa943cae45f82421d9a0..49be12f03b22c8856d332c190c0fc855c96eec37 100644 (file)
@@ -48,7 +48,7 @@ __lround (double x)
          result = i0 >> (20 - j0);
        }
     }
-  else if (j0 < (int32_t) (8 * sizeof (long int)))
+  else if (j0 < (int32_t) (8 * sizeof (long int)) - 1)
     {
       if (j0 >= 52)
        result = ((long int) i0 << (j0 - 20)) | (i1 << (j0 - 52));
index 0d3889c24af404a49ebd109f4d05da8a44d6a5dc..df1d242e2afd667d4cf834eb44693ee7aee78500 100644 (file)
@@ -37,7 +37,7 @@ __lroundf (float x)
   i &= 0x7fffff;
   i |= 0x800000;
 
-  if (j0 < (int32_t) (8 * sizeof (long int)))
+  if (j0 < (int32_t) (8 * sizeof (long int)) - 1)
     {
       if (j0 < 0)
        return j0 < -1 ? 0 : sign;
index d8b7db4b5ca6663ceebd24b6f3a0958ffb735410..3bdac830b495af001723f8170f7977929a7d2c67 100644 (file)
@@ -52,7 +52,7 @@ __lroundl (long double x)
          result = j >> (31 - j0);
        }
     }
-  else if (j0 < (int32_t) (8 * sizeof (long int)))
+  else if (j0 < (int32_t) (8 * sizeof (long int)) - 1)
     {
       if (j0 >= 63)
        result = ((long int) i0 << (j0 - 31)) | (i1 << (j0 - 63));
index aafb73e688eb9c4a122d3e15a5d5352f5a1442b3..b885fbcadb9a370507ebcc602a9dc8b03c946d58 100644 (file)
@@ -34,7 +34,7 @@ static const long double
 static long double
 #endif
 two63   =  4.50359962737049600000e+15,
-twom63  =  1.08420217248550443400e-19;
+twom63  =  1.08420217248550443400e-19,
 huge   = 1.0e+4900L,
 tiny   = 1.0e-4900L;
 
index 4e1d08ef90f7cfd4bb8cccdfe6e49202d240b2df..32e4fb8ceae04bac8e35e7b89035910468154a1d 100644 (file)
@@ -34,7 +34,7 @@ static const long double
 static long double
 #endif
 two63   =  4.50359962737049600000e+15,
-twom63  =  1.08420217248550443400e-19;
+twom63  =  1.08420217248550443400e-19,
 huge   = 1.0e+4900L,
 tiny   = 1.0e-4900L;
 
index 7cadf88a4023a285a6fb0f52cef6c7c862043a79..78c78d5619d61783aa67eff9e766be818d074d39 100644 (file)
@@ -38,7 +38,7 @@ __sincosl (long double x, long double *sinx, long double *cosx)
       *sinx = __kernel_sinl (x, 0.0, 0);
       *cosx = __kernel_cosl (x, 0.0);
     }
-  else if (ix == 0x7fff)
+  else if (se == 0x7fff)
     {
       /* sin(Inf or NaN) is NaN */
       *sinx = *cosx = x - x;
index bce6d07f3d02c7f6c77d8544c7b4f36c9b7cdecb..97a0b27f32feaa00c4290afb71e075e6856ca228 100644 (file)
@@ -66,7 +66,7 @@ static char rcsid[] = "$NetBSD: $";
 
     /* |x| ~< pi/4 */
        se &= 0x7fff;
-       if(ix <= 0x3ffe) return __kernel_tanl(x,z,1);
+       if(se <= 0x3ffe) return __kernel_tanl(x,z,1);
 
     /* tan(Inf or NaN) is NaN */
        else if (se==0x7fff) return x-x;                /* NaN */
index f5d0d51122247f6947f0c9dcf7069a67470076d0..9dfee644ed8d4034da2625246b0d602990a67757 100644 (file)
 #include "math_private.h"
 
 long long int
-__llrint (long double x)
+__llrint (double x)
 {
-  int32_t se, sx;
-  u_int32_t h, l;
+  int32_t e;
+  u_int32_t h, l, s;
   long long int result;
 
-  x = __m81_u(__rintl) (x);
+  x = __m81_u(__rint) (x);
 
   /* We could use __fixxfdi from libgcc, but here we can take advantage of
      the known floating point format.  */
-  GET_LDOUBLE_WORDS (se, h, l, x);
+  EXTRACT_WORDS (h, l, x);
 
-  sx = se & (1 << 15);
-  se = (se ^ sx) - 0x3fff;
+  e = ((h >> 20) & 0x7ff) - 0x3ff;
+  if (e < 0)
+    return 0;
+  s = h;
+  h &= 0xfffff;
+  h |= 0x100000;
 
-  if (se < 64)
+  if (e < 63)
     {
-      if (se > 31)
-       result = (((long long int) (h >> (63 - se)) << 32)
-                 | (l >> (63 - se)) | (h << (se - 31)));
+      if (e > 52)
+       {
+         h <<= e - 52;
+         h |= l >> (84 - e);
+         l <<= e - 52;
+         result = ((long long int) h << 32) | l;
+       }
+      else if (e > 20)
+       {
+         l >>= 52 - e;
+         l |= h << (e - 20);
+         h >>= 52 - e;
+         result = ((long long int) h << 32) | l;
+       }
       else
-       result = h >> (31 - se);
-      if (sx)
+       result = h >> (20 - e);
+      if (s & 0x80000000)
        result = -result;
     }
   else
-    /* Too large.  The number is either +-inf or NaN or it is too
-       large to be effected by rounding.  The standard leaves it
-       undefined what to return when the number is too large to fit in
-       a `long long int'.  */
+    /* The number is too large or not finite.  The standard leaves it
+       undefined what to return when the number is too large to fit in a
+       `long long int'.  */
     result = -1LL;
 
   return result;
diff --git a/sysdeps/m68k/fpu/s_llrintf.c b/sysdeps/m68k/fpu/s_llrintf.c
new file mode 100644 (file)
index 0000000..3c8528c
--- /dev/null
@@ -0,0 +1,66 @@
+/* Round argument to nearest integral value according to current rounding
+   direction.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+   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., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#define __LIBC_M81_MATH_INLINES
+#include <math.h>
+#include "math_private.h"
+
+long long int
+__llrintf (float x)
+{
+  int32_t e;
+  u_int32_t i, s;
+  long long int result;
+
+  x = __m81_u(__rintf) (x);
+
+  GET_FLOAT_WORD (i, x);
+
+  e = ((i >> 23) & 0xff) - 0x7f;
+  if (e < 0)
+    return 0;
+  s = i;
+  i &= 0x7fffff;
+  i |= 0x800000;
+
+  if (e < 63)
+    {
+      if (e > 55)
+       result = (long long int) (i << (e - 55)) << 32;
+      else if (e > 31)
+       result = (((long long int) (i >> (55 - e)) << 32) | (i << (e - 23)));
+      else if (e > 23)
+       result = i << (e - 23);
+      else
+       result = i >> (23 - e);
+      if (s & 0x80000000)
+       result = -result;
+    }
+  else
+    /* The number is too large or not finite.  The standard leaves it
+       undefined what to return when the number is too large to fit in a
+       `long long int'.  */
+    result = -1LL;
+
+  return result;
+}
+
+weak_alias (__llrintf, llrintf)
diff --git a/sysdeps/m68k/fpu/s_llrintl.c b/sysdeps/m68k/fpu/s_llrintl.c
new file mode 100644 (file)
index 0000000..55190b9
--- /dev/null
@@ -0,0 +1,65 @@
+/* Round argument to nearest integral value according to current rounding
+   direction.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+   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., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#define __LIBC_M81_MATH_INLINES
+#include <math.h>
+#include "math_private.h"
+
+long long int
+__llrintl (long double x)
+{
+  int32_t e, s;
+  u_int32_t h, l;
+  long long int result;
+
+  x = __m81_u(__rintl) (x);
+
+  GET_LDOUBLE_WORDS (e, h, l, x);
+
+  s = e;
+  e = (e & 0x7fff) - 0x3fff;
+  if (e < 0)
+    return 0;
+
+  if (e < 63)
+    {
+      if (e > 31)
+       {
+         l >>= 63 - e;
+         l |= h << (e - 31);
+         h >>= 63 - e;
+         result = ((long long int) h << 32) | l;
+       }
+      else
+       result = h >> (31 - e);
+      if (s & 0x8000)
+       result = -result;
+    }
+  else
+    /* The number is too large or not finite.  The standard leaves it
+       undefined what to return when the number is too large to fit in a
+       `long long int'.  */
+    result = -1LL;
+
+  return result;
+}
+
+weak_alias (__llrintl, llrintl)
index beb35ecd9a82af18c40b51a4d53467a024be627a..c17130d6fd4dbae7030a21959b6b88dd988beb7e 100644 (file)
@@ -2,7 +2,7 @@
 
 /* The Hurd uses Mach error system 0x10, currently only subsystem 0. */
 #ifndef _HURD_ERRNO
-#define _HURD_ERRNO(n) ((0x10 << 26) | ((n) & 0x3fff))
+# define _HURD_ERRNO(n)        ((0x10 << 26) | ((n) & 0x3fff))
 #endif
 
 #ifdef _ERRNO_H
@@ -293,24 +293,25 @@ enum __error_t_codes
 
 };
 
-#define        _HURD_ERRNOS    118
+# define _HURD_ERRNOS  118
 
 /* User-visible type of error codes.  It is ok to use `int' or
    `kern_return_t' for these, but with `error_t' the debugger prints
    symbolic values.  */
-#ifdef __USE_GNU
+# ifdef __USE_GNU
 typedef enum __error_t_codes error_t;
-#define __error_t_defined      1
-#endif
+#  define __error_t_defined    1
+# endif
 
 /* errno is a per-thread variable.  */
-#include <hurd/threadvar.h>
-#define errno  (*__hurd_errno_location ())
-#define __set_errno(val) errno = (val)
+# include <hurd/threadvar.h>
+# define errno (*__hurd_errno_location ())
+# define __set_errno(val) errno = (val)
 
 #endif /* <errno.h> included.  */
 
-#if !defined (_ERRNO_H) && defined (__need_Emath)
-#define        EDOM            _HURD_ERRNO (33)/* Numerical argument out of domain */
-#define        ERANGE          _HURD_ERRNO (34)/* Numerical result out of range */
+#if !defined _ERRNO_H && defined __need_Emath
+# define EDOM            _HURD_ERRNO (33)/* Numerical argument out of domain */
+# define EILSEQ          _HURD_ERRNO (106)/* Invalid or incomplete multibyte or wide character */
+# define ERANGE          _HURD_ERRNO (34)/* Numerical result out of range */
 #endif /* <errno.h> not included and need math error codes.  */
index 01f86ef47f3eaa3412b9d136de93d60124c52407..2ae3c1e897eb148e00d10a6b787a71f8c9c772c6 100644 (file)
@@ -135,6 +135,11 @@ extern void free ();
 # define memmove memcpy
 #endif /* Not ANSI_STRING.  */
 
+#ifdef _LIBC
+# define mempcpy __mempcpy
+# define HAVE_MEMPCPY  1
+#endif
+
 #if !defined __alloca && !defined __GNU_LIBRARY__
 
 # ifdef        __GNUC__
@@ -277,10 +282,10 @@ __getcwd (buf, size)
              dotp = &new[dotsize];
            }
 #ifdef HAVE_MEMPCPY
-         *((char *) mempcpy (dotp, new, dotsize)) = '\0';
+         *((char *) mempcpy ((char *) dotp, new, dotsize)) = '\0';
          dotsize *= 2;
 #else
-         memcpy (dotp, new, dotsize);
+         memcpy ((char *) dotp, new, dotsize);
          dotsize *= 2;
          new[dotsize] = '\0';
 #endif
index 2b8f9cb590dc99023e0f48ee27e297b10174c9fc..1111646bbda518bf3606df7cc3932b876a1e872e 100644 (file)
@@ -44,6 +44,7 @@ __libc_system (const char *line)
 #endif
 
   if (line == NULL)
+    /* This signals that we have a command processor available.  */
     return 1;
 
   sa.sa_handler = SIG_IGN;
index 30eec4308de7a14e5fd0d907d00a4ac85da33e02..d4030b7f443a5851c1b4f80bc9d3672f78c48c0a 100644 (file)
@@ -23,6 +23,7 @@
 #define        __Emath_defined 1
 
 # define EDOM  1
+# define EILSEQ 17
 # define ERANGE        2
 #endif
 
@@ -41,7 +42,6 @@
 # define ENOMSG 14
 # define E2BIG 15
 # define EINTR 16
-# define EILSEQ 17
 # define ENOEXEC 18
 # define ENOENT 19
 # define EPROTOTYPE 20
index cfe5202ba1905e924303c9c2674966a1a2606972..2896953cb78b96e3762908624e563095233fe19a 100644 (file)
@@ -38,6 +38,7 @@ sys/klog.h
 sys/module.h
 sys/mount.h
 sys/mtio.h
+sys/prctl.h
 sys/procfs.h
 sys/quota.h
 sys/socketvar.h
index 8db8094dc1f93cc7d8c9f48a4f86b2ee182a0142..005278068a82237b6e8cb821f4235edd0257e913 100644 (file)
@@ -13,7 +13,7 @@ sysdep_routines += sysctl clone llseek
 
 sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h sys/mtio.h \
                  sys/module.h sys/io.h sys/klog.h sys/kdaemon.h \
-                 sys/user.h sys/sysmacros.h sys/procfs.h \
+                 sys/user.h sys/sysmacros.h sys/procfs.h sys/prctl.h \
                  sys/debugreg.h sys/kd.h sys/soundcard.h sys/vt.h \
                  sys/quota.h sys/fsuid.h bits/mman.h \
                  scsi/sg.h
index d1005e730239b06df330291fb96a1345beecb641..cb0269b8af8df6b25bb6f888ff4cc75aeb976040 100644 (file)
@@ -29,7 +29,7 @@ xstat_conv (int vers, struct kernel_stat *kbuf, void *ubuf)
       /* Nothing to do.  The struct is in the form the kernel expects.
         We should have short-circuted before we got here, but for
         completeness... */
-      memcpy ((struct kernel_stat *) ubuf, kbuf, sizeof (*kbuf));
+      *(struct kernel_stat *) ubuf = *kbuf;
       break;
 
     case _STAT_VER_GLIBC2:
index f676d35e4905b475efc99e1c55777832925daf30..abcbd9b8011bca79b60485d98b175d17a7f6fb84 100644 (file)
@@ -50,10 +50,11 @@ __set_errno (int __err)
 # endif /* !__ASSEMBLER__ */
 #endif /* _ERRNO_H */
 
-#if !defined (_ERRNO_H) && defined (__need_Emath)
+#if !defined _ERRNO_H && defined __need_Emath
 /* This is ugly but the kernel header is not clean enough.  We must
    define only the values EDOM and ERANGE in case __need_Emath is
    defined.  The value is the same for all Linux ports.  */
 # define EDOM  33      /* Math argument out of domain of function.  */
+# define EILSEQ        84      /* Illegal byte sequence.  */
 # define ERANGE        34      /* Math result not representable.  */
 #endif /* !_ERRNO_H && __need_Emath */
index 06a28cce30b13d14d9a616464d5a2a65330ec65f..fcf2f3b9f628aca80c49b7a99ede47b6ce9687b8 100644 (file)
@@ -29,7 +29,7 @@ xstat_conv (int vers, struct kernel_stat *kbuf, void *ubuf)
       /* Nothing to do.  The struct is in the form the kernel expects.
          We should have short-circuted before we got here, but for
          completeness... */
-      memcpy ((struct kernel_stat *) ubuf, kbuf, sizeof (*kbuf));
+      *(struct kernel_stat *) ubuf = *kbuf;
       break;
 
     case _STAT_VER_LINUX:
index c0582c18766137209286e4e5db937a46e841e4cb..7bb8cbd5bca7f1f318f59c88171321697e16cb7f 100644 (file)
@@ -25,6 +25,9 @@
 #define _INTTYPES_H    1
 #include <features.h>
 
+#define __need_wchar_t
+#include <stddef.h>
+
 /* Exact integral types.  */
 
 /* Signed.  */
@@ -342,6 +345,31 @@ typedef unsigned long long int uint_fast64_t;
 #define SCNxPTR                "x"
 
 
+/* Limits of other integer types.  */
+
+/* Limits of `ptrdiff_t' type.  */
+#define PTRDIFF_MIN    (-2147483647-1)
+#define PTRDIFF_MAX    (2147483647)
+
+/* Limits of `sig_atomic_t'.  */
+#define SIG_ATOMIC_MIN (-2147483647-1)
+#define SIG_ATOMIC_MAX (-2147483647-1)
+
+/* Limit of `size_t' type.  */
+#define SIZE_MAX       (4294967295U)
+
+/* Limits of `wchar_t'.  */
+#ifndef WCHAR_MIN
+/* These constants might also be defined in <wchar.h>.  */
+# define WCHAR_MIN     (-2147483647-1)
+# define WCHAR_MAX     (2147483647)
+#endif
+
+/* Limits of `wint_t'.  */
+#define WINT_MIN       (0)
+#define WINT_MAX       (4294967295U)
+
+
 /* Macros for string conversion.  */
 
 /* Like `strtol' but convert to `intmax_t'.  */
@@ -370,4 +398,32 @@ extern unsigned long long int __strtoull_internal __P ((__const char *
 # define __strtoull_internal_defined   1
 #endif
 
+
+/* Like `wcstol' but convert to `intmax_t'.  */
+#define wcstoimax(nptr, endptr, base) \
+    __wcstoll_internal (nptr, endptr, base, 0)
+
+#ifndef __wcstoll_internal_defined
+extern long long int __wcstoll_internal __P ((__const wchar_t *
+                                             __restrict __nptr,
+                                             wchar_t **__restrict __endptr,
+                                             int __base, int __group));
+# define __wcstoll_internal_defined    1
+#endif
+
+
+/* Like `wcstoul' but convert to `uintmax_t'.  */
+#define wcstoumax(nptr, endptr, base) \
+    __wcstoull_internal (nptr, endptr, base, 0)
+
+#ifndef __wcstoull_internal_defined
+extern unsigned long long int __wcstoull_internal __P ((__const wchar_t *
+                                                       __restrict __nptr,
+                                                       wchar_t **
+                                                       __restrict __endptr,
+                                                       int __base,
+                                                       int __group));
+# define __wcstoull_internal_defined   1
+#endif
+
 #endif /* inttypes.h */
index 2a2628428d6d292c131869a438cee68d16320b7e..9967fc0844aa1f5dadf25b1dadc8c117abf251cc 100644 (file)
@@ -25,6 +25,9 @@
 #define _INTTYPES_H    1
 #include <features.h>
 
+#define __need_wchar_t
+#include <stddef.h>
+
 /* Exact integral types.  */
 
 /* Signed.  */
@@ -342,6 +345,31 @@ typedef unsigned long int uint_fast64_t;
 #define SCNxPTR                "lx"
 
 
+/* Limits of other integer types.  */
+
+/* Limits of `ptrdiff_t' type.  */
+#define PTRDIFF_MIN    (-9223372036854775807L-1)
+#define PTRDIFF_MAX    (9223372036854775807L)
+
+/* Limits of `sig_atomic_t'.  */
+#define SIG_ATOMIC_MIN (-2147483647-1)
+#define SIG_ATOMIC_MAX (-2147483647-1)
+
+/* Limit of `size_t' type.  */
+#define SIZE_MAX       (18446744073709551615uL)
+
+/* Limits of `wchar_t'.  */
+#ifndef WCHAR_MIN
+/* These constants might also be defined in <wchar.h>.  */
+# define WCHAR_MIN     (-2147483647-1)
+# define WCHAR_MAX     (2147483647)
+#endif
+
+/* Limits of `wint_t'.  */
+#define WINT_MIN       (0)
+#define WINT_MAX       (4294967295U)
+
+
 /* Macros for string conversion.  */
 
 /* Like `strtol' but convert to `intmax_t'.  */
@@ -368,4 +396,30 @@ extern unsigned long int __strtoul_internal __P ((__const char *
 # define __strtoul_internal_defined    1
 #endif
 
+
+/* Like `wcstol' but convert to `intmax_t'.  */
+#define wcstoimax(nptr, endptr, base) \
+    __wcstol_internal (nptr, endptr, base, 0)
+
+#ifndef __wcstol_internal_defined
+extern long int __wcstol_internal __P ((__const wchar_t *__restrict __nptr,
+                                       wchar_t **__restrict __endptr,
+                                       int __base, int __group));
+# define __wcstol_internal_defined     1
+#endif
+
+
+/* Like `wcstoul' but convert to `uintmax_t'.  */
+#define wcstoumax(nptr, endptr, base) \
+    __wcstoul_internal (nptr, endptr, base, 0)
+
+#ifndef __wcstoul_internal_defined
+extern unsigned long int __wcstoul_internal __P ((__const wchar_t *
+                                                 __restrict __nptr,
+                                                 wchar_t **
+                                                 __restrict __endptr,
+                                                 int __base, int __group));
+# define __wcstoul_internal_defined    1
+#endif
+
 #endif /* inttypes.h */
diff --git a/test-installation.pl b/test-installation.pl
new file mode 100644 (file)
index 0000000..76aa3fb
--- /dev/null
@@ -0,0 +1,195 @@
+#! /usr/bin/perl -w
+
+# Copyright (C) 1997 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+# Contributed by Andreas Jaeger <aj@arthur.rhein-neckar.de>, 1997.
+
+# 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+
+$PACKAGE = "libc";
+$progname = $0;
+if ($ENV{CC}) {
+  $CC = $ENV{CC};
+} else {
+  $CC= "gcc";
+}
+
+sub usage {
+  print "Usage: test-installation [soversions.mk]\n";
+  print "  --help       print this help, then exit\n";
+  print "  --version    print version number, then exit\n";
+  exit 0;
+}
+
+sub installation_problem {
+  print "The script has found some problems with your installation!\n";
+  print "Please read the FAQ and the README file and check the following:\n";
+  print "- Did you change the gcc specs file (neccessary after upgrading from\n";
+  print "  Linux libc5)?\n";
+  print "- Are there any symbolic links of the form libXXX.so to old libraries?\n";
+  print "  Links like libm.so -> libm.so.5 (where libm.so.5 is an old library) are wrong,\n";
+  print "  libm.so should point to the newly installed glibc file - and there should be\n";
+  print "  only one such link (check e.g. /lib and /usr/lib)\n";
+  print "You should restart this script from your build directory after you've\n";
+  print "fixed all problems!\n";
+  print "Btw. the script doesn't work if you're installing GNU libc not as your\n";
+  print "primary library!\n";
+  exit 1;
+}
+
+arglist: while (@ARGV) {
+  if ($ARGV[0] eq "--v" || $ARGV[0] eq "--ve" || $ARGV[0] eq "--ver" ||
+      $ARGV[0] eq "--vers" || $ARGV[0] eq "--versi" ||
+      $ARGV[0] eq "--versio" || $ARGV[0] eq "--version") {
+    print "test-installation (GNU $PACKAGE)\n";
+    print "Copyright (C) 1997 Free Software Foundation, Inc.\n";
+    print "This is free software; see the source for copying conditions.  There is NO\n";
+    print "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
+    print "Written by Andreas Jaeger <aj\@arthur.rhein-neckar.de>\n";
+
+    exit 0;
+  } elsif ($ARGV[0] eq "--h" || $ARGV[0] eq "--he" || $ARGV[0] eq "--hel" ||
+          $ARGV[0] eq "--help") {
+    &usage;
+  } elsif ($ARGV[0] =~ /^-/) {
+    print "$progname: unrecognized option `$ARGV[0]'\n";
+    print "Try `$progname --help' for more information.\n";
+    exit 1;
+  } else {
+    last arglist;
+  }
+}
+
+# We expect none or one argument.
+if ($#ARGV == -1) {
+    $soversions="soversions.mk";
+} elsif ($#ARGV == 0) {
+    if (-d $ARGV[0]) {
+      $soversions = "$ARGV[0]/soversions.mk";
+    } else {
+      $soversions = $ARGV[0];
+    }
+} else {
+    die "Wrong number of arguments.";
+}
+
+
+# Read names and versions of all shared libraries that are part of
+# glibc
+open SOVERSIONS, $soversions
+  or die ("Couldn't open $soversions in build directory!");
+
+$link_libs = "";
+%versions = ();
+
+while (<SOVERSIONS>) {
+  next if (/^all-sonames/);
+  chop;
+  if (/^lib/) {
+    ($name, $version)= /^lib(.*)\.so-version=\.(.*)$/;
+    if ($name ne "nss_ldap") {
+      $link_libs .= " -l$name";
+      $versions{$name} = $version;
+    }
+  } else {
+    if (/^ld\.so/) {
+      ($ld_so_name, $ld_so_version)= /=(.*)\.so\.(.*)$/;
+    }
+  }
+}
+
+close SOVERSIONS;
+
+# Create test program and link it against all
+# shared libraries
+
+open PRG, ">/tmp/test-prg$$.c"
+  or die ("Couldn't write test file /tmp/test-prg$$.c");
+
+print PRG '
+#include <stdlib.h>
+int main(void) {
+  printf ("Your new glibc installation seems to be ok.\n");
+  exit (0);
+}
+';
+close PRG;
+
+open GCC, "$CC /tmp/test-prg$$.c $link_libs -o /tmp/test-prg$$ 2>&1 |"
+  or die ("Couldn't execute $CC!");
+
+while (<GCC>) {
+  print $_ if (! /warning/);
+}
+close GCC;
+if ($?) {
+  print "Execution of $CC failed!\n";
+  &installation_problem;
+}
+
+# Test if test program is linked against the right versions of
+# shared libraries
+
+$ok = 1;
+%found = ();
+
+open LDD, "ldd /tmp/test-prg$$ |"
+  or die ("Couldn't execute ldd");
+while (<LDD>) {
+  if (/^\s*lib/) {
+    ($name, $version1, $version2) =
+      /^\s*lib(\w*)\.so\.([0-9\.]*)\s*=>.*\.so\.([0-9\.]*)/;
+    $found{$name} = 1;
+    if ($versions{$name} ne $version1 || $version1 ne $version2) {
+      print "Library lib$name is not correctly installed.\n";
+      print "Please check your installation!\n";
+      print "Offending line of ldd output: $_\n";
+      $ok = 0;
+    }
+  }
+  if (/$ld_so_name/) {
+    ($version1, $version2) =
+      /$ld_so_name\.so\.([0-9\.]*)\s*=>.*\.so\.([0-9\.]*)/;
+    if ($version1 ne $version2 || $version1 ne $ld_so_version) {
+      print "The dynamic linker $ld_so_name.so is not correctly installed.\n";
+      print "Please check your installation!\n";
+      print "Offending line of ldd output: $_\n";
+      $ok = 0;
+    }
+  }
+}
+
+close LDD;
+die "ldd execution failed" if $?;
+
+foreach (keys %versions) {
+  unless ($found{$_}) {
+    print "Library lib$_ is not correctly installed since the test program\n";
+    print "was not linked dynamically against it.\n";
+    print "Do you have a file/link lib$_.so?\n";
+    $ok = 0;
+  }
+}
+
+&installation_problem unless $ok;
+
+# Finally execute the test program
+system ("/tmp/test-prg$$") == 0
+  or die ("Execution of test program failed");
+
+# Clean up after ourselves
+unlink ("/tmp/test-prg$$", "/tmp/test-prg$$.c");
index c4945f7e4b59bcf08b7f2074c04bec4e29de0648..87231d7770170193a686fcc034bf48b426a92c00 100644 (file)
@@ -32,7 +32,7 @@ routines      := offtime asctime clock ctime ctime_r difftime \
                   tzfile gettimeofday settimeofday adjtime     \
                   getitimer setitimer                          \
                   stime dysize timegm ftime                    \
-                  strptime getdate
+                  strptime getdate strfxtime
 
 others := ap zdump zic
 tests  := test_time clocktest test-tz
index 1573cc79a91b3a0a71adb26b36fcb241418b3206..7a94c21244755794848a51915978d6cd84e47402 100644 (file)
@@ -194,7 +194,7 @@ __mktime_internal (tp, convert, offset)
 
   /* The maximum number of probes (calls to CONVERT) should be enough
      to handle any combinations of time zone rule changes, solar time,
-     and leap seconds.  Posix.1 prohibits leap seconds, but some hosts
+     and leap seconds.  POSIX.1 prohibits leap seconds, but some hosts
      have them anyway.  */
   int remaining_probes = 4;
 
index 8d94dcdf605d68326c3bbb5ce7feb87510f9e93a..e66a444d402dc10046af4214d6128d95a3496dc7 100644 (file)
@@ -883,6 +883,11 @@ my_strftime (s, maxsize, format, tp)
          cpy (buf + sizeof (buf) - bufp, bufp);
          break;
 
+       case 'F':
+         if (modifier != 0)
+           goto bad_format;
+         subfmt = "%Y-%m-%d";
+         goto subformat;
 
        case 'H':
          if (modifier == 'E')
@@ -1029,6 +1034,7 @@ my_strftime (s, maxsize, format, tp)
          add (1, *p = '\t');
          break;
 
+       case 'f':
        case 'u':               /* POSIX.2 extension.  */
          DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
 
similarity index 54%
rename from sysdeps/unix/sysv/i386/i686/time.S
rename to time/strfxtime.c
index c5d27635c92f758c36501efe4264d9c60cbf00ce..eb563ae52e27deb83d3418c5dff82cb940a64027 100644 (file)
@@ -1,5 +1,7 @@
-/* Copyright (C) 1991, 1992, 1996, 1997 Free Software Foundation, Inc.
+/* ISO C extended string formatting.
+   Copyright (C) 1997 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
    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
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#include <sysdep.h>
-#include <asm-syntax.h>
+#include <time.h>
 
-SYSCALL (time, 1)
-       movl 4(%esp), %edx      /* Put passed pointer in %edx.  */
-       testl %edx, %edx        /* Is it non-nil?  */
-       cmovnel %eax, (%edx)    /* Yes; store the time there.  */
-       ret
-PSEUDO_END (time)
+/* The ISO C 9X standard extended the `struct tm' structure to contain some
+   more information necessary for the new formats.  But the struct format
+   we used so far already contains the information and since the `struct tm'
+   and `struct tmx' structures match exactly in the first part.  So we can
+   simply use `strftime' to implement `strfxtime'.  */
+size_t
+strfxtime (char *s, size_t maxsize, const char *format,
+          const struct tmx *timeptr)
+{
+  return strftime (s, maxsize, format, (const struct tm *) timeptr);
+}
index 184f4eda10b38a1241e45bc32571990073a6b707..f60599d2cbd5d01bb405a37ca31d0d13ae2dc051 100644 (file)
@@ -95,6 +95,13 @@ struct timespec
 #undef __need_timespec
 
 
+/* Value used for `tm_' field in `struct tmx' if describing the local
+   time.  */
+#define _LOCALTIME             (0x7fffffff)
+
+/* Value used for `tm_leapsecond' field if the number cannot be computed.  */
+#define _NO_LEAP_SECONDS       (0x7fffffff)
+
 
 #ifdef _TIME_H
 /* Used by other time functions.  */
@@ -119,10 +126,36 @@ struct tm
 # endif
 };
 
-#endif /* <time.h> included.  */
+#ifdef __USE_ISOC9X
+/* Extended form of `struct tm' defined in ISO C 9X.  */
+struct tmx
+{
+  int tm_sec;                  /* Seconds.     [0-60] (1 leap second) */
+  int tm_min;                  /* Minutes.     [0-59] */
+  int tm_hour;                 /* Hours.       [0-23] */
+  int tm_mday;                 /* Day.         [1-31] */
+  int tm_mon;                  /* Month.       [0-11] */
+  int tm_year;                 /* Year - 1900.  */
+  int tm_wday;                 /* Day of week. [0-6] */
+  int tm_yday;                 /* Days in year.[0-365] */
+  int tm_isdst;                        /* DST.         [-1/0/1]*/
+
+# ifdef        __USE_BSD
+  long int tm_gmtoff;          /* Seconds east of UTC.  */
+# else
+  long int __tm_gmtoff;                /* Seconds east of UTC.  */
+# endif
+  __const char *__tm_zonestr;  /* Timezone abbreviation.  */
+
+  int tm_version;              /* Version number.  */
+  int tm_zone;                 /* Minutes offset from UTC [-1439-1439] */
+  int tm_leapsecs;             /* Number of leap seconds applied.  */
+  void *tm_ext;                        /* Extension block.  */
+  size_t tm_extlen;            /* Size of the extension block.  */
+};
+#endif
 
 
-#ifdef _TIME_H
 /* Time used by the program so far (user time + system time).
    The result / CLOCKS_PER_SECOND is program time in seconds.  */
 extern clock_t clock __P ((void));
@@ -145,6 +178,12 @@ extern time_t __mktime_internal __P ((struct tm *__tp,
                                                            struct tm *),
                                      time_t *__offset));
 
+#ifdef __USE_ISOC9X
+/* Return the `time_t' representation of TP and normalize TP, taking
+   account for the extra members in `struct tmx'.  */
+extern time_t mkxtime __P ((struct tmx *__tp));
+#endif
+
 
 /* Format TP into S according to FORMAT.
    Write no more than MAXSIZE characters and return the number
index 82e51faf62e44547d66da3f681ba92fc9c3bdd3e..966d20cba1fd328407edc7723e579f82d77f9152 100644 (file)
@@ -55,8 +55,11 @@ typedef struct
   wint_t value;                /* Value so far.  */
 } mbstate_t;
 
-#define WCHAR_MIN ((wchar_t) 0)
-#define WCHAR_MAX (~WCHAR_MIN)
+#ifndef WCHAR_MIN
+/* These constants might also be defined in <inttypes.h>.  */
+# define WCHAR_MIN ((wchar_t) 0)
+# define WCHAR_MAX (~WCHAR_MIN)
+#endif
 
 #ifndef WEOF
 # define WEOF (0xffffffffu)
@@ -388,26 +391,36 @@ extern __long_double_t __wcstold_internal __P ((__const wchar_t *
                                                wchar_t **__restrict __endptr,
                                                int __group));
 
+#ifndef __wcstol_internal_defined
 extern long int __wcstol_internal __P ((__const wchar_t *__restrict __nptr,
                                        wchar_t **__restrict __endptr,
                                        int __base, int __group));
+# define __wcstol_internal_defined     1
+#endif
+#ifndef __wcstoul_internal_defined
 extern unsigned long int __wcstoul_internal __P ((__const wchar_t *
                                                  __restrict __nptr,
                                                  wchar_t **
                                                  __restrict __endptr,
                                                  int __base, int __group));
-#if defined __GNUC__ && defined __USE_GNU
+# define __wcstoul_internal_defined    1
+#endif
+#ifndef __wcstoll_internal_defined
 extern long long int __wcstoll_internal __P ((__const wchar_t *
                                              __restrict __nptr,
                                              wchar_t **__restrict __endptr,
                                              int __base, int __group));
+# define __wcstoll_internal_defined    1
+#endif
+#ifndef __wcstoull_internal_defined
 extern unsigned long long int __wcstoull_internal __P ((__const wchar_t *
                                                        __restrict __nptr,
                                                        wchar_t **
                                                        __restrict __endptr,
                                                        int __base,
                                                        int __group));
-#endif /* GCC and use GNU.  */
+# define __wcstoull_internal_defined   1
+#endif
 
 
 #if defined __OPTIMIZE__ && __GNUC__ >= 2