-# Id: configure.ac,v 11.100 2001/07/10 15:13:48 bostic Exp
+# Id: configure.ac,v 11.116 2001/10/11 20:29:35 bostic Exp
# Process this file with autoconf to produce a configure script.
PACKAGE=db
# Substitution variables.
AC_SUBST(ADDITIONAL_INCS)
AC_SUBST(ADDITIONAL_LANG)
-AC_SUBST(ADDITIONAL_LIBS)
AC_SUBST(ADDITIONAL_OBJS)
AC_SUBST(ADDITIONAL_PROGS)
AC_SUBST(BUILD_TARGET)
AC_SUBST(INSTALL_LIBS)
AC_SUBST(INSTALL_TARGET)
AC_SUBST(JAR)
-AC_SUBST(JAVAC)
AC_SUBST(JAVACFLAGS)
AC_SUBST(LDFLAGS)
AC_SUBST(LIBJSO_LIBS)
AC_SUBST(LIBXSO_LIBS)
AC_SUBST(MAKEFILE_CC)
AC_SUBST(MAKEFILE_CCLINK)
+AC_SUBST(MAKEFILE_SOLINK)
AC_SUBST(MAKEFILE_CXX)
AC_SUBST(MAKEFILE_CXXLINK)
+AC_SUBST(MAKEFILE_XSOLINK)
AC_SUBST(POSTLINK)
AC_SUBST(RPC_CLIENT_OBJS)
AC_SUBST(RPM_POST_INSTALL)
AC_SUBST(RPM_POST_UNINSTALL)
AC_SUBST(SOFLAGS)
-AC_SUBST(SOLINK)
AC_SUBST(SOSUFFIX)
AC_SUBST(TEST_LIBS)
AC_SUBST(db_cv_path_embedix_install)
# Don't override anything if it's already set from the environment.
optimize_def="-O"
case "$host_os" in
-aix4.*) optimize_def="-O2"
- CC=${CC-"xlc_r"}
- CPPFLAGS="-D_THREAD_SAFE $CPPFLAGS"
- LIBTSO_LIBS="\$(LIBS)";;
-bsdi3*) CC=${CC-"shlicc2"}
- optimize_def="-O2"
- LIBS="-lipc $LIBS";;
-bsdi*) optimize_def="-O2";;
-freebsd*) optimize_def="-O2"
- CPPFLAGS="-D_THREAD_SAFE $CPPFLAGS"
- LIBS="-pthread";;
-hpux*) CPPFLAGS="-D_REENTRANT $CPPFLAGS";;
-irix*) optimize_def="-O2"
- CPPFLAGS="-D_SGI_MP_SOURCE $CPPFLAGS";;
-linux*) optimize_def="-O2"
- CPPFLAGS="-D_GNU_SOURCE -D_REENTRANT $CPPFLAGS";;
-mpeix*) CPPFLAGS="-D_POSIX_SOURCE -D_SOCKET_SOURCE $CPPFLAGS"
- LIBS="-lsocket -lsvipc $LIBS";;
-osf*) CPPFLAGS="-D_REENTRANT $CPPFLAGS";;
-*qnx) AC_DEFINE(HAVE_QNX)
- AH_TEMPLATE(HAVE_QNX, [Define if building on QNX.]);;
-sco3.2v4*) CC=${CC-"cc -belf"}
- LIBS="-lsocket -lnsl_s $LIBS";;
-sco*) CC=${CC-"cc -belf"}
- LIBS="-lsocket -lnsl $LIBS";;
-solaris*) CPPFLAGS="-D_REENTRANT $CPPFLAGS";;
+aix4.3.[12])
+ optimize_def="-O2"
+ CC=${CC-"xlc_r"}
+ CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE"
+ LIBTSO_LIBS="\$(LIBS)";;
+aix4.3.3)
+ optimize_def="-O2"
+ CC=${CC-"xlc_r"}
+ CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE"
+ LDFLAGS="$LDFLAGS -pthread"
+ LIBTSO_LIBS="\$(LIBS)";;
+bsdi3*) optimize_def="-O2"
+ CC=${CC-"shlicc2"}
+ LIBS="$LIBS -lipc";;
+bsdi*) optimize_def="-O2";;
+freebsd*)
+ optimize_def="-O2"
+ CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE"
+ LDFLAGS="$LDFLAGS -pthread";;
+hpux*) CPPFLAGS="$CPPFLAGS -D_REENTRANT";;
+irix*) optimize_def="-O2"
+ CPPFLAGS="$CPPFLAGS -D_SGI_MP_SOURCE";;
+linux*) optimize_def="-O2"
+ CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE -D_REENTRANT";;
+mpeix*) CPPFLAGS="$CPPFLAGS -D_POSIX_SOURCE -D_SOCKET_SOURCE"
+ LIBS="$LIBS -lsocket -lsvipc";;
+osf*) CPPFLAGS="$CPPFLAGS -D_REENTRANT"
+ LDFLAGS="$LDFLAGS -pthread";;
+*qnx) AC_DEFINE(HAVE_QNX)
+ AH_TEMPLATE(HAVE_QNX, [Define if building on QNX.]);;
+sco3.2v4*)
+ CC=${CC-"cc -belf"}
+ LIBS="$LIBS -lsocket -lnsl_s";;
+sco*) CC=${CC-"cc -belf"}
+ LIBS="$LIBS -lsocket -lnsl";;
+solaris*)
+ CPPFLAGS="$CPPFLAGS -D_REENTRANT";;
esac
# Set CFLAGS/CXXFLAGS. We MUST set the flags before we call autoconf
# Because of shared library building, the ${CC} used for config tests
# may be different than the ${CC} we want to put in the Makefile.
# The latter is known as ${MAKEFILE_CC} in this script.
-MAKEFILE_CC=${CC}
-MAKEFILE_CCLINK="\$(CC)"
+MAKEFILE_CC="${CC}"
+MAKEFILE_CCLINK="${CC}"
MAKEFILE_CXX="nocxx"
MAKEFILE_CXXLINK="nocxx"
if test "$db_cv_cxx" = "yes"; then
if test "$GCC" != "yes"; then
case "$host_os" in
- aix*) AC_CHECK_TOOL(CCC, xlC_r);;
+ aix*) AC_CHECK_TOOL(CCC, xlC_r)
+ LIBXSO_LIBS="-lC_r $LIBXSO_LIBS"
+ LIBS="-lC_r $LIBS";;
hpux*) AC_CHECK_TOOL(CCC, aCC);;
osf*) AC_CHECK_TOOL(CCC, cxx);;
solaris*) AC_CHECK_TOOL(CCC, CC);;
esac
fi
AC_PROG_CXX
- MAKEFILE_CXX=${CXX}
- MAKEFILE_CXXLINK="\$(CXX)"
+ MAKEFILE_CXX="${CXX}"
+ MAKEFILE_CXXLINK="${CXX}"
fi
# Do some gcc specific configuration.
AC_PROG_LIBTOOL
LIBTOOL="\$(SHELL) ./libtool"
-SOSUFFIX=`sed -e '/^library_names_spec=/!d' -e 's/.*\.\([[a-zA-Z0-9_]]*\).*/\1/' ./libtool`
SOFLAGS="-rpath \$(libdir)"
-SAVE_CC="${MAKEFILE_CC}"
-SAVE_CXX="${MAKEFILE_CXX}"
-MAKEFILE_CC="\$(LIBTOOL) --mode=compile ${SAVE_CC}"
-MAKEFILE_CXX="\$(LIBTOOL) --mode=compile ${SAVE_CXX}"
-MAKEFILE_CCLINK="\$(LIBTOOL) --mode=link ${SAVE_CC}"
-MAKEFILE_CXXLINK="\$(LIBTOOL) --mode=link ${SAVE_CXX}"
+AC_MSG_CHECKING([SOSUFFIX from libtool])
+# $library_names_spec is a snippet of shell that may
+# defined in terms of $versuffix, $release, $libname.
+# All we want is to eval it and grab the suffix used
+# for shared objects.
+versuffix=""
+release=""
+libname=libfoo
+eval library_names=\"$library_names_spec\"
+SOSUFFIX=`echo "$library_names" | sed -e 's/.*\.\([[a-zA-Z0-9_]]*\).*/\1/'`
+AC_MSG_RESULT($SOSUFFIX)
+
+if test "$SOSUFFIX" = '' ; then
+ SOSUFFIX=so
+ if test "$enable_shared" = "yes"; then
+ AC_MSG_WARN([libtool may not know about this architecture.])
+ AC_MSG_WARN([assuming .$SOSUFFIX suffix for dynamic libraries.])
+ fi
+fi
-SOLINK="\$(LIBTOOL) --mode=link ${SAVE_CC} -avoid-version"
INSTALLER="\$(LIBTOOL) --mode=install cp"
+MAKEFILE_CC="\$(LIBTOOL) --mode=compile ${MAKEFILE_CC}"
+MAKEFILE_SOLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CCLINK} -avoid-version"
+MAKEFILE_CCLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CCLINK}"
+MAKEFILE_CXX="\$(LIBTOOL) --mode=compile ${MAKEFILE_CXX}"
+MAKEFILE_XSOLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CXXLINK} -avoid-version"
+MAKEFILE_CXXLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CXXLINK}"
+
# Configure for shared libraries, static libraries, or both. If both are
# configured, build the utilities and example programs with shared versions.
#
# instead of .o
if test "$enable_shared" = "no"; then
DEFAULT_LIB="\$(libdb)"
- DEFAULT_LIB_CXX="\$(libcxx)"
- DEFAULT_INSTALL="install_static"
POSTLINK="@true"
o=".o"
fi
if test "$enable_shared" = "yes"; then
DEFAULT_LIB="\$(libso_target)"
- DEFAULT_LIB_CXX="\$(libxso_target)"
- DEFAULT_INSTALL="${DEFAULT_INSTALL} install_shared"
POSTLINK="\$(LIBTOOL) --mode=execute true"
o=".lo"
fi
+INSTALL_LIBS="$DEFAULT_LIB"
# Optional C++ API.
if test "$db_cv_cxx" = "yes"; then
if test "$enable_shared" = "no"; then
- DEFAULT_INSTALL="${DEFAULT_INSTALL} install_static_cxx"
+ DEFAULT_LIB_CXX="\$(libcxx)"
fi
if test "$enable_shared" = "yes"; then
- ADDITIONAL_LIBS="$ADDITIONAL_LIBS \$(libxso_target)"
- DEFAULT_INSTALL="${DEFAULT_INSTALL} install_shared_cxx"
+ DEFAULT_LIB_CXX="\$(libxso_target)"
fi
+ INSTALL_LIBS="$INSTALL_LIBS $DEFAULT_LIB_CXX"
# Fill in C++ library for Embedix.
EMBEDIX_ECD_CXX='<OPTION db-extra>\
AC_MSG_ERROR([Java requires shared libraries])
fi
- AC_CHECK_TOOL(JAVAC, javac, nojavac)
- if test "$JAVAC" = "nojavac"; then
- AC_MSG_ERROR([no javac compiler in PATH])
- fi
- AC_CHECK_TOOL(JAR, jar, nojar)
- if test "$JAR" = "nojar"; then
- AC_MSG_ERROR([no jar utility in PATH])
- fi
- AC_PATH_PROG(JAVACABS, javac, nojavac)
- ADDITIONAL_LIBS="$ADDITIONAL_LIBS \$(libjso_target)"
- ADDITIONAL_LANG="$ADDITIONAL_LANG java"
- DEFAULT_INSTALL="${DEFAULT_INSTALL} install_java"
-
-# find the include directory relative to the javac executable
- while ls -ld "$JAVACABS" 2>/dev/null | grep " -> " >/dev/null; do
- AC_MSG_CHECKING(symlink for $JAVACABS)
- JAVACLINK=`ls -ld $JAVACABS | sed 's/.* -> //'`
- case "$JAVACLINK" in
- /*) JAVACABS="$JAVACLINK";;
-# 'X' avoids triggering unwanted echo options.
- *) JAVACABS=`echo "X$JAVACABS" | sed -e 's/^X//' -e 's:[[^/]]*$::'`"$JAVACLINK";;
- esac
- AC_MSG_RESULT($JAVACABS)
- done
- JTOPDIR=`echo "$JAVACABS" | sed -e 's://*:/:g' -e 's:/[[^/]]*$::'`
- case "$host_os" in
- darwin*) JTOPDIR=`echo "$JTOPDIR" | sed -e s:/[[^/]]*$::'`
- JNIHEADERDIR="$JTOPDIR/Headers";;
- *) JNIHEADERDIR="$JTOPDIR/include";;
- esac
- if test -f "$JNIHEADERDIR/jni.h"; then
- CPPFLAGS="$CPPFLAGSS -I$JNIHEADERDIR"
- else
- JTOPDIR=`echo "$JTOPDIR" | sed -e 's:/[[^/]]*$::'`
- if test -f "$JTOPDIR/include/jni.h"; then
- CPPFLAGS="$CPPFLAGS -I$JTOPDIR/include"
- else
- AC_MSG_ERROR([cannot find java include files])
- fi
- fi
-
-# get the likely subdirectories for system specific java includes
- case "$host_os" in
- solaris*) JINCSUBDIRS="solaris";;
- linux*) JINCSUBDIRS="linux genunix";;
- *) JINCSUBDIRS="genunix";;
- esac
+ AC_PROG_JAVAC
+ AC_PROG_JAR
+ AC_JNI_INCLUDE_DIR
- for JINCSUBDIR in $JINCSUBDIRS
+ for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS
do
- if test -d "$JTOPDIR/include/$JINCSUBDIR"; then
- CPPFLAGS="$CPPFLAGS -I$JTOPDIR/include/$JINCSUBDIR"
- fi
+ CPPFLAGS="$CPPFLAGS -I$JNI_INCLUDE_DIR"
done
+
+ ADDITIONAL_LANG="$ADDITIONAL_LANG java"
+ INSTALL_LIBS="$INSTALL_LIBS \$(libjso_target)"
else
JAVAC=nojavac
fi
ADDITIONAL_PROGS="db_dump185 $ADDITIONAL_PROGS"
fi
-# test servers, example programs.
-# Include -lpthread if the library exists.
-AC_CHECK_LIB(rt, sched_yield, TEST_LIBS="-lrt $TEST_LIBS")
-AC_CHECK_LIB(pthread, pthread_create, TEST_LIBS="-lpthread $TEST_LIBS")
-
# Checks for system/compiler characteristics.
AC_C_BIGENDIAN
AC_C_CONST
# Check for C types.
AM_TYPES
-# Check for ANSI C exit success/failure values.
-AC_EGREP_CPP(yes, [
- #include <stdlib.h>
- #ifdef EXIT_SUCCESS
- yes
- #endif], [
- AC_DEFINE(HAVE_EXIT_SUCCESS)
- AH_TEMPLATE(HAVE_EXIT_SUCCESS, [
- Define if you have EXIT_SUCCESS/EXIT_FAILURE #defines.])])
-
-# Check for mutexes. We do this here because it changes $LIBS.
+AC_CACHE_CHECK([for ANSI C exit success/failure values], db_cv_exit_defines, [
+AC_TRY_COMPILE([#include <stdlib.h>], return (EXIT_SUCCESS);,
+ [db_cv_exit_defines=yes], [db_cv_exit_defines=no])])
+if test "$db_cv_exit_defines" = yes; then
+ AC_DEFINE(HAVE_EXIT_SUCCESS)
+ AH_TEMPLATE(HAVE_EXIT_SUCCESS, [
+ Define if you have EXIT_SUCCESS/EXIT_FAILURE #defines.])
+fi
+
+# Test for sched_yield, the test programs use it.
+# We do this here because it changes $LIBS.
+AC_MSG_CHECKING([for sched_yield in current configuration])
+AC_TRY_LINK([#include <sched.h>],(void)sched_yield();,
+ AC_MSG_RESULT(yes), [
+ AC_MSG_RESULT(no)
+ AC_MSG_CHECKING([for sched_yield in -lrt])
+ saved_libs=$LIBS
+ LIBS="$LIBS -lrt"
+ AC_TRY_LINK([#include <sched.h>],(void)sched_yield();,
+ AC_MSG_RESULT(yes), LIBS="$saved_libs"; AC_MSG_RESULT(no))])
+
+# Test for a pthreads library, the test programs use it.
+# We do this here because it changes $LIBS.
+#
+# XXX
+# We can't do checking similar to the above because the Solaris C library
+# includes pthread interfaces which are not thread-safe. For that reason
+# we always add -lpthread if we can find a pthread library. Also we can't
+# depend on any specific call existing (pthread_create, for example), as
+# it may be #defined in an include file -- OSF/1 (Tru64) has this problem.
+AC_CHECK_LIB(pthread, main, TEST_LIBS="$TEST_LIBS -lpthread")
+
+# Check for mutexes.
+# We do this here because it changes $LIBS.
AM_DEFINE_MUTEXES
# Checks for system functions for which we have replacements.
# Check for system functions we optionally use.
AC_CHECK_FUNCS(_fstati64 getuid pstat_getdynamic sched_yield select strtoul)
-AC_CHECK_FUNCS(sysconf yield)
+AC_CHECK_FUNCS(gettimeofday clock_gettime sysconf yield)
# Pread/pwrite.
#
# file. If the user has requested unique names, use the file that does
# DB_VERSION_UNIQUE_NAME substitution.
if test "$db_cv_uniquename" = "yes"; then
- CREATE_LIST="${CREATE_LIST}
+ CREATE_LIST="$CREATE_LIST
db.h:$srcdir/../include/db.in:$srcdir/../include_auto/rpc_defs.in:$srcdir/../include_auto/global_uext.in"
else
- CREATE_LIST="${CREATE_LIST}
+ CREATE_LIST="$CREATE_LIST
db.h:$srcdir/../include/db.in:$srcdir/../include_auto/rpc_defs.in:$srcdir/../include_auto/global_ext.in"
fi
# Create the function prototype include files. If the user has requested
# unique names, use the files that do DB_VERSION_UNIQUE_NAME substitution.
if test "$db_cv_uniquename" = "yes"; then
- CREATE_LIST="${CREATE_LIST}
+ CREATE_LIST="$CREATE_LIST
db_ext.h:$srcdir/../include_auto/db_ext.in
btree_ext.h:$srcdir/../include_auto/btree_ext.in
clib_ext.h:$srcdir/../include_auto/clib_ext.in
mutex_ext.h:$srcdir/../include_auto/mutex_ext.in
os_ext.h:$srcdir/../include_auto/os_ext.in
qam_ext.h:$srcdir/../include_auto/qam_ext.in
+ rep_ext.h:$srcdir/../include_auto/rep_ext.in
rpc_client_ext.h:$srcdir/../include_auto/rpc_client_ext.in
rpc_server_ext.h:$srcdir/../include_auto/rpc_server_ext.in
tcl_ext.h:$srcdir/../include_auto/tcl_ext.in
fi
if test "$db_cv_compat185" = "yes"; then
if test "$db_cv_uniquename" = "yes"; then
- CREATE_LIST="${CREATE_LIST}
+ CREATE_LIST="$CREATE_LIST
db_185.h:$srcdir/../include/db_185.in:$srcdir/../include_auto/db185_uext.in
db185_int.h:$srcdir/../db185/db185_int.in:$srcdir/../include_auto/db185_uext.in"
else
- CREATE_LIST="${CREATE_LIST}
+ CREATE_LIST="$CREATE_LIST
db_185.h:$srcdir/../include/db_185.in:$srcdir/../include_auto/db185_ext.in
db185_int.h:$srcdir/../db185/db185_int.in:$srcdir/../include_auto/db185_ext.in"
fi
fi
if test "$db_cv_embedix" = "yes"; then
- CREATE_LIST="${CREATE_LIST} db.ecd:../dist/db.ecd.in"
+ CREATE_LIST="$CREATE_LIST db.ecd:../dist/db.ecd.in"
fi
if test "$db_cv_rpm" = "yes"; then
- CREATE_LIST="${CREATE_LIST} db.spec:../dist/db.spec.in"
+ CREATE_LIST="$CREATE_LIST db.spec:../dist/db.spec.in"
fi
-AC_CONFIG_FILES(${CREATE_LIST})
+AC_CONFIG_FILES($CREATE_LIST)
AC_OUTPUT
# Name
-# C == Java case value
# D == documentation
# I == include file
-# J == Java constant
+# C == Java case value (declared and initialized)
+# J == Java constant (declared only)
DB_AFTER D I J
DB_AGGRESSIVE D I J
DB_ALREADY_ABORTED * I *
DB_AM_TXN * I *
DB_AM_VERIFYING * I *
DB_APPEND D I J
+DB_APPLY_LOGREG * I *
DB_ARCH_ABS D I J
DB_ARCH_DATA D I J
DB_ARCH_LOG D I J
DB_BEFORE D I J
+DB_BROADCAST_EID D I J
DB_BTREE * I C
DB_BTREEMAGIC * I *
DB_BTREEOLDVER * I *
DB_CDB_ALLDB D I J
DB_CHECKPOINT D I J
DB_CLIENT D I J
+DB_CL_WRITER * I *
DB_COMMIT * I *
DB_CONFIG D * *
DB_CONSUME D I J
DB_ENV_CREATE * I *
DB_ENV_DBLOCAL * I *
DB_ENV_LOCKDOWN * I *
+DB_ENV_NOLOCKING * I *
DB_ENV_NOMMAP * I *
+DB_ENV_NOPANIC * I *
DB_ENV_OPEN_CALLED * I *
-DB_ENV_PANIC_OK * I *
DB_ENV_PRIVATE * I *
+DB_ENV_REGION_INIT * I *
+DB_ENV_REP_CLIENT * I *
+DB_ENV_REP_LOGSONLY * I *
+DB_ENV_REP_MASTER * I *
DB_ENV_RPCCLIENT * I *
DB_ENV_RPCCLIENT_GIVEN * I *
DB_ENV_STANDALONE * I *
DB_ENV_THREAD * I *
DB_ENV_TXN_NOSYNC * I *
DB_ENV_USER_ALLOC * I *
+DB_ENV_YIELDCPU * I *
DB_EXCL D I J
DB_EXTENT * I *
DB_FAST_STAT D I J
DB_FORCE D I J
DB_GET_BOTH D I J
DB_GET_BOTHC * I *
+DB_GET_BOTH_RANGE D I J
DB_GET_RECNO D I J
DB_HASH * I C
DB_HASHMAGIC * I *
DB_INIT_LOG D I J
DB_INIT_MPOOL D I J
DB_INIT_TXN D I J
+DB_INVALID_EID * I *
DB_JAVA_CALLBACK * I *
DB_JOINENV D I J
DB_JOIN_ITEM D I J
DB_LOCK_DEFAULT D I J
DB_LOCK_DIRTY * I *
DB_LOCK_DUMP * I *
+DB_LOCK_EXPIRE D I J
+DB_LOCK_FREE_LOCKER * I *
DB_LOCK_GET D I J
+DB_LOCK_GET_TIMEOUT D I J
DB_LOCK_INHERIT * I *
DB_LOCK_IREAD * I J
DB_LOCK_IWR * I J
DB_LOCK_PUT D I J
DB_LOCK_PUT_ALL D I J
DB_LOCK_PUT_OBJ D I J
+DB_LOCK_PUT_READ * I *
DB_LOCK_RANDOM D I J
DB_LOCK_READ * I J
DB_LOCK_RECORD * I *
+DB_LOCK_SET_TIMEOUT * I *
DB_LOCK_SWITCH * I *
+DB_LOCK_TIMEOUT D I J
DB_LOCK_UPGRADE * I *
DB_LOCK_UPGRADE_WRITE * I *
DB_LOCK_WAIT * I *
DB_LOCK_WRITE * I J
DB_LOCK_WWRITE * I *
DB_LOCK_YOUNGEST D I J
+DB_LOGC_BUF_SIZE * I *
DB_LOGFILEID_INVALID * I *
DB_LOGMAGIC * I *
DB_LOGOLDVER * I *
DB_LOGVERSION * I *
+DB_LOG_DISK * I *
+DB_LOG_LOCKED * I *
+DB_LOG_SILENT_ERR * I *
DB_LSTAT_ABORTED * I *
DB_LSTAT_ERR * I *
+DB_LSTAT_EXPIRED * I *
DB_LSTAT_FREE * I *
DB_LSTAT_HELD * I *
-DB_LSTAT_NOGRANT * I *
DB_LSTAT_PENDING * I *
DB_LSTAT_WAITING * I *
DB_MAX_PAGES * I *
DB_MPOOL_DISCARD D I *
DB_MPOOL_LAST D I *
DB_MPOOL_NEW D I *
-DB_MPOOL_NEW_GROUP * I *
DB_MULTIPLE D I J
DB_MULTIPLE_INIT D I *
DB_MULTIPLE_KEY D I J
DB_NEXT_DUP D I J
DB_NEXT_NODUP D I J
DB_NODUPDATA D I J
+DB_NOLOCKING D I J
DB_NOMMAP D I J
DB_NOORDERCHK D I J
DB_NOOVERWRITE D I J
+DB_NOPANIC D I J
DB_NOSERVER D I C
DB_NOSERVER_HOME D I C
DB_NOSERVER_ID D I C
DB_NOSYNC D I J
DB_NOTFOUND D I C
-DB_ODDFILESIZE * I *
+DB_ODDFILESIZE D I J
DB_OK_BTREE * I *
DB_OK_HASH * I *
DB_OK_QUEUE * I *
DB_ORDERCHKONLY D I J
DB_PAGE_LOCK * I *
DB_PAGE_NOTFOUND D I C
+DB_PANIC_ENVIRONMENT D I J
DB_POSITION D I J
DB_POSITIONI * I *
DB_PREV D I J
DB_RECOVER D I J
DB_RECOVER_FATAL D I J
DB_REDO * I *
+DB_REGION_INIT D I J
DB_REGION_MAGIC * I *
DB_RENUMBER D I J
+DB_REP_CLIENT D I J
+DB_REP_DUPMASTER D I C
+DB_REP_HOLDELECTION D I C
+DB_REP_LOGSONLY D I J
+DB_REP_MASTER D I J
+DB_REP_NEWMASTER D I C
+DB_REP_NEWSITE D I C
+DB_REP_OUTDATED D I C
+DB_REP_PERMANENT D I J
+DB_REP_UNAVAIL D I J
DB_REVSPLITOFF D I J
DB_RE_DELIMITER * I *
DB_RE_FIXEDLEN * I *
DB_SALVAGE D I J
DB_SECONDARY_BAD D I C
DB_SET D I J
+DB_SET_LOCK_TIMEOUT D I J
DB_SET_RANGE D I J
DB_SET_RECNO D I J
+DB_SET_TXN_NOW * I *
+DB_SET_TXN_TIMEOUT D I J
DB_SNAPSHOT D I J
+DB_STAT_CLEAR D I J
DB_SURPRISE_KID * I *
DB_SWAPBYTES * I *
DB_SYSTEM_MEM D I J
DB_TEST_PREDESTROY * I *
DB_TEST_PREOPEN * I *
DB_THREAD D I J
+DB_TIMEOUT * I *
DB_TRUNCATE D I J
DB_TXNVERSION * I *
DB_TXN_ABORT D I C
+DB_TXN_APPLY * I *
DB_TXN_BACKWARD_ROLL D I C
DB_TXN_CKP * I *
DB_TXN_FORWARD_ROLL D I C
DB_WRITELOCK * I *
DB_XA_CREATE D I J
DB_XIDDATASIZE D I J
+DB_YIELDCPU D I J
<h1>DbMultipleDataIterator</h1>
</td>
<td align=right>
-<a href="../api_java/java_index.html"><img src="../images/api.gif" alt="API"></a><a href="../reftoc.html"><img src="../images/ref.gif" alt="Ref"></a>
+<a href="../api_java/c_index.html"><img src="../images/api.gif" alt="API"></a><a href="../reftoc.html"><img src="../images/ref.gif" alt="Ref"></a>
</td></tr></table>
<hr size=1 noshade>
<tt>
</dl>
</tt>
<table width="100%"><tr><td><br></td><td align=right>
-<a href="../api_java/java_index.html"><img src="../images/api.gif" alt="API"></a><a href="../reftoc.html"><img src="../images/ref.gif" alt="Ref"></a>
+<a href="../api_java/c_index.html"><img src="../images/api.gif" alt="API"></a><a href="../reftoc.html"><img src="../images/ref.gif" alt="Ref"></a>
</td></tr></table>
<p><font size=1><a href="http://www.sleepycat.com">Copyright Sleepycat Software</a></font>
</body>
-<!--Id: faq.so,v 10.2 2001/07/06 13:15:47 bostic Exp -->
+<!--Id: faq.so,v 10.3 2001/10/13 19:56:25 bostic Exp -->
<!--Copyright 1997-2001 by Sleepycat Software, Inc.-->
<!--All rights reserved.-->
<html>
<a name="2"><!--meow--></a>
<table width="100%"><tr valign=top>
<td><h3><dl><dt>Berkeley DB Reference Guide:<dd>Berkeley DB Transactional Data Store Applications</dl></h3></td>
-<td align=right><a href="../../ref/transapp/throughput.html"><img src="../../images/prev.gif" alt="Prev"></a><a href="../../reftoc.html"><img src="../../images/ref.gif" alt="Ref"></a><a href="../../ref/xa/intro.html"><img src="../../images/next.gif" alt="Next"></a>
+<td align=right><a href="../../ref/transapp/throughput.html"><img src="../../images/prev.gif" alt="Prev"></a><a href="../../reftoc.html"><img src="../../images/ref.gif" alt="Ref"></a><a href="../../ref/rep/intro.html"><img src="../../images/next.gif" alt="Next"></a>
</td></tr></table>
<p>
<h1 align=center>Transaction FAQ</h1>
searched-for key item is not present in the database. Applications may
want to explicitly test for and handle this error, or, in the case where
the absence of a key implies the enclosing transaction should fail,
-simply call <a href="../../api_c/txn_abort.html">txn_abort</a>. Unexpected but recoverable errors are
+simply call <a href="../../api_c/txn_abort.html">DB_TXN->abort</a>. Unexpected but recoverable errors are
errors like <a href="../../ref/program/errorret.html#DB_LOCK_DEADLOCK">DB_LOCK_DEADLOCK</a>, which indicates that an operation
has been selected to resolve a deadlock, or a system error such as EIO,
which likely indicates that the filesystem has no available disk space.
-Applications must immediately call <a href="../../api_c/txn_abort.html">txn_abort</a> when these returns
+Applications must immediately call <a href="../../api_c/txn_abort.html">DB_TXN->abort</a> when these returns
occur, as it is not possible to proceed otherwise. The only
unrecoverable error is <a href="../../ref/program/errorret.html#DB_RUNRECOVERY">DB_RUNRECOVERY</a>, which indicates that the
system must stop and recovery must be run.
<p>See <a href="../../ref/transapp/reclimit.html">Berkeley DB recoverability</a>
for more detailed information.
</ol>
-<table width="100%"><tr><td><br></td><td align=right><a href="../../ref/transapp/throughput.html"><img src="../../images/prev.gif" alt="Prev"></a><a href="../../reftoc.html"><img src="../../images/ref.gif" alt="Ref"></a><a href="../../ref/xa/intro.html"><img src="../../images/next.gif" alt="Next"></a>
+<table width="100%"><tr><td><br></td><td align=right><a href="../../ref/transapp/throughput.html"><img src="../../images/prev.gif" alt="Prev"></a><a href="../../reftoc.html"><img src="../../images/ref.gif" alt="Ref"></a><a href="../../ref/rep/intro.html"><img src="../../images/next.gif" alt="Next"></a>
</td></tr></table>
<p><font size=1><a href="http://www.sleepycat.com">Copyright Sleepycat Software</a></font>
</body>
* Copyright (c) 1999-2001
* Sleepycat Software. All rights reserved.
*
- * Id: hash_verify.c,v 1.39 2001/07/02 01:05:39 bostic Exp
+ * Id: hash_verify.c,v 1.41 2001/07/25 21:59:31 krinsky Exp
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "Id: hash_verify.c,v 1.39 2001/07/02 01:05:39 bostic Exp ";
+static const char revid[] = "Id: hash_verify.c,v 1.41 2001/07/25 21:59:31 krinsky Exp ";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
u_int32_t flags;
{
DB *pgset;
+ DB_MPOOLFILE *mpf;
HMETA *m;
PAGE *h;
VRFY_PAGEINFO *pip;
db_pgno_t pgno;
u_int32_t bucket, spares_entry;
- ret = isbad = 0;
- h = NULL;
+ mpf = dbp->mpf;
pgset = vdp->pgset;
+ h = NULL;
+ ret = isbad = 0;
if ((ret = __db_vrfy_pgset_get(pgset, meta_pgno, &p)) != 0)
return (ret);
return (ret);
/* Get the meta page; we'll need it frequently. */
- if ((ret = memp_fget(dbp->mpf, &meta_pgno, 0, &m)) != 0)
+ if ((ret = mpf->get(mpf, &meta_pgno, 0, &m)) != 0)
return (ret);
/* Loop through bucket by bucket. */
goto err;
}
-err: if ((t_ret = memp_fput(dbp->mpf, m, 0)) != 0)
+err: if ((t_ret = mpf->put(mpf, m, 0)) != 0)
return (t_ret);
- if (h != NULL && (t_ret = memp_fput(dbp->mpf, h, 0)) != 0)
+ if (h != NULL && (t_ret = mpf->put(mpf, h, 0)) != 0)
return (t_ret);
return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD: ret);
}
u_int32_t (*hfunc) __P((DB *, const void *, u_int32_t));
{
DBT dbt;
+ DB_MPOOLFILE *mpf;
PAGE *h;
db_indx_t i;
int ret, t_ret, isbad;
u_int32_t hval, bucket;
+ mpf = dbp->mpf;
ret = isbad = 0;
+
memset(&dbt, 0, sizeof(DBT));
F_SET(&dbt, DB_DBT_REALLOC);
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
return (ret);
for (i = 0; i < nentries; i += 2) {
err: if (dbt.data != NULL)
__os_free(dbp->dbenv, dbt.data, 0);
- if ((t_ret = memp_fput(dbp->mpf, h, 0)) != 0)
+ if ((t_ret = mpf->put(mpf, h, 0)) != 0)
return (t_ret);
return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
dbt.size = len;
dbt.data = buf;
if ((ret = __db_prdbt(&dbt,
- 0, " ", handle, callback, 0, NULL)) != 0)
+ 0, " ", handle, callback, 0, vdp)) != 0)
err_ret = ret;
break;
case H_OFFPAGE:
dpgno, &dbt, &buf, flags)) != 0) {
err_ret = ret;
(void)__db_prdbt(&unkdbt, 0, " ",
- handle, callback, 0, NULL);
+ handle, callback, 0, vdp);
break;
}
if ((ret = __db_prdbt(&dbt,
- 0, " ", handle, callback, 0, NULL)) != 0)
+ 0, " ", handle, callback, 0, vdp)) != 0)
err_ret = ret;
break;
case H_OFFDUP:
/* UNKNOWN iff pgno is bad or we're a key. */
if (!IS_VALID_PGNO(dpgno) || (i % 2 == 0)) {
if ((ret = __db_prdbt(&unkdbt, 0, " ",
- handle, callback, 0, NULL)) != 0)
+ handle, callback, 0, vdp)) != 0)
err_ret = ret;
} else if ((ret = __db_salvage_duptree(dbp,
vdp, dpgno, &dbt, handle, callback,
dbt.size = dlen;
dbt.data = buf;
if ((ret = __db_prdbt(&dbt, 0, " ",
- handle, callback, 0, NULL)) != 0)
+ handle, callback, 0, vdp)) != 0)
err_ret = ret;
tlen += sizeof(db_indx_t);
}
u_int32_t flags;
DB *pgset;
{
+ DB_MPOOLFILE *mpf;
PAGE *h;
db_pgno_t pgno;
u_int32_t bucket, totpgs;
DB_ASSERT(pgset != NULL);
+ mpf = dbp->mpf;
totpgs = 0;
/*
* Safely walk the list of pages in this bucket.
*/
for (;;) {
- if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
return (ret);
if (TYPE(h) == P_HASH) {
* pgset.
*/
if (++totpgs > vdp->last_pgno) {
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
return (DB_VERIFY_BAD);
}
if ((ret =
__db_vrfy_pgset_inc(pgset, pgno)) != 0) {
- (void)memp_fput(dbp->mpf, h, 0);
+ (void)mpf->put(mpf, h, 0);
return (ret);
}
} else
pgno = PGNO_INVALID;
- if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
+ if ((ret = mpf->put(mpf, h, 0)) != 0)
return (ret);
/* If the new pgno is wonky, go onto the next bucket. */
* Copyright (c) 1996-2001
* Sleepycat Software. All rights reserved.
*
- * Id: log.h,v 11.26 2001/07/05 18:41:03 bostic Exp
+ * Id: log.h,v 11.35 2001/10/09 18:13:26 ubell Exp
*/
#ifndef _LOG_H_
* The per-process table that maps log file-id's to DB structures.
*/
typedef struct __db_entry {
- TAILQ_HEAD(dblist, __db) dblist; /* Associated DB structures. */
+ TAILQ_HEAD(dblist, __db) dblist;/* Associated DB structures. */
u_int32_t refcount; /* Reference counted. */
u_int32_t count; /* Number of ops on a deleted db. */
int deleted; /* File was not found during open. */
* to be stored elsewhere on architectures unable to support mutexes in heap
* memory, e.g., HP/UX 9.
*/
- MUTEX *mutexp; /* Mutex for thread protection. */
+ DB_MUTEX *mutexp; /* Mutex for thread protection. */
DB_ENTRY *dbentry; /* Recovery file-id mapping. */
#define DB_GROW_SIZE 64
u_int32_t lfname; /* Log file "name". */
DB_FH lfh; /* Log file handle. */
- DB_LSN c_lsn; /* Cursor: current LSN. */
- DBT c_dbt; /* Cursor: return DBT structure. */
- DB_FH c_fh; /* Cursor: file handle. */
- u_int32_t c_off; /* Cursor: previous record offset. */
- u_int32_t c_len; /* Cursor: current record length. */
- u_int32_t r_file; /* Cursor: current read file */
- u_int32_t r_off; /* Cursor: offset of read buffer. */
- u_int32_t r_size; /* Cursor: size of data in read buf. */
-
u_int8_t *bufp; /* Region buffer. */
- u_int8_t *readbufp; /* Read buffer. */
/* These fields are not protected. */
DB_ENV *dbenv; /* Reference to error information. */
REGINFO reginfo; /* Region information. */
#define DBLOG_RECOVER 0x01 /* We are in recovery. */
-#define DBLOG_FORCE_OPEN 0x02 /* Force the db open even
- * if it appears to be deleted.
+#define DBLOG_FORCE_OPEN 0x02 /* Force the DB open even if it appears
+ * to be deleted.
*/
u_int32_t flags;
};
DB_LSN lsn; /* LSN at current file offset. */
/*
- * The s_lsn LSN is the last LSN that we know is on disk, not just
- * written, but synced.
+ * The f_lsn LSN is the LSN (returned to the user) that "owns" the
+ * first byte of the buffer. If the record associated with the LSN
+ * spans buffers, it may not reflect the physical file location of
+ * the first byte of the buffer.
*/
- DB_LSN s_lsn; /* LSN of the last sync. */
-
+ DB_LSN f_lsn; /* LSN of first byte in the buffer. */
+ size_t b_off; /* Current offset in the buffer. */
+ u_int32_t w_off; /* Current write offset in the file. */
u_int32_t len; /* Length of the last record. */
- u_int32_t w_off; /* Current write offset in the file. */
+ /*
+ * The s_lsn LSN is the last LSN that we know is on disk, not just
+ * written, but synced. This field only is protected by the
+ * flush mutex rather than by the region mutex.
+ */
+ int in_flush; /* Log flush in progress. */
+ DB_MUTEX flush; /* Mutex for flushing. */
+ DB_LSN s_lsn; /* LSN of the last sync. */
DB_LSN chkpt_lsn; /* LSN of the last checkpoint. */
time_t chkpt; /* Time of the last checkpoint. */
DB_LOG_STAT stat; /* Log statistics. */
/*
- * The f_lsn LSN is the LSN (returned to the user) that "owns" the
- * first byte of the buffer. If the record associated with the LSN
- * spans buffers, it may not reflect the physical file location of
- * the first byte of the buffer.
+ * The waiting_lsn is used by the replication system. It is the
+ * first LSN that we are holding without putting in the log, because
+ * we received one or more log records out of order.
*/
- DB_LSN f_lsn; /* LSN of first byte in the buffer. */
- size_t b_off; /* Current offset in the buffer. */
+ DB_LSN waiting_lsn; /* First log record after a gap. */
- roff_t buffer_off; /* Log buffer offset. */
+ /*
+ * The ready_lsn is also used by the replication system. It is the
+ * next LSN we expect to receive. It's normally equal to "lsn",
+ * except at the beginning of a log file, at which point it's set
+ * to the LSN of the first record of the new file (after the
+ * header), rather than to 0.
+ */
+ DB_LSN ready_lsn;
+
+
+ roff_t buffer_off; /* Log buffer offset in the region. */
u_int32_t buffer_size; /* Log buffer size. */
+ u_int32_t ncommit; /* Number of txns waiting to commit. */
+
+ DB_LSN t_lsn; /* LSN of first commit */
+ SH_TAILQ_HEAD(__commit) commits;/* list of txns waiting to commit. */
+ SH_TAILQ_HEAD(__free) free_commits;/* free list of commit structs. */
+
#ifdef MUTEX_SYSTEM_RESOURCES
#define LG_MAINT_SIZE (sizeof(roff_t) * DB_MAX_HANDLES)
};
/*
+ * __db_commit structure --
+ * One of these is allocated for each transaction waiting
+ * to commit.
+ */
+struct __db_commit {
+ DB_MUTEX mutex; /* Mutex for txn to wait on. */
+ DB_LSN lsn; /* LSN of commit record. */
+ SH_TAILQ_ENTRY links; /* Either on free or waiting list. */
+
+#define DB_COMMIT_FLUSH 0x0001 /* Flush the log when you wake up. */
+ u_int32_t flags;
+};
+
+/*
* FNAME --
* File name and id.
*/
DB_LV_OLD_UNREADABLE
} logfile_validity;
+/*
+ * Boolean macro that returns whether or not a specified log_put flags
+ * value indicates that the log should be sync'ed to disk.
+ */
+#define FLUSH_ON_FLAG(flags) \
+ ((flags) == DB_COMMIT || (flags) == DB_FLUSH || (flags) == DB_CHECKPOINT)
+
#include "log_auto.h"
#include "log_ext.h"
#endif /* _LOG_H_ */
#include "db_config.h"
#ifndef lint
-static const char revid[] = "Id: log.c,v 11.56 2001/07/05 14:24:45 bostic Exp ";
+static const char revid[] = "Id: log.c,v 11.69 2001/10/02 01:33:40 bostic Exp ";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <unistd.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
#include "log.h"
#include "db_dispatch.h"
#include "txn.h"
#include "txn_auto.h"
-#ifdef HAVE_RPC
-#include "rpc_client_ext.h"
-#endif
-
static int __log_init __P((DB_ENV *, DB_LOG *));
static int __log_recover __P((DB_LOG *));
static size_t __log_region_size __P((DB_ENV *));
DB_LOG *dblp;
LOG *lp;
int ret;
- u_int8_t *readbufp;
-
- readbufp = NULL;
/* Create/initialize the DB_LOG structure. */
if ((ret = __os_calloc(dbenv, 1, sizeof(DB_LOG), &dblp)) != 0)
return (ret);
- if ((ret = __os_calloc(dbenv, 1, dbenv->lg_bsize, &readbufp)) != 0)
- goto err;
- ZERO_LSN(dblp->c_lsn);
dblp->dbenv = dbenv;
/* Join/create the log region. */
dbenv, &dblp->reginfo, __log_region_size(dbenv))) != 0)
goto err;
- dblp->readbufp = readbufp;
-
/* If we created the region, initialize it. */
- if (F_ISSET(&dblp->reginfo, REGION_CREATE) &&
- (ret = __log_init(dbenv, dblp)) != 0)
- goto err;
+ if (F_ISSET(&dblp->reginfo, REGION_CREATE))
+ if ((ret = __log_init(dbenv, dblp)) != 0)
+ goto err;
/* Set the local addresses. */
lp = dblp->reginfo.primary =
R_ADDR(&dblp->reginfo, dblp->reginfo.rp->primary);
- dblp->bufp = R_ADDR(&dblp->reginfo, lp->buffer_off);
/*
* If the region is threaded, then we have to lock both the handles
goto err;
}
- R_UNLOCK(dbenv, &dblp->reginfo);
+ /* Initialize the rest of the structure. */
+ dblp->bufp = R_ADDR(&dblp->reginfo, lp->buffer_off);
- dblp->r_file = 0;
- dblp->r_off = 0;
- dblp->r_size = 0;
+ /*
+ * Set the handle -- we may be about to run recovery, which allocates
+ * log cursors. Log cursors require logging be already configured,
+ * and the handle being set is what demonstrates that.
+ */
dbenv->lg_handle = dblp;
+
+ /* If we created the region, run recovery. */
+ if (F_ISSET(&dblp->reginfo, REGION_CREATE))
+ if ((ret = __log_recover(dblp)) != 0)
+ goto err;
+
+ R_UNLOCK(dbenv, &dblp->reginfo);
return (0);
err: if (dblp->reginfo.addr != NULL) {
(void)__db_r_detach(dbenv, &dblp->reginfo, 0);
}
- if (readbufp != NULL)
- __os_free(dbenv, readbufp, dbenv->lg_bsize);
if (dblp->mutexp != NULL)
__db_mutex_free(dbenv, &dblp->reginfo, dblp->mutexp);
+
__os_free(dbenv, dblp, sizeof(*dblp));
+
return (ret);
}
/* Initialize LOG LSNs. */
region->lsn.file = 1;
region->lsn.offset = 0;
+ region->waiting_lsn.file = 1;
+ region->waiting_lsn.offset = 0;
+ region->ready_lsn.file = 1;
+ region->ready_lsn.offset = 0;
+ region->t_lsn.file = 1;
+ region->t_lsn.offset = 0;
#ifdef MUTEX_SYSTEM_RESOURCES
/* Allocate room for the txn maintenance info and initialize it. */
region->maint_off = R_OFFSET(&dblp->reginfo, addr);
#endif
+ if ((ret = __db_shmutex_init(dbenv, ®ion->flush, 0,
+ 0, &dblp->reginfo,
+ (REGMAINT *)R_ADDR(&dblp->reginfo, region->maint_off))) != 0)
+ return (ret);
+
/* Initialize the buffer. */
if ((ret =
__db_shalloc(dblp->reginfo.addr, dbenv->lg_bsize, 0, &p)) != 0) {
region->buffer_size = dbenv->lg_bsize;
region->buffer_off = R_OFFSET(&dblp->reginfo, p);
- /* Try and recover any previous log files before releasing the lock. */
- return (__log_recover(dblp));
+ /* Initialize the commit Queue. */
+ SH_TAILQ_INIT(®ion->free_commits);
+ SH_TAILQ_INIT(®ion->commits);
+ region->ncommit = 0;
+
+ return (0);
}
/*
DB_LOG *dblp;
{
DBT dbt;
+ DB_ENV *dbenv;
+ DB_LOGC *logc;
DB_LSN lsn;
LOG *lp;
int cnt, found_checkpoint, ret;
u_int32_t chk;
logfile_validity status;
+ logc = NULL;
lp = dblp->reginfo.primary;
/*
lsn.file = cnt;
lsn.offset = 0;
- /* Set the cursor. Shouldn't fail; leave error messages on. */
- memset(&dbt, 0, sizeof(dbt));
- if ((ret = __log_get(dblp, &lsn, &dbt, DB_SET, 0)) != 0)
+ /*
+ * Allocate a cursor and set it to the first record. This shouldn't
+ * fail, leave error messages on.
+ */
+ dbenv = dblp->dbenv;
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
return (ret);
+ F_SET(logc, DB_LOG_LOCKED);
+ memset(&dbt, 0, sizeof(dbt));
+ if ((ret = logc->get(logc, &lsn, &dbt, DB_SET)) != 0)
+ goto err;
/*
- * Read to the end of the file, saving checkpoints. This will fail
- * at some point, so turn off error messages.
+ * Read to the end of the file, looking for checkpoints. This will
+ * fail at some point, so turn off error messages.
*/
+ F_SET(logc, DB_LOG_SILENT_ERR);
found_checkpoint = 0;
- while (__log_get(dblp, &lsn, &dbt, DB_NEXT, 1) == 0) {
+ while (logc->get(logc, &lsn, &dbt, DB_NEXT) == 0) {
if (dbt.size < sizeof(u_int32_t))
continue;
memcpy(&chk, dbt.data, sizeof(u_int32_t));
found_checkpoint = 1;
}
}
+ F_CLR(logc, DB_LOG_SILENT_ERR);
/*
* We now know where the end of the log is. Set the first LSN that
*/
lp->lsn = lsn;
lp->s_lsn = lsn;
- lp->lsn.offset += dblp->c_len;
- lp->s_lsn.offset += dblp->c_len;
+ lp->lsn.offset += logc->c_len;
+ lp->s_lsn.offset += logc->c_len;
/* Set up the current buffer information, too. */
- lp->len = dblp->c_len;
+ lp->len = logc->c_len;
lp->b_off = 0;
lp->w_off = lp->lsn.offset;
lsn.file = cnt;
lsn.offset = 0;
- /* Set the cursor. Shouldn't fail, leave error messages on. */
- if ((ret = __log_get(dblp, &lsn, &dbt, DB_SET, 0)) != 0)
- return (ret);
+ /* Set the cursor; shouldn't fail, leave error messages on. */
+ if ((ret = logc->get(logc, &lsn, &dbt, DB_SET)) != 0)
+ goto err;
/*
- * Read to the end of the file, saving checkpoints. Again,
- * this can fail if there are no checkpoints in any log file,
- * so turn error messages off.
+ * Read to the end of the file, looking for checkpoints. This
+ * can fail if there are no checkpoints in any log file, so we
+ * turn off error messages.
*/
- while (__log_get(dblp, &lsn, &dbt, DB_PREV, 1) == 0) {
+ F_SET(logc, DB_LOG_SILENT_ERR);
+ while (logc->get(logc, &lsn, &dbt, DB_PREV) == 0) {
if (dbt.size < sizeof(u_int32_t))
continue;
memcpy(&chk, dbt.data, sizeof(u_int32_t));
break;
}
}
+ F_CLR(logc, DB_LOG_SILENT_ERR);
}
/* If we never find a checkpoint, that's okay, just 0 it out. */
if (!found_checkpoint)
skipsearch: ZERO_LSN(lp->chkpt_lsn);
- /*
- * Reset the cursor lsn to the beginning of the log, so that an
- * initial call to DB_NEXT does the right thing.
- */
- ZERO_LSN(dblp->c_lsn);
-
if (FLD_ISSET(dblp->dbenv->verbose, DB_VERB_RECOVERY))
__db_err(dblp->dbenv,
"Finding last valid log LSN: file: %lu offset %lu",
(u_long)lp->lsn.file, (u_long)lp->lsn.offset);
- return (0);
+err: if (logc != NULL)
+ (void)logc->close(logc, 0);
+
+ return (ret);
}
/*
}
/*
- * __log_close --
- * Internal version of log_close: only called from dbenv_refresh.
+ * __log_dbenv_refresh --
+ * Clean up after the log system on a close or failed open. Called only
+ * from __dbenv_refresh. (Formerly called __log_close.)
*
- * PUBLIC: int __log_close __P((DB_ENV *));
+ * PUBLIC: int __log_dbenv_refresh __P((DB_ENV *));
*/
int
-__log_close(dbenv)
+__log_dbenv_refresh(dbenv)
DB_ENV *dbenv;
{
DB_LOG *dblp;
+ u_int32_t buffer_size;
int ret, t_ret;
- ret = 0;
dblp = dbenv->lg_handle;
+ buffer_size = ((LOG *)dblp->reginfo.primary)->buffer_size;
/* We may have opened files as part of XA; if so, close them. */
F_SET(dblp, DBLOG_RECOVER);
if (F_ISSET(&dblp->lfh, DB_FH_VALID) &&
(t_ret = __os_closehandle(&dblp->lfh)) != 0 && ret == 0)
ret = t_ret;
- if (dblp->c_dbt.data != NULL)
- __os_free(dbenv, dblp->c_dbt.data, dblp->c_dbt.ulen);
- if (F_ISSET(&dblp->c_fh, DB_FH_VALID) &&
- (t_ret = __os_closehandle(&dblp->c_fh)) != 0 && ret == 0)
- ret = t_ret;
if (dblp->dbentry != NULL)
__os_free(dbenv, dblp->dbentry,
(dblp->dbentry_cnt * sizeof(DB_ENTRY)));
- if (dblp->readbufp != NULL)
- __os_free(dbenv, dblp->readbufp, dbenv->lg_bsize);
__os_free(dbenv, dblp, sizeof(*dblp));
}
/*
- * log_stat --
+ * __log_stat --
* Return log statistics.
*
- * EXTERN: int log_stat __P((DB_ENV *, DB_LOG_STAT **));
+ * PUBLIC: int __log_stat __P((DB_ENV *, DB_LOG_STAT **, u_int32_t));
*/
int
-log_stat(dbenv, statp)
+__log_stat(dbenv, statp, flags)
DB_ENV *dbenv;
DB_LOG_STAT **statp;
+ u_int32_t flags;
{
DB_LOG *dblp;
DB_LOG_STAT *stats;
LOG *region;
int ret;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_log_stat(dbenv, statp));
-#endif
-
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->lg_handle, "log_stat", DB_INIT_LOG);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lg_handle, "DB_ENV->log_stat", DB_INIT_LOG);
*statp = NULL;
+ if ((ret = __db_fchk(dbenv,
+ "DB_ENV->log_stat", flags, DB_STAT_CLEAR)) != 0)
+ return (ret);
dblp = dbenv->lg_handle;
region = dblp->reginfo.primary;
/* Copy out the global statistics. */
R_LOCK(dbenv, &dblp->reginfo);
*stats = region->stat;
+ if (LF_ISSET(DB_STAT_CLEAR))
+ memset(®ion->stat, 0, sizeof(region->stat));
stats->st_magic = region->persist.magic;
stats->st_version = region->persist.version;
stats->st_region_wait = dblp->reginfo.rp->mutex.mutex_set_wait;
stats->st_region_nowait = dblp->reginfo.rp->mutex.mutex_set_nowait;
+ if (LF_ISSET(DB_STAT_CLEAR)) {
+ dblp->reginfo.rp->mutex.mutex_set_wait = 0;
+ dblp->reginfo.rp->mutex.mutex_set_nowait = 0;
+ }
stats->st_regsize = dblp->reginfo.rp->size;
stats->st_cur_file = region->lsn.file;
COMPQUIET(dbenv, NULL);
COMPQUIET(infop, NULL);
}
+
+/*
+ * __log_vtruncate
+ * This is a virtual truncate. We set up the log indicators to
+ * make everyone believe that the given record is the last one in the
+ * log. Returns with the next valid LSN (i.e., the LSN of the next
+ * record to be written). This is used in replication to discard records
+ * in the log file that do not agree with the master.
+ *
+ * PUBLIC: int __log_vtruncate __P((DB_ENV *, DB_LSN *, DB_LSN *));
+ */
+int
+__log_vtruncate(dbenv, lsn, ckplsn)
+ DB_ENV *dbenv;
+ DB_LSN *lsn, *ckplsn;
+{
+ DBT log_dbt;
+ DB_FH fh;
+ DB_LOG *dblp;
+ DB_LOGC *logc;
+ LOG *lp;
+ u_int32_t bytes, c_len;
+ int fn, ret, t_ret;
+ char *fname;
+
+ /* Need to find out the length of this soon-to-be-last record. */
+ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+ return (ret);
+ memset(&log_dbt, 0, sizeof(log_dbt));
+ ret = logc->get(logc, lsn, &log_dbt, DB_SET);
+ c_len = logc->c_len;
+ if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+ ret = t_ret;
+ if (ret != 0)
+ return (ret);
+
+ /* Now do the truncate. */
+ dblp = (DB_LOG *)dbenv->lg_handle;
+ lp = (LOG *)dblp->reginfo.primary;
+
+ R_LOCK(dbenv, &dblp->reginfo);
+ lp->lsn = *lsn;
+ lp->len = c_len;
+ lp->lsn.offset += lp->len;
+ lp->chkpt_lsn = *ckplsn;
+
+ /*
+ * I am going to assume that the number of bytes written since
+ * the last checkpoint doesn't exceed a 32-bit number.
+ */
+ DB_ASSERT(lp->lsn.file >= ckplsn->file);
+ bytes = 0;
+ if (ckplsn->file != lp->lsn.file) {
+ bytes = lp->persist.lg_max - ckplsn->offset;
+ if (lp->lsn.file > ckplsn->file + 1)
+ bytes += lp->persist.lg_max *
+ (lp->lsn.file - ckplsn->file - 1);
+ bytes += lp->lsn.offset;
+ } else
+ bytes = lp->lsn.offset - ckplsn->offset;
+
+ lp->stat.st_wc_mbytes += bytes / MEGABYTE;
+ lp->stat.st_wc_bytes += bytes % MEGABYTE;
+
+ /*
+ * If the saved lsn is greater than our new end of log, reset it
+ * to our current end of log.
+ */
+ if (log_compare(&lp->s_lsn, lsn) > 0)
+ lp->s_lsn = lp->lsn;
+
+ /*
+ * If the new end of log is in the middle of the
+ * buffer, don't change the w_off. If the new end
+ * is before the w_off then reset w_off to the new
+ * end of log.
+ */
+ if (lp->w_off >= lp->lsn.offset) {
+ lp->w_off = lp->lsn.offset;
+ lp->b_off = 0;
+ } else
+ lp->b_off = lp->lsn.offset - lp->w_off;
+
+ ZERO_LSN(lp->waiting_lsn);
+ lp->ready_lsn = lp->lsn;
+ lp->f_lsn = lp->lsn;
+
+ /* Now throw away any extra log files that we have around. */
+ for (fn = lp->lsn.file + 1;; fn++) {
+ if (__log_name(dblp, fn, &fname, &fh, DB_OSO_RDONLY) != 0)
+ break;
+ (void)__os_closehandle(&fh);
+ if ((ret = __os_unlink(dbenv, fname)) != 0)
+ break;
+ __os_freestr(dbenv, fname);
+ }
+ R_UNLOCK(dbenv, &dblp->reginfo);
+ return (ret);
+}
+
+/*
+ * __log_is_outdated --
+ * Used by the replication system to identify if a client's logs
+ * are too old. The log represented by dbenv is compared to the file
+ * number passed in fnum. If the log file fnum does not exist and is
+ * lower-numbered than the current logs, the we return *outdatedp non
+ * zero, else we return it 0.
+ *
+ * PUBLIC: int __log_is_outdated __P((DB_ENV *dbenv,
+ * PUBLIC: u_int32_t fnum, int *outdatedp));
+ */
+int
+__log_is_outdated(dbenv, fnum, outdatedp)
+ DB_ENV *dbenv;
+ u_int32_t fnum;
+ int *outdatedp;
+{
+ DB_LOG *dblp;
+ LOG *lp;
+ char *name;
+ int ret;
+ u_int32_t cfile;
+
+ dblp = dbenv->lg_handle;
+ *outdatedp = 0;
+
+ if ((ret = __log_name(dblp, fnum, &name, NULL, 0)) != 0)
+ return (ret);
+
+ /* If the file exists, we're just fine. */
+ if (__os_exists(name, NULL) == 0)
+ goto out;
+
+ /*
+ * It didn't exist, decide if the file number is too big or
+ * too little. If it's too little, then we need to indicate
+ * that the LSN is outdated.
+ */
+ R_LOCK(dbenv, &dblp->reginfo);
+ lp = (LOG *)dblp->reginfo.primary;
+ cfile = lp->lsn.file;
+ R_UNLOCK(dbenv, &dblp->reginfo);
+
+ if (cfile > fnum)
+ *outdatedp = 1;
+out: __os_freestr(dbenv, name);
+ return (ret);
+}
#include "db_config.h"
#ifndef lint
-static const char revid[] = "Id: log_rec.c,v 11.60 2001/06/12 01:49:05 bostic Exp ";
+static const char revid[] = "Id: log_rec.c,v 11.67 2001/10/10 02:57:41 margo Exp ";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
static int __log_check_master __P((DB_ENV *, u_int8_t *, char *));
static int __log_do_open __P((DB_ENV *, DB_LOG *,
- u_int8_t *, char *, DBTYPE, int32_t, db_pgno_t));
-static int __log_open_file __P((DB_ENV *, DB_LOG *, __log_register_args *));
+ u_int8_t *, char *, DBTYPE, int32_t, db_pgno_t, u_int32_t));
+static int __log_open_file __P((DB_ENV *,
+ DB_LOG *, __log_register_args *, u_int32_t));
/*
* PUBLIC: int __log_register_recover
DB *dbp;
__log_register_args *argp;
int do_rem, ret, t_ret;
+ u_int32_t flags;
logp = dbenv->lg_handle;
dbp = NULL;
#endif
COMPQUIET(lsnp, NULL);
+ flags = 0;
+
if ((ret = __log_register_read(dbenv, dbtp->data, &argp)) != 0)
goto out;
*/
if (op == DB_TXN_OPENFILES)
F_SET(logp, DBLOG_FORCE_OPEN);
- ret = __log_open_file(dbenv, logp, argp);
+ /*
+ * If we are applying a log_register record in replication,
+ * we may be doing so out-of-order with respect to
+ * a crdel_fileopen record that came before us in the log
+ * but were in a still-uncommitted transaction. Let the
+ * underlying log_register know, so that it can postpone
+ * opening the file until it actually exists.
+ */
+ if (op == DB_TXN_APPLY)
+ flags = DB_APPLY_LOGREG;
+ ret = __log_open_file(dbenv, logp, argp, flags);
F_CLR(logp, DBLOG_FORCE_OPEN);
if (ret == ENOENT || ret == EINVAL) {
if ((op == DB_TXN_OPENFILES || op == DB_TXN_POPENFILES)
if (dbe->refcount != 1) {
__db_err(dbenv,
"Improper file close. LSN: %lu/%lu.",
- (u_long)logp->c_lsn.file,
- (u_long)logp->c_lsn.offset);
+ (u_long)lsnp->file, (u_long)lsnp->offset);
ret = EINVAL;
goto out;
}
ret = __db_txnlist_close(info,
argp->fileid, dbe->count);
if ((dbp = TAILQ_FIRST(&dbe->dblist)) != NULL)
- (void)log_unregister(dbenv, dbp);
+ (void)dbenv->log_unregister(dbenv, dbp);
do_rem = 1;
}
MUTEX_THREAD_UNLOCK(dbenv, logp->mutexp);
* closed and has therefore not been reopened yet. If
* so, we need to try to open it.
*/
- ret = __log_open_file(dbenv, logp, argp);
+ ret = __log_open_file(dbenv, logp, argp, 0);
if (ret == ENOENT || ret == EINVAL) {
if (argp->name.size != 0 && (ret =
__db_txnlist_delete(dbenv, info,
* non-zero on error.
*/
static int
-__log_open_file(dbenv, lp, argp)
+__log_open_file(dbenv, lp, argp, flags)
DB_ENV *dbenv;
DB_LOG *lp;
__log_register_args *argp;
+ u_int32_t flags;
{
DB_ENTRY *dbe;
DB *dbp;
MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp);
if (0) {
-reopen: (void)log_unregister(dbp->dbenv, dbp);
+reopen: (void)dbenv->log_unregister(dbenv, dbp);
(void)__log_rem_logid(lp, dbp, argp->fileid);
dbp->close(dbp, 0);
}
return (__log_do_open(dbenv, lp,
argp->uid.data, argp->name.data,
- argp->ftype, argp->fileid, argp->meta_pgno));
+ argp->ftype, argp->fileid, argp->meta_pgno, flags));
}
/*
* Must be called when a metadata page changes.
*
* PUBLIC: int __log_reopen_file __P((DB_ENV *,
- * PUBLIC: char *, int32_t, u_int8_t *, db_pgno_t));
+ * PUBLIC: char *, int32_t, u_int8_t *, db_pgno_t, u_int32_t));
*
*/
int
-__log_reopen_file(dbenv, name, ndx, fileid, meta_pgno)
+__log_reopen_file(dbenv, name, ndx, fileid, meta_pgno, flags)
DB_ENV *dbenv;
char *name;
int32_t ndx;
u_int8_t *fileid;
db_pgno_t meta_pgno;
+ u_int32_t flags;
{
DB *dbp;
DB_LOG *logp;
if ((ret = __db_fileid_to_db(dbenv, &dbp, ndx, 0)) != 0)
goto out;
ftype = dbp->type;
- (void)log_unregister(dbenv, dbp);
+ (void)dbenv->log_unregister(dbenv, dbp);
(void)__log_rem_logid(logp, dbp, ndx);
(void)dbp->close(dbp, 0);
- ret = __log_do_open(dbenv, logp, fileid, name, ftype, ndx, meta_pgno);
+ ret = __log_do_open(dbenv,
+ logp, fileid, name, ftype, ndx, meta_pgno, flags);
if (tmp_name != NULL)
__os_free(dbenv, tmp_name, 0);
* is not protected by the thread mutex.
*/
static int
-__log_do_open(dbenv, lp, uid, name, ftype, ndx, meta_pgno)
+__log_do_open(dbenv, lp, uid, name, ftype, ndx, meta_pgno, flags)
DB_ENV *dbenv;
DB_LOG *lp;
u_int8_t *uid;
DBTYPE ftype;
int32_t ndx;
db_pgno_t meta_pgno;
+ u_int32_t flags;
{
DB *dbp;
int ret;
if (meta_pgno != PGNO_BASE_MD)
memcpy(dbp->fileid, uid, DB_FILE_ID_LEN);
dbp->type = ftype;
- if ((ret = __db_dbopen(dbp,
- name, DB_ODDFILESIZE, __db_omode("rw----"), meta_pgno)) == 0) {
+ if ((ret = __db_dbopen(dbp, name,
+ flags | DB_ODDFILESIZE, __db_omode("rw----"), meta_pgno)) == 0) {
/*
* Verify that we are opening the same file that we were
* referring to when we wrote this log record.
memset(zeroid, 0, DB_FILE_ID_LEN);
if (memcmp(dbp->fileid, zeroid, DB_FILE_ID_LEN) != 0)
goto not_right;
- memcpy(dbp->fileid, uid, DB_FILE_ID_LEN);
+skipopen: memcpy(dbp->fileid, uid, DB_FILE_ID_LEN);
}
- if (IS_RECOVERING(dbenv)) {
- (void)log_register(dbp->dbenv, dbp, name);
+ if (IS_RECOVERING(dbenv) || LF_ISSET(DB_APPLY_LOGREG)) {
+ /*
+ * If DB_APPLY_LOGREG is set, we want to register this
+ * log file with a specific fileid, but we don't want
+ * to log anything. Pass the flag down into
+ * the log_register code.
+ */
+ (void)__log_register_int(dbp->dbenv, dbp, name, flags);
(void)__log_add_logid(dbenv, lp, dbp, ndx);
}
return (0);
- }
+ } else if (ret == ENOENT && LF_ISSET(DB_APPLY_LOGREG))
+ goto skipopen;
not_right:
(void)dbp->close(dbp, 0);
*/
if ((ret = __log_do_open(dbenv, logp,
fname->ufid, name, fname->s_type,
- ndx, fname->meta_pgno)) != 0)
+ ndx, fname->meta_pgno, 0)) != 0)
return (ret);
*dbpp = TAILQ_FIRST(&logp->dbentry[ndx].dblist);
for (i = 0; i < logp->dbentry_cnt; i++) {
dbe = &logp->dbentry[i];
while ((dbp = TAILQ_FIRST(&dbe->dblist)) != NULL) {
- (void)log_unregister(dbenv, dbp);
+ (void)dbenv->log_unregister(dbenv, dbp);
TAILQ_REMOVE(&dbe->dblist, dbp, links);
(void)dbp->close(dbp, dbp->mpf == NULL ? DB_NOSYNC : 0);
}
MUTEX_THREAD_LOCK(logp->dbenv, logp->mutexp);
if (--logp->dbentry[ndx].refcount == 0) {
+ if (dbp == NULL &&
+ (xdbp = TAILQ_FIRST(&logp->dbentry[ndx].dblist)) != NULL)
+ (void)xdbp->close(xdbp, 0);
TAILQ_INIT(&logp->dbentry[ndx].dblist);
logp->dbentry[ndx].deleted = 0;
} else if (dbp != NULL)
#include "db_config.h"
#ifndef lint
-static const char revid[] = "Id: mp_fopen.c,v 11.54 2001/07/02 01:05:42 bostic Exp ";
+static const char revid[] = "Id: mp_fopen.c,v 11.60 2001/10/04 21:26:56 bostic Exp ";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <string.h>
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
-#endif
-
#include "db_int.h"
#include "db_shash.h"
#include "mp.h"
-#ifdef HAVE_RPC
-#include "rpc_client_ext.h"
-#endif
-
-static int __memp_mf_open __P((DB_MPOOL *, const char *,
- size_t, db_pgno_t, DB_MPOOL_FINFO *, u_int32_t, MPOOLFILE **));
+static int __memp_fclose __P((DB_MPOOLFILE *, u_int32_t));
+static int __memp_fopen __P((DB_MPOOLFILE *,
+ const char *, u_int32_t, int, size_t));
+static int __memp_mf_open __P((DB_MPOOLFILE *,
+ const char *, size_t, db_pgno_t, u_int32_t, MPOOLFILE **));
+static void __memp_last_pgno __P((DB_MPOOLFILE *, db_pgno_t *));
+static void __memp_refcnt __P((DB_MPOOLFILE *, db_pgno_t *));
+static int __memp_set_clear_len __P((DB_MPOOLFILE *, u_int32_t));
+static int __memp_set_fileid __P((DB_MPOOLFILE *, u_int8_t *));
+static int __memp_set_ftype __P((DB_MPOOLFILE *, int));
+static int __memp_set_lsn_offset __P((DB_MPOOLFILE *, int32_t));
+static int __memp_set_pgcookie __P((DB_MPOOLFILE *, DBT *));
+static void __memp_set_unlink __P((DB_MPOOLFILE *, int));
/*
* MEMP_FREMOVE --
F_SET(mfp, MP_DEADFILE); \
}
+/* Initialization methods cannot be called after open is called. */
+#define MPF_ILLEGAL_AFTER_OPEN(dbmfp, name) \
+ if (F_ISSET(dbmfp, MP_OPEN_CALLED)) \
+ return (__db_mi_open((dbmfp)->dbmp->dbenv, name, 1));
+
/*
- * memp_fopen --
- * Open a backing file for the memory pool.
+ * __memp_fcreate --
+ * Create a DB_MPOOLFILE handle.
*
- * EXTERN: int memp_fopen __P((DB_ENV *, const char *,
- * EXTERN: u_int32_t, int, size_t, DB_MPOOL_FINFO *, DB_MPOOLFILE **));
+ * PUBLIC: int __memp_fcreate __P((DB_ENV *, DB_MPOOLFILE **, u_int32_t));
*/
int
-memp_fopen(dbenv, path, flags, mode, pagesize, finfop, retp)
+__memp_fcreate(dbenv, retp, flags)
DB_ENV *dbenv;
- const char *path;
- u_int32_t flags;
- int mode;
- size_t pagesize;
- DB_MPOOL_FINFO *finfop;
DB_MPOOLFILE **retp;
+ u_int32_t flags;
{
DB_MPOOL *dbmp;
+ DB_MPOOLFILE *dbmfp;
int ret;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_memp_fopen(dbenv, path, flags,
- mode, pagesize, finfop, retp));
-#endif
-
PANIC_CHECK(dbenv);
ENV_REQUIRES_CONFIG(dbenv,
- dbenv->mp_handle, "memp_fopen", DB_INIT_MPOOL);
+ dbenv->mp_handle, "memp_fcreate", DB_INIT_MPOOL);
dbmp = dbenv->mp_handle;
/* Validate arguments. */
- if ((ret = __db_fchk(dbenv, "memp_fopen", flags,
- DB_CREATE |
- DB_NOMMAP | DB_ODDFILESIZE | DB_RDONLY | DB_TRUNCATE)) != 0)
+ if ((ret = __db_fchk(dbenv, "memp_fcreate", flags, 0)) != 0)
return (ret);
- /* Require a non-zero pagesize. */
- if (pagesize == 0 ||
- (finfop != NULL && finfop->clear_len > pagesize)) {
- __db_err(dbenv, "memp_fopen: illegal page size.");
- return (EINVAL);
+ /* Allocate and initialize the per-process structure. */
+ if ((ret = __os_calloc(dbenv, 1, sizeof(DB_MPOOLFILE), &dbmfp)) != 0)
+ return (ret);
+ if ((ret = __os_calloc(dbenv, 1, sizeof(DB_FH), &dbmfp->fhp)) != 0) {
+ __os_free(dbenv, dbmfp, sizeof(DB_MPOOLFILE));
+ return (ret);
}
- return (__memp_fopen(dbmp,
- NULL, path, flags, mode, pagesize, 1, finfop, retp));
+ /* Allocate and initialize a mutex if necessary. */
+ if (F_ISSET(dbenv, DB_ENV_THREAD)) {
+ if ((ret = __db_mutex_alloc(
+ dbenv, dbmp->reginfo, 0, &dbmfp->mutexp)) != 0)
+ return (ret);
+
+ if ((ret = __db_shmutex_init(dbenv, dbmfp->mutexp, 0,
+ MUTEX_THREAD, dbmp->reginfo,
+ (REGMAINT *)R_ADDR(dbmp->reginfo,
+ ((MPOOL *)dbmp->reginfo->primary)->maint_off))) != 0) {
+ __db_mutex_free(dbenv, dbmp->reginfo, dbmfp->mutexp);
+ return (ret);
+ }
+ }
+
+ dbmfp->ref = 1;
+ dbmfp->lsn_offset = -1;
+ dbmfp->dbmp = dbmp;
+
+ dbmfp->close = __memp_fclose;
+ dbmfp->get = __memp_fget;
+ dbmfp->last_pgno = __memp_last_pgno;
+ dbmfp->open = __memp_fopen;
+ dbmfp->put = __memp_fput;
+ dbmfp->refcnt = __memp_refcnt;
+ dbmfp->set = __memp_fset;
+ dbmfp->set_clear_len = __memp_set_clear_len;
+ dbmfp->set_fileid = __memp_set_fileid;
+ dbmfp->set_ftype = __memp_set_ftype;
+ dbmfp->set_lsn_offset = __memp_set_lsn_offset;
+ dbmfp->set_pgcookie = __memp_set_pgcookie;
+ dbmfp->set_unlink = __memp_set_unlink;
+ dbmfp->sync = __memp_fsync;
+
+ /* Add the file to the environment's list of files. */
+ MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
+ TAILQ_INSERT_TAIL(&dbmp->dbmfq, dbmfp, q);
+ MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
+
+ *retp = dbmfp;
+ return (0);
}
/*
- * __memp_set_unlink -- set unlink on last close flag.
- *
- * PUBLIC: void __memp_set_unlink __P((DB_MPOOLFILE *));
+ * __memp_set_clear_len --
+ * Set the clear length.
*/
-void
-__memp_set_unlink(dbmpf)
- DB_MPOOLFILE *dbmpf;
+static int
+__memp_set_clear_len(dbmfp, clear_len)
+ DB_MPOOLFILE *dbmfp;
+ u_int32_t clear_len;
{
- DB_MPOOL *dbmp;
- dbmp = dbmpf->dbmp;
+ MPF_ILLEGAL_AFTER_OPEN(dbmfp, "set_clear_len");
- R_LOCK(dbmp->dbenv, dbmp->reginfo);
- F_SET(dbmpf->mfp, MP_UNLINK);
- R_UNLOCK(dbmp->dbenv, dbmp->reginfo);
+ dbmfp->clear_len = clear_len;
+ return (0);
}
/*
- * __memp_clear_unlink -- clear unlink on last close flag.
- *
- * PUBLIC: void __memp_clear_unlink __P((DB_MPOOLFILE *));
+ * __memp_set_fileid --
+ * Set the file ID.
*/
-void
-__memp_clear_unlink(dbmpf)
- DB_MPOOLFILE *dbmpf;
+static int
+__memp_set_fileid(dbmfp, fileid)
+ DB_MPOOLFILE *dbmfp;
+ u_int8_t *fileid;
{
- DB_MPOOL *dbmp;
- dbmp = dbmpf->dbmp;
+ MPF_ILLEGAL_AFTER_OPEN(dbmfp, "set_fileid");
- /*
- * This bit is protected in the queue code because the metapage
- * is locked so we can avoid geting the region lock.
- * If this gets used from other than the queue code, we cannot.
- */
- if (!F_ISSET(dbmpf->mfp, MP_UNLINK))
- return;
- R_LOCK(dbmp->dbenv, dbmp->reginfo);
- F_CLR(dbmpf->mfp, MP_UNLINK);
- R_UNLOCK(dbmp->dbenv, dbmp->reginfo);
+ dbmfp->fileid = fileid;
+ return (0);
}
/*
- * __memp_refcount -- return the current refcount
- *
- * PUBLIC: void __memp_refcount __P((DB_MPOOLFILE *, db_pgno_t *));
+ * __memp_set_ftype --
+ * Set the file type (as registered).
*/
-void
-__memp_refcount(dbmpf, cntp)
- DB_MPOOLFILE *dbmpf;
- db_pgno_t *cntp;
+static int
+__memp_set_ftype(dbmfp, ftype)
+ DB_MPOOLFILE *dbmfp;
+ int ftype;
{
- *cntp = dbmpf->mfp->mpf_cnt;
+ MPF_ILLEGAL_AFTER_OPEN(dbmfp, "set_ftype");
+
+ dbmfp->ftype = ftype;
+ return (0);
+}
+
+/*
+ * __memp_set_lsn_offset --
+ * Set the page's LSN offset.
+ */
+static int
+__memp_set_lsn_offset(dbmfp, lsn_offset)
+ DB_MPOOLFILE *dbmfp;
+ int32_t lsn_offset;
+{
+ MPF_ILLEGAL_AFTER_OPEN(dbmfp, "set_lsn_offset");
+
+ dbmfp->lsn_offset = lsn_offset;
+ return (0);
+}
+
+/*
+ * __memp_set_pgcookie --
+ * Set the pgin/pgout cookie.
+ */
+static int
+__memp_set_pgcookie(dbmfp, pgcookie)
+ DB_MPOOLFILE *dbmfp;
+ DBT *pgcookie;
+{
+ MPF_ILLEGAL_AFTER_OPEN(dbmfp, "set_pgcookie");
+
+ dbmfp->pgcookie = pgcookie;
+ return (0);
}
/*
/*
* __memp_fopen --
+ * Open a backing file for the memory pool.
+ */
+static int
+__memp_fopen(dbmfp, path, flags, mode, pagesize)
+ DB_MPOOLFILE *dbmfp;
+ const char *path;
+ u_int32_t flags;
+ int mode;
+ size_t pagesize;
+{
+ DB_ENV *dbenv;
+ DB_MPOOL *dbmp;
+ int ret;
+
+ dbmp = dbmfp->dbmp;
+ dbenv = dbmp->dbenv;
+
+ PANIC_CHECK(dbenv);
+
+ /* Validate arguments. */
+ if ((ret = __db_fchk(dbenv, "memp_fopen", flags,
+ DB_CREATE | DB_EXTENT |
+ DB_NOMMAP | DB_ODDFILESIZE | DB_RDONLY | DB_TRUNCATE)) != 0)
+ return (ret);
+
+ /*
+ * Require a non-zero, power-of-two pagesize, smaller than the
+ * clear length.
+ */
+ if (pagesize == 0 || !POWER_OF_TWO(pagesize)) {
+ __db_err(dbenv,
+ "memp_fopen: page sizes must be a power-of-2");
+ return (EINVAL);
+ }
+ if (dbmfp->clear_len > pagesize) {
+ __db_err(dbenv,
+ "memp_fopen: clear length larger than page size.");
+ return (EINVAL);
+ }
+
+ /* Read-only checks, and local flag. */
+ if (LF_ISSET(DB_RDONLY)) {
+ if (path == NULL) {
+ __db_err(dbenv,
+ "memp_fopen: temporary files can't be readonly");
+ return (EINVAL);
+ }
+ F_SET(dbmfp, MP_READONLY);
+ }
+
+ if ((ret = __memp_fopen_int(
+ dbmfp, NULL, path, flags, mode, pagesize, 1)) != 0)
+ return (ret);
+
+ F_SET(dbmfp, MP_OPEN_CALLED);
+ return (0);
+}
+
+/*
+ * __memp_fopen_int --
* Open a backing file for the memory pool; internal version.
*
- * PUBLIC: int __memp_fopen __P((DB_MPOOL *, MPOOLFILE *, const char *,
- * PUBLIC: u_int32_t, int, size_t, int, DB_MPOOL_FINFO *, DB_MPOOLFILE **));
+ * PUBLIC: int __memp_fopen_int __P((DB_MPOOLFILE *,
+ * PUBLIC: MPOOLFILE *, const char *, u_int32_t, int, size_t, int));
*/
int
-__memp_fopen(dbmp, mfp, path, flags, mode, pagesize, needlock, finfop, retp)
- DB_MPOOL *dbmp;
+__memp_fopen_int(dbmfp, mfp, path, flags, mode, pagesize, needlock)
+ DB_MPOOLFILE *dbmfp;
MPOOLFILE *mfp;
const char *path;
u_int32_t flags;
int mode, needlock;
size_t pagesize;
- DB_MPOOL_FINFO *finfop;
- DB_MPOOLFILE **retp;
{
DB_ENV *dbenv;
- DB_MPOOLFILE *dbmfp;
- DB_MPOOL_FINFO finfo;
+ DB_MPOOL *dbmp;
db_pgno_t last_pgno;
size_t maxmap;
u_int32_t mbytes, bytes, oflags;
u_int8_t idbuf[DB_FILE_ID_LEN];
char *rpath, *rpath_orig;
+ dbmp = dbmfp->dbmp;
dbenv = dbmp->dbenv;
ret = 0;
rpath = NULL;
- /*
- * If mfp is provided, we take the DB_MPOOL_FINFO information from
- * the mfp. We don't bother initializing everything, because some
- * of them are expensive to acquire. If no mfp is provided and the
- * finfop argument is NULL, we default the values.
- */
- if (finfop == NULL) {
- memset(&finfo, 0, sizeof(finfo));
- if (mfp != NULL) {
- finfo.ftype = mfp->ftype;
- finfo.pgcookie = NULL;
- finfo.fileid = NULL;
- finfo.lsn_offset = mfp->lsn_off;
- finfo.clear_len = mfp->clear_len;
- } else {
- finfo.ftype = 0;
- finfo.pgcookie = NULL;
- finfo.fileid = NULL;
- finfo.lsn_offset = -1;
- finfo.clear_len = 0;
- }
- finfop = &finfo;
- }
-
- /* Allocate and initialize the per-process structure. */
- if ((ret = __os_calloc(dbenv, 1, sizeof(DB_MPOOLFILE), &dbmfp)) != 0)
- return (ret);
- dbmfp->dbmp = dbmp;
- dbmfp->ref = 1;
- if (LF_ISSET(DB_RDONLY))
- F_SET(dbmfp, MP_READONLY);
-
- if (path == NULL) {
- if (LF_ISSET(DB_RDONLY)) {
- __db_err(dbenv,
- "memp_fopen: temporary files can't be readonly");
- ret = EINVAL;
- goto err;
- }
+ if (path == NULL)
last_pgno = 0;
- } else {
+ else {
/* Get the real name for this file and open it. */
if ((ret = __db_appname(dbenv,
DB_APP_DATA, NULL, path, 0, NULL, &rpath)) != 0)
if (LF_ISSET(DB_RDONLY))
oflags |= DB_OSO_RDONLY;
if ((ret =
- __os_open(dbenv, rpath, oflags, mode, &dbmfp->fh)) != 0) {
+ __os_open(dbenv, rpath, oflags, mode, dbmfp->fhp)) != 0) {
if (!LF_ISSET(DB_EXTENT))
__db_err(dbenv,
"%s: %s", rpath, db_strerror(ret));
* offsets are 64-bits, and they pay us a lot of money.
*/
if ((ret = __os_ioinfo(dbenv, rpath,
- &dbmfp->fh, &mbytes, &bytes, NULL)) != 0) {
+ dbmfp->fhp, &mbytes, &bytes, NULL)) != 0) {
__db_err(dbenv, "%s: %s", rpath, db_strerror(ret));
goto err;
}
/*
* If we're doing a verify, we might have to cope with
* a truncated file; if the file size is not a multiple
- * of the page size, round down to a page--we'll
+ * of the page size, round down to a page -- we'll
* take care of the partial page outside the memp system.
*/
-
- /* Page sizes have to be a power-of-two, ignore mbytes. */
if (bytes % pagesize != 0) {
if (LF_ISSET(DB_ODDFILESIZE))
/*
- * If we're doing a verify, we might
- * have to cope with a truncated file;
- * round down, we'll worry about the partial
- * page outside the memp system.
+ * During verify or recovery, we might have
+ * to cope with a truncated file; round down,
+ * we'll worry about the partial page outside
+ * the memp system.
*/
bytes -= (bytes % pagesize);
else {
__db_err(dbenv,
- "%s: file size not a multiple of the pagesize",
+ "%s: file size not a multiple of the pagesize",
rpath);
ret = EINVAL;
goto err;
* don't use timestamps, otherwise there'd be no chance of any
* other process joining the party.
*/
- if (finfop->fileid == NULL) {
+ if (dbmfp->fileid == NULL) {
if ((ret = __os_fileid(dbenv, rpath, 0, idbuf)) != 0)
goto err;
- finfop->fileid = idbuf;
+ dbmfp->fileid = idbuf;
}
}
R_LOCK(dbenv, dbmp->reginfo);
if (mfp == NULL)
ret = __memp_mf_open(
- dbmp, path, pagesize, last_pgno, finfop, flags, &mfp);
+ dbmfp, path, pagesize, last_pgno, flags, &mfp);
else {
++mfp->mpf_cnt;
ret = 0;
}
+ dbmfp->mfp = mfp;
if (needlock)
R_UNLOCK(dbenv, dbmp->reginfo);
if (ret != 0)
goto err;
- if (F_ISSET(dbenv, DB_ENV_THREAD)) {
- if ((ret = __db_mutex_alloc(
- dbenv, dbmp->reginfo, 0, &dbmfp->mutexp)) != 0)
- goto err;
-
- if ((ret = __db_shmutex_init(dbenv, dbmfp->mutexp, 0,
- MUTEX_THREAD, dbmp->reginfo,
- (REGMAINT *)R_ADDR(dbmp->reginfo,
- ((MPOOL *)dbmp->reginfo->primary)->maint_off))) != 0)
- goto err;
-
- /* XXX: KEITH: CLOSE THE FILE ON FAILURE? */
- }
-
- dbmfp->mfp = mfp;
-
/*
* If a file:
* + is read-only
F_CLR(mfp, MP_CAN_MMAP);
if (path == NULL)
F_CLR(mfp, MP_CAN_MMAP);
- if (finfop->ftype != 0)
+ if (dbmfp->ftype != 0)
F_CLR(mfp, MP_CAN_MMAP);
if (LF_ISSET(DB_NOMMAP) || F_ISSET(dbenv, DB_ENV_NOMMAP))
F_CLR(mfp, MP_CAN_MMAP);
if (F_ISSET(mfp, MP_CAN_MMAP)) {
dbmfp->len = (size_t)mbytes * MEGABYTE + bytes;
if (__os_mapfile(dbenv, rpath,
- &dbmfp->fh, dbmfp->len, 1, &dbmfp->addr) != 0) {
+ dbmfp->fhp, dbmfp->len, 1, &dbmfp->addr) != 0) {
dbmfp->addr = NULL;
F_CLR(mfp, MP_CAN_MMAP);
}
if (rpath != NULL)
__os_freestr(dbenv, rpath_orig);
- MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
- TAILQ_INSERT_TAIL(&dbmp->dbmfq, dbmfp, q);
- MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
-
- *retp = dbmfp;
return (0);
-err: /*
- * Note that we do not have to free the thread mutex, because we
- * never get to here after we have successfully allocated it.
- */
- if (rpath != NULL)
+err: if (rpath != NULL)
__os_freestr(dbenv, rpath_orig);
- if (F_ISSET(&dbmfp->fh, DB_FH_VALID))
- (void)__os_closehandle(&dbmfp->fh);
- if (dbmfp != NULL) {
- if (dbmfp->mutexp != NULL)
- __db_mutex_free(dbenv, dbmp->reginfo, dbmfp->mutexp);
- __os_free(dbenv, dbmfp, sizeof(DB_MPOOLFILE));
- }
+ if (F_ISSET(dbmfp->fhp, DB_FH_VALID))
+ (void)__os_closehandle(dbmfp->fhp);
return (ret);
}
* Open an MPOOLFILE.
*/
static int
-__memp_mf_open(dbmp, path, pagesize, last_pgno, finfop, flags, retp)
- DB_MPOOL *dbmp;
+__memp_mf_open(dbmfp, path, pagesize, last_pgno, flags, retp)
+ DB_MPOOLFILE *dbmfp;
const char *path;
size_t pagesize;
db_pgno_t last_pgno;
- DB_MPOOL_FINFO *finfop;
u_int32_t flags;
MPOOLFILE **retp;
{
+ DB_MPOOL *dbmp;
MPOOL *mp;
MPOOLFILE *mfp;
int ret;
#define ISTEMPORARY (path == NULL)
+ dbmp = dbmfp->dbmp;
+
/*
* If not creating a temporary file, walk the list of MPOOLFILE's,
* looking for a matching file. Files backed by temporary files
mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
if (F_ISSET(mfp, MP_DEADFILE | MP_TEMP))
continue;
- if (memcmp(finfop->fileid, R_ADDR(dbmp->reginfo,
+ if (memcmp(dbmfp->fileid, R_ADDR(dbmp->reginfo,
mfp->fileid_off), DB_FILE_ID_LEN) == 0) {
if (LF_ISSET(DB_TRUNCATE)) {
MEMP_FREMOVE(mfp);
continue;
}
- if (finfop->clear_len != mfp->clear_len ||
+ if (dbmfp->clear_len != mfp->clear_len ||
pagesize != mfp->stat.st_pagesize) {
__db_err(dbmp->dbenv,
"%s: page size or clear length changed",
* an application created a hash subdatabase
* in a database that was previously all btree.
*/
- if (finfop->ftype != 0)
- mfp->ftype = finfop->ftype;
+ if (dbmfp->ftype != 0)
+ mfp->ftype = dbmfp->ftype;
++mfp->mpf_cnt;
/* Initialize the structure. */
memset(mfp, 0, sizeof(MPOOLFILE));
mfp->mpf_cnt = 1;
- mfp->ftype = finfop->ftype;
- mfp->lsn_off = finfop->lsn_offset;
- mfp->clear_len = finfop->clear_len;
+ mfp->ftype = dbmfp->ftype;
+ mfp->lsn_off = dbmfp->lsn_offset;
+ mfp->clear_len = dbmfp->clear_len;
/*
* If the user specifies DB_MPOOL_LAST or DB_MPOOL_NEW on a memp_fget,
if ((ret = __memp_alloc(dbmp, dbmp->reginfo,
NULL, DB_FILE_ID_LEN, &mfp->fileid_off, &p)) != 0)
goto err;
- memcpy(p, finfop->fileid, DB_FILE_ID_LEN);
+ memcpy(p, dbmfp->fileid, DB_FILE_ID_LEN);
F_SET(mfp, MP_CAN_MMAP);
if (LF_ISSET(DB_EXTENT))
}
/* Copy the page cookie into shared memory. */
- if (finfop->pgcookie == NULL || finfop->pgcookie->size == 0) {
+ if (dbmfp->pgcookie == NULL || dbmfp->pgcookie->size == 0) {
mfp->pgcookie_len = 0;
mfp->pgcookie_off = 0;
} else {
if ((ret = __memp_alloc(dbmp, dbmp->reginfo,
- NULL, finfop->pgcookie->size, &mfp->pgcookie_off, &p)) != 0)
+ NULL, dbmfp->pgcookie->size, &mfp->pgcookie_off, &p)) != 0)
goto err;
- memcpy(p, finfop->pgcookie->data, finfop->pgcookie->size);
- mfp->pgcookie_len = finfop->pgcookie->size;
+ memcpy(p, dbmfp->pgcookie->data, dbmfp->pgcookie->size);
+ mfp->pgcookie_len = dbmfp->pgcookie->size;
}
/* Prepend the MPOOLFILE to the list of MPOOLFILE's. */
}
/*
+ * __memp_last_pgno --
+ * Return the page number of the last page in the file.
+ *
+ * XXX
+ * Undocumented interface: DB private.
+ */
+static void
+__memp_last_pgno(dbmfp, pgnoaddr)
+ DB_MPOOLFILE *dbmfp;
+ db_pgno_t *pgnoaddr;
+{
+ DB_ENV *dbenv;
+ DB_MPOOL *dbmp;
+
+ dbmp = dbmfp->dbmp;
+ dbenv = dbmp->dbenv;
+
+ R_LOCK(dbenv, dbmp->reginfo);
+ *pgnoaddr = dbmfp->mfp->last_pgno;
+ R_UNLOCK(dbenv, dbmp->reginfo);
+}
+
+/*
+ * __memp_refcnt --
+ * Return the current reference count.
+ *
+ * XXX
+ * Undocumented interface: DB private.
+ */
+static void
+__memp_refcnt(dbmfp, cntp)
+ DB_MPOOLFILE *dbmfp;
+ db_pgno_t *cntp;
+{
+ DB_ENV *dbenv;
+ DB_MPOOL *dbmp;
+
+ dbmp = dbmfp->dbmp;
+ dbenv = dbmp->dbenv;
+
+ R_LOCK(dbenv, dbmp->reginfo);
+ *cntp = dbmfp->mfp->mpf_cnt;
+ R_UNLOCK(dbenv, dbmp->reginfo);
+}
+
+/*
+ * __memp_set_unlink --
+ * Set unlink on last close flag.
+ *
+ * XXX
+ * Undocumented interface: DB private.
+ */
+static void
+__memp_set_unlink(dbmpf, set)
+ DB_MPOOLFILE *dbmpf;
+ int set;
+{
+ DB_MPOOL *dbmp;
+
+ dbmp = dbmpf->dbmp;
+
+ if (set) {
+ R_LOCK(dbmp->dbenv, dbmp->reginfo);
+ F_SET(dbmpf->mfp, MP_UNLINK);
+ R_UNLOCK(dbmp->dbenv, dbmp->reginfo);
+ } else {
+ /*
+ * This bit is protected in the queue code because the metapage
+ * is locked, so we can avoid getting the region lock. If this
+ * gets used from other than the queue code, we cannot.
+ */
+ if (F_ISSET(dbmpf->mfp, MP_UNLINK)) {
+ R_LOCK(dbmp->dbenv, dbmp->reginfo);
+ F_CLR(dbmpf->mfp, MP_UNLINK);
+ R_UNLOCK(dbmp->dbenv, dbmp->reginfo);
+ }
+ }
+}
+
+/*
* memp_fclose --
* Close a backing file for the memory pool.
- *
- * EXTERN: int memp_fclose __P((DB_MPOOLFILE *));
*/
-int
-memp_fclose(dbmfp)
+static int
+__memp_fclose(dbmfp, flags)
DB_MPOOLFILE *dbmfp;
+ u_int32_t flags;
{
DB_ENV *dbenv;
+ int ret;
dbenv = dbmfp->dbmp->dbenv;
PANIC_CHECK(dbenv);
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_memp_fclose(dbmfp));
-#endif
+ /*
+ * XXX
+ * DB_MPOOL_DISCARD: Undocumented flag: DB private.
+ */
+ if (flags != 0 && (ret = __db_fchk(dbenv,
+ "DB_MPOOLFILE->close", flags, DB_MPOOL_DISCARD)) != 0)
+ return (ret);
- return (__memp_fclose(dbmfp, 1));
+ return (__memp_fclose_int(dbmfp, flags, 1));
}
/*
- * PUBLIC: int __memp_fclose __P((DB_MPOOLFILE *, int));
+ * __memp_fclose_int --
+ * Internal version of __memp_fclose.
+ *
+ * PUBLIC: int __memp_fclose_int __P((DB_MPOOLFILE *, u_int32_t, int));
*/
int
-__memp_fclose(dbmfp, needlock)
+__memp_fclose_int(dbmfp, flags, needlock)
DB_MPOOLFILE *dbmfp;
+ u_int32_t flags;
int needlock;
{
DB_ENV *dbenv;
__db_err(dbenv, "%s: %s", __memp_fn(dbmfp), db_strerror(ret));
/* Close the file; temporary files may not yet have been created. */
- if (F_ISSET(&dbmfp->fh, DB_FH_VALID) &&
- (t_ret = __os_closehandle(&dbmfp->fh)) != 0) {
+ if (F_ISSET(dbmfp->fhp, DB_FH_VALID) &&
+ (t_ret = __os_closehandle(dbmfp->fhp)) != 0) {
__db_err(dbenv, "%s: %s", __memp_fn(dbmfp), db_strerror(t_ret));
if (ret == 0)
ret = t_ret;
* MPOOLFILE as dead so that even the dirty ones just get discarded
* when we try to flush them.
*/
+ if ((mfp = dbmfp->mfp) == NULL)
+ goto done;
if (needlock)
R_LOCK(dbenv, dbmp->reginfo);
- mfp = dbmfp->mfp;
- if (--mfp->mpf_cnt == 0) {
- if (F_ISSET(mfp, MP_TEMP | MP_UNLINK))
+ if (--mfp->mpf_cnt == 0 || LF_ISSET(DB_MPOOL_DISCARD)) {
+ if (LF_ISSET(DB_MPOOL_DISCARD) ||
+ F_ISSET(mfp, MP_TEMP | MP_UNLINK))
MEMP_FREMOVE(mfp);
if (F_ISSET(mfp, MP_UNLINK)) {
if ((t_ret = __db_appname(dbmp->dbenv,
mfp->path_off), 0, NULL, &rpath)) != 0 && ret == 0)
ret = t_ret;
if (t_ret == 0 && (t_ret =
- __os_unlink(dbmp->dbenv, rpath) != 0 && ret == 0))
+ __os_unlink(dbmp->dbenv, rpath) != 0) && ret == 0)
ret = t_ret;
__os_free(dbenv, rpath, 0);
}
if (needlock)
R_UNLOCK(dbenv, dbmp->reginfo);
- /* Discard the DB_MPOOLFILE structure. */
+done: /* Discard the DB_MPOOLFILE structure. */
+ __os_free(dbenv, dbmfp->fhp, sizeof(DB_FH));
__os_free(dbenv, dbmfp, sizeof(DB_MPOOLFILE));
return (ret);
}
/*
- * __memp_fremove --
- * Remove an underlying file from the system.
- *
- * PUBLIC: int __memp_fremove __P((DB_MPOOLFILE *));
- */
-int
-__memp_fremove(dbmfp)
- DB_MPOOLFILE *dbmfp;
-{
- DB_ENV *dbenv;
- DB_MPOOL *dbmp;
- MPOOLFILE *mfp;
-
- dbmp = dbmfp->dbmp;
- dbenv = dbmp->dbenv;
- mfp = dbmfp->mfp;
-
- PANIC_CHECK(dbenv);
-
- R_LOCK(dbenv, dbmp->reginfo);
-
- MEMP_FREMOVE(mfp);
-
- R_UNLOCK(dbenv, dbmp->reginfo);
-
- return (0);
-}
-
-/*
* __memp_fn --
* On errors we print whatever is available as the file name.
*
#include "db_config.h"
#ifndef lint
-static const char revid[] = "Id: os_map.c,v 11.34 2001/04/10 20:44:34 bostic Exp ";
+static const char revid[] = "Id: os_map.c,v 11.37 2001/10/04 21:27:57 bostic Exp ";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
*/
if (ret == 0 && F_ISSET(infop, REGION_CREATE))
ret = __os_finit(dbenv,
- &fh, rp->size, DB_GLOBAL(db_region_init));
+ &fh, rp->size, F_ISSET(dbenv, DB_ENV_REGION_INIT) ? 1 : 0);
/* Map the file in. */
if (ret == 0)
#ifdef HAVE_MMAP
#ifdef HAVE_MUNLOCK
if (F_ISSET(dbenv, DB_ENV_LOCKDOWN))
- (void)munlock(addr, len);
+ while (munlock(addr, len) != 0 && __os_get_errno() == EINTR)
+ ;
#else
COMPQUIET(dbenv, NULL);
#endif
- return (munmap(addr, len) ? __os_get_errno() : 0);
+ {
+ int ret;
+
+ while ((ret = munmap(addr, len)) != 0 &&
+ __os_get_errno() == EINTR)
+ ;
+ return (ret ? __os_get_errno() : 0);
+ }
#else
COMPQUIET(dbenv, NULL);
# Copyright (c) 2001
# Sleepycat Software. All rights reserved.
#
-# Id: bigfile001.tcl,v 11.3 2001/05/22 16:20:40 krinsky Exp
+# Id: bigfile001.tcl,v 11.5 2001/08/03 18:02:53 sandstro Exp
#
-# Big file test.
-# Create a database greater than 4 GB in size. Close, verify. Grow
-# the database somewhat. Close, reverify. Lather, rinse, repeat.
-# Since it will not work on all systems, this test is not run by default.
+# TEST bigfile001
+# TEST Create a database greater than 4 GB in size. Close, verify.
+# Grow the database somewhat. Close, reverify. Lather, rinse,
+# repeat. Since it will not work on all systems, this test is
+# not run by default.
proc bigfile001 { method \
{ itemsize 4096 } { nitems 1048576 } { growby 5000 } { growtms 2 } args } {
source ./include.tcl
# factor, and page size doesn't matter much. Use a 50MB
# cache; that should be manageable, and will help
# performance.
- set dbname TESTDIR/big.db
+ set dbname $testdir/big.db
set db [eval {berkdb_open -create} {-pagesize 65536 \
-cachesize {0 50000000 0}} $omethod $args $dbname]
# Copyright (c) 2001
# Sleepycat Software. All rights reserved.
#
-# Id: bigfile002.tcl,v 11.2 2001/07/02 01:08:45 bostic Exp
+# Id: bigfile002.tcl,v 11.4 2001/08/03 18:31:15 sandstro Exp
#
-# Big file test #2.
-# This one should be faster and not require so much disk space, although it
-# doesn't test as extensively.
-# Create an mpool file with 1K pages. Dirty page 6000000. Sync.
+# TEST bigfile002
+# TEST This one should be faster and not require so much disk space,
+# although it doesn't test as extensively. Create an mpool file
+# with 1K pages. Dirty page 6000000. Sync.
proc bigfile002 { args } {
source ./include.tcl
env_cleanup $testdir
# Create env.
- set env [berkdb env -create -home TESTDIR]
+ set env [berkdb env -create -home $testdir]
error_check_good valid_env [is_valid_env $env] TRUE
# Create the file.
# Copyright (c) 1999-2001
# Sleepycat Software. All rights reserved.
#
-# Id: env009.tcl,v 11.1 2001/05/23 16:47:32 sue Exp
+# Id: env009.tcl,v 11.2 2001/08/03 16:39:24 bostic Exp
#
-# Env Test 9
-# Test calls to all the various stat functions.
-# We have several sprinkled throughout the test suite, but
-# this will ensure that we run all of them at least once.
+# TEST env009
+# TEST Test calls to all the various stat functions. We have several
+# TEST sprinkled throughout the test suite, but this will ensure that
+# TEST we run all of them at least once.
proc env009 { } {
source ./include.tcl
# Copyright (c) 1996-2003
# Sleepycat Software. All rights reserved.
#
-# Id: rpc003.tcl,v 11.4 2001/07/02 01:08:46 bostic Exp
+# Id: rpc003.tcl,v 11.5 2001/08/29 19:07:42 sue Exp
#
# Test RPC and secondary indices.
proc rpc003 { } {
[eval {$pdb associate} "" $sdb] 0
lappend sdbs $sdb
}
- check_secondaries $pdb $sdbs $nentries keys data "Rpc003.f"
+ check_secondaries $pdb $sdbs $nentries keys data "Rpc003.h"
foreach sdb $sdbs {
error_check_good secondary_close [$sdb close] 0
# Copyright (c) 2000-2001
# Sleepycat Software. All rights reserved.
#
-# Id: test095.tcl,v 11.6 2001/05/21 17:09:10 krinsky Exp
-#
-# DB Test 95 {access method}
-# Bulk get test.
+# Id: test095.tcl,v 11.13 2001/10/11 18:08:40 sandstro Exp
#
+# TEST test095
+# TEST Bulk get test. [#2934]
proc test095 { method {nsets 1000} {noverflows 25} {tnum 95} args } {
source ./include.tcl
set args [convert_args $method $args]
t95_cgettest $db $tnum d [expr 100] 1
t95_cgettest $db $tnum e [expr 10 * 8192] 0
- set m [expr 4000 * $noverflows]
- puts "\tTest0$tnum.f: Growing\
- database with $noverflows overflow sets (max item size $m)"
+ # Run invalid flag combination tests
+ # Sync and reopen test file so errors won't be sent to stderr
+ error_check_good db_sync [$db sync] 0
+ set noerrdb [eval berkdb_open_noerr $dargs $testfile]
+ t95_flagtest $noerrdb $tnum f [expr 8192]
+ t95_cflagtest $noerrdb $tnum g [expr 100]
+ error_check_good noerrdb_close [$noerrdb close] 0
+
+ # Set up for overflow tests
+ set max [expr 4000 * $noverflows]
+ puts "\tTest0$tnum.h: Growing\
+ database with $noverflows overflow sets (max item size $max)"
t95_populate $db $did $noverflows 4000
# Run overflow get tests.
- t95_gettest $db $tnum g [expr 10 * 8192] 1
- t95_gettest $db $tnum h [expr $m * 2] 1
- t95_gettest $db $tnum i [expr $m * $noverflows * 2] 0
+ t95_gettest $db $tnum i [expr 10 * 8192] 1
+ t95_gettest $db $tnum j [expr $max * 2] 1
+ t95_gettest $db $tnum k [expr $max * $noverflows * 2] 0
- # Run cursor get tests.
- t95_cgettest $db $tnum j [expr 10 * 8192] 1
- t95_cgettest $db $tnum k [expr $m * 2] 0
+ # Run overflow cursor get tests.
+ t95_cgettest $db $tnum l [expr 10 * 8192] 1
+ t95_cgettest $db $tnum m [expr $max * 2] 0
error_check_good db_close [$db close] 0
close $did
}
-
}
proc t95_gettest { db tnum letter bufsize expectfail } {
proc t95_cgettest { db tnum letter bufsize expectfail } {
t95_gettest_body $db $tnum $letter $bufsize $expectfail 1
}
+proc t95_flagtest { db tnum letter bufsize } {
+ t95_flagtest_body $db $tnum $letter $bufsize 0
+}
+proc t95_cflagtest { db tnum letter bufsize } {
+ t95_flagtest_body $db $tnum $letter $bufsize 1
+}
+# Basic get test
proc t95_gettest_body { db tnum letter bufsize expectfail usecursor } {
global errorCode
}
}
+# Test of invalid flag combinations for -multi
+proc t95_flagtest_body { db tnum letter bufsize usecursor } {
+ global errorCode
+
+ if { $usecursor == 0 } {
+ set action "db get -multi "
+ } else {
+ set action "dbc get -multi "
+ }
+ puts "\tTest0$tnum.$letter: $action with invalid flag combinations"
+
+ # Cursor for $usecursor.
+ if { $usecursor != 0 } {
+ set getcurs [$db cursor]
+ error_check_good getcurs [is_valid_cursor $getcurs $db] TRUE
+ }
+
+ if { $usecursor == 0 } {
+ # Disallowed flags for basic -multi get
+ set badflags [list consume consume_wait {rmw some_key}]
+
+ foreach flag $badflags {
+ catch {eval $db get -multi $bufsize -$flag} ret
+ error_check_good \
+ db:get:multi:$flag [is_substr $errorCode EINVAL] 1
+ }
+ } else {
+ # Disallowed flags for cursor -multi get
+ set cbadflags [list last get_recno join_item \
+ {multi_key 1000} prev prevnodup]
+
+ set dbc [$db cursor]
+ $dbc get -first
+ foreach flag $cbadflags {
+ catch {eval $dbc get -multi $bufsize -$flag} ret
+ error_check_good dbc:get:multi:$flag \
+ [is_substr $errorCode EINVAL] 1
+ }
+ error_check_good dbc_close [$dbc close] 0
+ }
+ if { $usecursor != 0 } {
+ error_check_good getcurs_close [$getcurs close] 0
+ }
+ puts "\t\tTest0$tnum.$letter completed"
+}
+
# Verify that a passed-in list of key/data pairs all match the predicted
# structure (e.g. {{thing1 thing1.0}}, {{key2 key2.0} {key2 key2.1}}).
proc t95_verify { res multiple_keys } {
# Copyright (c) 1999-2001
# Sleepycat Software. All rights reserved.
#
-# Id: test096.tcl,v 11.8 2001/07/09 14:49:16 dda Exp
+# Id: test096.tcl,v 11.9 2001/08/03 16:39:49 bostic Exp
#
-# Access Method Test 96
-# Test of db->truncate method.
+# TEST test096
+# TEST Db->truncate test.
proc test096 { method {pagesize 512} {nentries 1000} {ndups 19} args} {
global fixed_len
source ./include.tcl