From 6a3779986983280ca9b793cc7710f94349e3ee08 Mon Sep 17 00:00:00 2001 From: prabatuty Date: Tue, 26 Aug 2008 09:53:43 +0000 Subject: [PATCH] Renamed server directory to storage directory in src --- configure | 1576 +++++++++----------------------- configure.in | 2 +- src/Makefile.am | 2 +- src/Makefile.in | 2 +- src/jdbc/Makefile.am | 2 +- src/jdbc/Makefile.in | 2 +- src/odbc/Makefile | 22 +- src/odbc/Makefile.am | 2 +- src/odbc/Makefile.in | 2 +- src/sql/Makefile.am | 4 +- src/sql/Makefile.in | 4 +- src/storage/AggTableImpl.cxx | 559 ++++++++++++ src/storage/BucketIter.cxx | 26 + src/storage/BucketList.cxx | 68 ++ src/storage/CatalogTables.cxx | 579 ++++++++++++ src/storage/Chunk.cxx | 703 ++++++++++++++ src/storage/ChunkIterator.cxx | 103 +++ src/storage/Condition.cxx | 62 ++ src/storage/Config.cxx | 366 ++++++++ src/storage/Connection.cxx | 97 ++ src/storage/DataType.cxx | 1717 +++++++++++++++++++++++++++++++++++ src/storage/Database.cxx | 486 ++++++++++ src/storage/DatabaseManagerImpl.cxx | 1120 +++++++++++++++++++++++ src/storage/Debug.cxx | 102 +++ src/storage/FieldList.cxx | 326 +++++++ src/storage/HashIndex.cxx | 447 +++++++++ src/storage/Index.cxx | 34 + src/storage/LockListIter.cxx | 29 + src/storage/LockManager.cxx | 675 ++++++++++++++ src/storage/Logger.cxx | 112 +++ src/{server => storage}/Makefile.am | 4 - src/{server => storage}/Makefile.in | 12 +- src/storage/Mutex.cxx | 212 +++++ src/storage/PageInfo.cxx | 36 + src/storage/PredicateImpl.cxx | 286 ++++++ src/storage/Process.cxx | 366 ++++++++ src/storage/SessionImpl.cxx | 283 ++++++ src/storage/TableDef.cxx | 107 +++ src/storage/TableImpl.cxx | 815 +++++++++++++++++ src/storage/Transaction.cxx | 274 ++++++ src/storage/TransactionManager.cxx | 229 +++++ src/storage/TupleIterator.cxx | 148 +++ src/storage/UserManagerImpl.cxx | 93 ++ src/storage/os.cxx | 256 ++++++ src/tools/Makefile.am | 20 +- src/tools/Makefile.in | 38 +- 46 files changed, 11201 insertions(+), 1209 deletions(-) create mode 100644 src/storage/AggTableImpl.cxx create mode 100644 src/storage/BucketIter.cxx create mode 100644 src/storage/BucketList.cxx create mode 100644 src/storage/CatalogTables.cxx create mode 100644 src/storage/Chunk.cxx create mode 100644 src/storage/ChunkIterator.cxx create mode 100644 src/storage/Condition.cxx create mode 100644 src/storage/Config.cxx create mode 100644 src/storage/Connection.cxx create mode 100644 src/storage/DataType.cxx create mode 100644 src/storage/Database.cxx create mode 100644 src/storage/DatabaseManagerImpl.cxx create mode 100644 src/storage/Debug.cxx create mode 100644 src/storage/FieldList.cxx create mode 100644 src/storage/HashIndex.cxx create mode 100644 src/storage/Index.cxx create mode 100644 src/storage/LockListIter.cxx create mode 100644 src/storage/LockManager.cxx create mode 100644 src/storage/Logger.cxx rename src/{server => storage}/Makefile.am (77%) rename src/{server => storage}/Makefile.in (97%) create mode 100644 src/storage/Mutex.cxx create mode 100644 src/storage/PageInfo.cxx create mode 100644 src/storage/PredicateImpl.cxx create mode 100644 src/storage/Process.cxx create mode 100644 src/storage/SessionImpl.cxx create mode 100644 src/storage/TableDef.cxx create mode 100644 src/storage/TableImpl.cxx create mode 100644 src/storage/Transaction.cxx create mode 100644 src/storage/TransactionManager.cxx create mode 100644 src/storage/TupleIterator.cxx create mode 100644 src/storage/UserManagerImpl.cxx create mode 100644 src/storage/os.cxx diff --git a/configure b/configure index e5803f56..5ad821a5 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.60. +# Generated by GNU Autoconf 2.61. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. @@ -10,7 +10,8 @@ ## M4sh Initialization. ## ## --------------------- ## -# Be Bourne compatible +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: @@ -19,10 +20,13 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh + + # PATH needs CR @@ -215,7 +219,7 @@ test \$exitcode = 0) || { (exit 1); exit 1; } else as_candidate_shells= as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /usr/bin/posix$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. @@ -233,7 +237,6 @@ IFS=$as_save_IFS # Try only shells that exist, to save several forks. if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { ("$as_shell") 2> /dev/null <<\_ASEOF -# Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: @@ -242,10 +245,12 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh + : _ASEOF @@ -253,7 +258,6 @@ _ASEOF CONFIG_SHELL=$as_shell as_have_required=yes if { "$as_shell" 2> /dev/null <<\_ASEOF -# Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: @@ -262,10 +266,12 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh + : (as_func_return () { @@ -512,19 +518,28 @@ else as_mkdir_p=false fi -# Find out whether ``test -x'' works. Don't use a zero-byte file, as -# systems may use methods other than mode bits to determine executability. -cat >conf$$.file <<_ASEOF -#! /bin/sh -exit 0 -_ASEOF -chmod +x conf$$.file -if test -x conf$$.file >/dev/null 2>&1; then - as_executable_p="test -x" +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' else - as_executable_p=: + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' fi -rm -f conf$$.file +as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" @@ -719,36 +734,36 @@ ac_unique_file="configure.in" # Factoring default headers for most tests. ac_includes_default="\ #include -#if HAVE_SYS_TYPES_H +#ifdef HAVE_SYS_TYPES_H # include #endif -#if HAVE_SYS_STAT_H +#ifdef HAVE_SYS_STAT_H # include #endif -#if STDC_HEADERS +#ifdef STDC_HEADERS # include # include #else -# if HAVE_STDLIB_H +# ifdef HAVE_STDLIB_H # include # endif #endif -#if HAVE_STRING_H -# if !STDC_HEADERS && HAVE_MEMORY_H +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif -#if HAVE_STRINGS_H +#ifdef HAVE_STRINGS_H # include #endif -#if HAVE_INTTYPES_H +#ifdef HAVE_INTTYPES_H # include #endif -#if HAVE_STDINT_H +#ifdef HAVE_STDINT_H # include #endif -#if HAVE_UNISTD_H +#ifdef HAVE_UNISTD_H # include #endif" @@ -855,8 +870,8 @@ LIBTOOL YACC YFLAGS LEX -LEXLIB LEX_OUTPUT_ROOT +LEXLIB LIBOBJS LTLIBOBJS' ac_subst_files='' @@ -866,6 +881,7 @@ target_alias CXX CXXFLAGS LDFLAGS +LIBS CPPFLAGS CCC CC @@ -981,10 +997,10 @@ do -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/-/_/g'` + ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` eval enable_$ac_feature=no ;; -docdir | --docdir | --docdi | --doc | --do) @@ -1000,10 +1016,10 @@ do -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/-/_/g'` + ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` eval enable_$ac_feature=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ @@ -1197,19 +1213,19 @@ do -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } - ac_package=`echo $ac_package| sed 's/-/_/g'` + ac_package=`echo $ac_package | sed 's/[-.]/_/g'` eval with_$ac_package=\$ac_optarg ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } - ac_package=`echo $ac_package | sed 's/-/_/g'` + ac_package=`echo $ac_package | sed 's/[-.]/_/g'` eval with_$ac_package=no ;; --x) @@ -1474,6 +1490,7 @@ Some influential environment variables: CXXFLAGS C++ compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory + LIBS libraries to pass to the linker, e.g. -l CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if you have headers in a nonstandard directory CC C compiler command @@ -1552,7 +1569,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure -generated by GNU Autoconf 2.60 +generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. @@ -1566,7 +1583,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was -generated by GNU Autoconf 2.60. Invocation command line was +generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ @@ -1981,7 +1998,7 @@ case $as_dir/ in # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. @@ -2147,7 +2164,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AWK="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2282,7 +2299,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2322,7 +2339,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_STRIP="strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2411,7 +2428,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2455,7 +2472,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CXX="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2589,7 +2606,7 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. -for ac_file in $ac_files +for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in @@ -2617,6 +2634,12 @@ done test "$ac_cv_exeext" = no && ac_cv_exeext= else + ac_file='' +fi + +{ echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6; } +if test -z "$ac_file"; then echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 @@ -2628,8 +2651,6 @@ See \`config.log' for more details." >&2;} fi ac_exeext=$ac_cv_exeext -{ echo "$as_me:$LINENO: result: $ac_file" >&5 -echo "${ECHO_T}$ac_file" >&6; } # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. @@ -2807,27 +2828,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 @@ -2882,27 +2886,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_prog_cxx_g=yes else echo "$as_me: failed program was:" >&5 @@ -2937,27 +2924,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : else echo "$as_me: failed program was:" >&5 @@ -2993,27 +2963,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_prog_cxx_g=yes else echo "$as_me: failed program was:" >&5 @@ -3406,7 +3359,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -3446,7 +3399,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -3503,7 +3456,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -3544,7 +3497,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue @@ -3602,7 +3555,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -3646,7 +3599,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -3766,27 +3719,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 @@ -3841,27 +3777,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 @@ -3896,27 +3815,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : else echo "$as_me: failed program was:" >&5 @@ -3952,27 +3854,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 @@ -4088,27 +3973,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_prog_cc_c89=$ac_arg else echo "$as_me: failed program was:" >&5 @@ -4332,7 +4200,7 @@ do for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_GREP" && $as_executable_p "$ac_path_GREP"; } || continue + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in @@ -4414,7 +4282,7 @@ do for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_EGREP" && $as_executable_p "$ac_path_EGREP"; } || continue + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in @@ -4895,7 +4763,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 4898 "configure"' > conftest.$ac_ext + echo '#line 4766 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -5019,27 +4887,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then lt_cv_cc_needs_belf=yes else echo "$as_me: failed program was:" >&5 @@ -5048,7 +4900,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 lt_cv_cc_needs_belf=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -5142,17 +4994,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : else echo "$as_me: failed program was:" >&5 @@ -5186,17 +5031,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then # Broken: success on invalid input. continue else @@ -5261,17 +5099,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : else echo "$as_me: failed program was:" >&5 @@ -5305,17 +5136,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then # Broken: success on invalid input. continue else @@ -5386,27 +5210,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 @@ -5582,27 +5389,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 @@ -5665,27 +5455,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 @@ -5721,17 +5494,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 @@ -5843,17 +5609,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then : else echo "$as_me: failed program was:" >&5 @@ -5887,17 +5646,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then # Broken: success on invalid input. continue else @@ -5962,17 +5714,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then : else echo "$as_me: failed program was:" >&5 @@ -6006,17 +5751,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then # Broken: success on invalid input. continue else @@ -6057,7 +5795,7 @@ ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_f77_compiler_gnu if test -n "$ac_tool_prefix"; then - for ac_prog in g77 f77 xlf frt pgf77 cf77 fort77 fl32 af77 f90 xlf90 pgf90 pghpf epcf90 gfortran g95 f95 fort xlf95 ifort ifc efc pgf95 lf95 ftn + for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 @@ -6075,7 +5813,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_F77="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -6101,7 +5839,7 @@ fi fi if test -z "$F77"; then ac_ct_F77=$F77 - for ac_prog in g77 f77 xlf frt pgf77 cf77 fort77 fl32 af77 f90 xlf90 pgf90 pghpf epcf90 gfortran g95 f95 fort xlf95 ifort ifc efc pgf95 lf95 ftn + for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -6119,7 +5857,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_F77="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -6226,27 +5964,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_f77_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 @@ -6289,27 +6010,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_f77_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_prog_f77_g=yes else echo "$as_me: failed program was:" >&5 @@ -6764,7 +6468,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AR="${ac_tool_prefix}ar" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -6804,7 +6508,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_AR="ar" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -6860,7 +6564,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -6900,7 +6604,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_RANLIB="ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -6956,7 +6660,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -6996,7 +6700,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_STRIP="strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -7313,11 +7017,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7316: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7020: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7320: \$? = $ac_status" >&5 + echo "$as_me:7024: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -7581,11 +7285,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7584: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7288: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7588: \$? = $ac_status" >&5 + echo "$as_me:7292: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -7685,11 +7389,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7688: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7392: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:7692: \$? = $ac_status" >&5 + echo "$as_me:7396: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -8165,27 +7869,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` @@ -8199,7 +7887,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi @@ -8240,27 +7928,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` @@ -8274,7 +7946,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi @@ -9522,27 +9194,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_lib_dl_dlopen=yes else echo "$as_me: failed program was:" >&5 @@ -9551,7 +9207,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi @@ -9633,27 +9289,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_func_shl_load=yes else echo "$as_me: failed program was:" >&5 @@ -9662,7 +9302,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_shl_load=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 @@ -9712,27 +9352,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_lib_dld_shl_load=yes else echo "$as_me: failed program was:" >&5 @@ -9741,7 +9365,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_shl_load=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi @@ -9813,27 +9437,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_func_dlopen=yes else echo "$as_me: failed program was:" >&5 @@ -9842,7 +9450,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_dlopen=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 @@ -9892,27 +9500,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_lib_dl_dlopen=yes else echo "$as_me: failed program was:" >&5 @@ -9921,7 +9513,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi @@ -9972,27 +9564,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_lib_svld_dlopen=yes else echo "$as_me: failed program was:" >&5 @@ -10001,7 +9577,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_svld_dlopen=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi @@ -10052,27 +9628,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_lib_dld_dld_link=yes else echo "$as_me: failed program was:" >&5 @@ -10081,7 +9641,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_dld_link=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi @@ -10137,7 +9697,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` @@ -11358,7 +10902,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi @@ -11400,27 +10944,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` @@ -11434,7 +10962,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi @@ -12605,11 +12133,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:12608: $lt_compile\"" >&5) + (eval echo "\"\$as_me:12136: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:12612: \$? = $ac_status" >&5 + echo "$as_me:12140: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -12709,11 +12237,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:12712: $lt_compile\"" >&5) + (eval echo "\"\$as_me:12240: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:12716: \$? = $ac_status" >&5 + echo "$as_me:12244: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -14279,11 +13807,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14282: $lt_compile\"" >&5) + (eval echo "\"\$as_me:13810: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:14286: \$? = $ac_status" >&5 + echo "$as_me:13814: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -14383,11 +13911,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14386: $lt_compile\"" >&5) + (eval echo "\"\$as_me:13914: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:14390: \$? = $ac_status" >&5 + echo "$as_me:13918: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -14853,27 +14381,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_f77_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` @@ -14887,7 +14399,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi @@ -14918,27 +14430,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_f77_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` @@ -14952,7 +14448,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi @@ -16613,11 +16109,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16616: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16112: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:16620: \$? = $ac_status" >&5 + echo "$as_me:16116: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -16881,11 +16377,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16884: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16380: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:16888: \$? = $ac_status" >&5 + echo "$as_me:16384: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -16985,11 +16481,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16988: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16484: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:16992: \$? = $ac_status" >&5 + echo "$as_me:16488: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -17465,27 +16961,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` @@ -17499,7 +16979,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi @@ -17540,27 +17020,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` @@ -17574,7 +17038,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi @@ -19697,7 +19161,8 @@ cat >>conftest.$ac_ext <<_ACEOF int main () { -#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN && defined LITTLE_ENDIAN \ + && BYTE_ORDER && BIG_ENDIAN && LITTLE_ENDIAN) bogus endian macros #endif @@ -19718,27 +19183,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then # It does; now see whether it defined to BIG_ENDIAN or not. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ @@ -19773,27 +19221,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_cv_c_bigendian=yes else echo "$as_me: failed program was:" >&5 @@ -19844,27 +19275,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then ac_cv_c_bigendian=yes fi @@ -20020,7 +19434,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_YACC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -20063,7 +19477,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_LEX="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -20088,116 +19502,69 @@ fi done test -n "$LEX" || LEX=":" -if test -z "$LEXLIB" -then - { echo "$as_me:$LINENO: checking for yywrap in -lfl" >&5 -echo $ECHO_N "checking for yywrap in -lfl... $ECHO_C" >&6; } -if test "${ac_cv_lib_fl_yywrap+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lfl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" +if test "x$LEX" != "x:"; then + cat >conftest.l <<_ACEOF +%% +a { ECHO; } +b { REJECT; } +c { yymore (); } +d { yyless (1); } +e { yyless (input () != 0); } +f { unput (yytext[0]); } +. { BEGIN INITIAL; } +%% +#ifdef YYTEXT_POINTER +extern char *yytext; #endif -char yywrap (); int -main () +main (void) { -return yywrap (); - ; - return 0; + return ! yylex () + ! yywrap (); } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" +{ (ac_try="$LEX conftest.l" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 + (eval "$LEX conftest.l") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_fl_yywrap=yes + (exit $ac_status); } +{ echo "$as_me:$LINENO: checking lex output file root" >&5 +echo $ECHO_N "checking lex output file root... $ECHO_C" >&6; } +if test "${ac_cv_prog_lex_root+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - ac_cv_lib_fl_yywrap=no +if test -f lex.yy.c; then + ac_cv_prog_lex_root=lex.yy +elif test -f lexyy.c; then + ac_cv_prog_lex_root=lexyy +else + { { echo "$as_me:$LINENO: error: cannot find output from $LEX; giving up" >&5 +echo "$as_me: error: cannot find output from $LEX; giving up" >&2;} + { (exit 1); exit 1; }; } fi - -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS fi -{ echo "$as_me:$LINENO: result: $ac_cv_lib_fl_yywrap" >&5 -echo "${ECHO_T}$ac_cv_lib_fl_yywrap" >&6; } -if test $ac_cv_lib_fl_yywrap = yes; then - LEXLIB="-lfl" -else - { echo "$as_me:$LINENO: checking for yywrap in -ll" >&5 -echo $ECHO_N "checking for yywrap in -ll... $ECHO_C" >&6; } -if test "${ac_cv_lib_l_yywrap+set}" = set; then +{ echo "$as_me:$LINENO: result: $ac_cv_prog_lex_root" >&5 +echo "${ECHO_T}$ac_cv_prog_lex_root" >&6; } +LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root + +if test -z "${LEXLIB+set}"; then + { echo "$as_me:$LINENO: checking lex library" >&5 +echo $ECHO_N "checking lex library... $ECHO_C" >&6; } +if test "${ac_cv_lib_lex+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ll $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char yywrap (); -int -main () -{ -return yywrap (); - ; - return 0; -} + ac_save_LIBS=$LIBS + ac_cv_lib_lex='none needed' + for ac_lib in '' -lfl -ll; do + LIBS="$ac_lib $ac_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +`cat $LEX_OUTPUT_ROOT.c` _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" @@ -20212,85 +19579,31 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_l_yywrap=yes + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_lex=$ac_lib else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - ac_cv_lib_l_yywrap=no + fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ echo "$as_me:$LINENO: result: $ac_cv_lib_l_yywrap" >&5 -echo "${ECHO_T}$ac_cv_lib_l_yywrap" >&6; } -if test $ac_cv_lib_l_yywrap = yes; then - LEXLIB="-ll" -fi + test "$ac_cv_lib_lex" != 'none needed' && break + done + LIBS=$ac_save_LIBS fi - +{ echo "$as_me:$LINENO: result: $ac_cv_lib_lex" >&5 +echo "${ECHO_T}$ac_cv_lib_lex" >&6; } + test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex fi -if test "x$LEX" != "x:"; then - { echo "$as_me:$LINENO: checking lex output file root" >&5 -echo $ECHO_N "checking lex output file root... $ECHO_C" >&6; } -if test "${ac_cv_prog_lex_root+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # The minimal lex program is just a single line: %%. But some broken lexes -# (Solaris, I think it was) want two %% lines, so accommodate them. -cat >conftest.l <<_ACEOF -%% -%% -_ACEOF -{ (ac_try="$LEX conftest.l" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$LEX conftest.l") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -if test -f lex.yy.c; then - ac_cv_prog_lex_root=lex.yy -elif test -f lexyy.c; then - ac_cv_prog_lex_root=lexyy -else - { { echo "$as_me:$LINENO: error: cannot find output from $LEX; giving up" >&5 -echo "$as_me: error: cannot find output from $LEX; giving up" >&2;} - { (exit 1); exit 1; }; } -fi -fi -{ echo "$as_me:$LINENO: result: $ac_cv_prog_lex_root" >&5 -echo "${ECHO_T}$ac_cv_prog_lex_root" >&6; } -rm -f conftest.l -LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root { echo "$as_me:$LINENO: checking whether yytext is a pointer" >&5 echo $ECHO_N "checking whether yytext is a pointer... $ECHO_C" >&6; } @@ -20298,13 +19611,13 @@ if test "${ac_cv_prog_lex_yytext_pointer+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # POSIX says lex can declare yytext either as a pointer or an array; the -# default is implementation-dependent. Figure out which it is, since +# default is implementation-dependent. Figure out which it is, since # not all implementations provide the %pointer and %array declarations. ac_cv_prog_lex_yytext_pointer=no -echo 'extern char *yytext;' >>$LEX_OUTPUT_ROOT.c ac_save_LIBS=$LIBS -LIBS="$LIBS $LEXLIB" +LIBS="$LEXLIB $ac_save_LIBS" cat >conftest.$ac_ext <<_ACEOF +#define YYTEXT_POINTER 1 `cat $LEX_OUTPUT_ROOT.c` _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext @@ -20320,27 +19633,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then ac_cv_prog_lex_yytext_pointer=yes else echo "$as_me: failed program was:" >&5 @@ -20349,10 +19646,9 @@ sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_save_LIBS -rm -f "${LEX_OUTPUT_ROOT}.c" fi { echo "$as_me:$LINENO: result: $ac_cv_prog_lex_yytext_pointer" >&5 @@ -20364,6 +19660,7 @@ cat >>confdefs.h <<\_ACEOF _ACEOF fi +rm -f conftest.l $LEX_OUTPUT_ROOT.c fi if test "$LEX" = :; then @@ -20442,27 +19739,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 @@ -20498,17 +19778,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 @@ -20570,7 +19843,7 @@ done -ac_config_files="$ac_config_files Makefile src/Makefile include/Makefile src/server/Makefile src/sql/Makefile src/adapter/Makefile src/gateway/Makefile src/cache/Makefile src/network/Makefile src/sqllog/Makefile src/tools/Makefile src/jdbc/Makefile src/odbc/Makefile" +ac_config_files="$ac_config_files Makefile src/Makefile include/Makefile src/storage/Makefile src/sql/Makefile src/adapter/Makefile src/gateway/Makefile src/cache/Makefile src/network/Makefile src/sqllog/Makefile src/tools/Makefile src/jdbc/Makefile src/odbc/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -20713,7 +19986,8 @@ cat >>$CONFIG_STATUS <<\_ACEOF ## M4sh Initialization. ## ## --------------------- ## -# Be Bourne compatible +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: @@ -20722,10 +19996,13 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh + + # PATH needs CR @@ -20949,19 +20226,28 @@ else as_mkdir_p=false fi -# Find out whether ``test -x'' works. Don't use a zero-byte file, as -# systems may use methods other than mode bits to determine executability. -cat >conf$$.file <<_ASEOF -#! /bin/sh -exit 0 -_ASEOF -chmod +x conf$$.file -if test -x conf$$.file >/dev/null 2>&1; then - as_executable_p="test -x" +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' else - as_executable_p=: + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' fi -rm -f conf$$.file +as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" @@ -20977,7 +20263,7 @@ exec 6>&1 # values after options handling. ac_log=" This file was extended by $as_me, which was -generated by GNU Autoconf 2.60. Invocation command line was +generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -21006,7 +20292,7 @@ current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit - -V, --version print version number, then exit + -V, --version print version number and configuration settings, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions @@ -21030,7 +20316,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ config.status -configured by $0, generated by GNU Autoconf 2.60, +configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2006 Free Software Foundation, Inc. @@ -21147,7 +20433,7 @@ do "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; - "src/server/Makefile") CONFIG_FILES="$CONFIG_FILES src/server/Makefile" ;; + "src/storage/Makefile") CONFIG_FILES="$CONFIG_FILES src/storage/Makefile" ;; "src/sql/Makefile") CONFIG_FILES="$CONFIG_FILES src/sql/Makefile" ;; "src/adapter/Makefile") CONFIG_FILES="$CONFIG_FILES src/adapter/Makefile" ;; "src/gateway/Makefile") CONFIG_FILES="$CONFIG_FILES src/gateway/Makefile" ;; @@ -21363,8 +20649,8 @@ LIBTOOL!$LIBTOOL$ac_delim YACC!$YACC$ac_delim YFLAGS!$YFLAGS$ac_delim LEX!$LEX$ac_delim -LEXLIB!$LEXLIB$ac_delim LEX_OUTPUT_ROOT!$LEX_OUTPUT_ROOT$ac_delim +LEXLIB!$LEXLIB$ac_delim LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF diff --git a/configure.in b/configure.in index a836ef98..510b68f4 100644 --- a/configure.in +++ b/configure.in @@ -36,4 +36,4 @@ AC_CHECK_HEADERS(stdio.h sys/mman.h sys/shm.h sys/errno.h crypt.h unistd.h \ -AC_OUTPUT(Makefile src/Makefile include/Makefile src/server/Makefile src/sql/Makefile src/adapter/Makefile src/gateway/Makefile src/cache/Makefile src/network/Makefile src/sqllog/Makefile src/tools/Makefile src/jdbc/Makefile src/odbc/Makefile) +AC_OUTPUT(Makefile src/Makefile include/Makefile src/storage/Makefile src/sql/Makefile src/adapter/Makefile src/gateway/Makefile src/cache/Makefile src/network/Makefile src/sqllog/Makefile src/tools/Makefile src/jdbc/Makefile src/odbc/Makefile) diff --git a/src/Makefile.am b/src/Makefile.am index eb13ae41..e4d79a3e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,4 +3,4 @@ INCLUDES= $(all_includes) # the library search path. -SUBDIRS = server adapter gateway sqllog sql cache network jdbc odbc tools +SUBDIRS = storage adapter gateway sqllog sql cache network jdbc odbc tools diff --git a/src/Makefile.in b/src/Makefile.in index 5a9fafe0..72652e79 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -167,7 +167,7 @@ target_alias = @target_alias@ INCLUDES = $(all_includes) # the library search path. -SUBDIRS = server adapter gateway sqllog sql cache network jdbc odbc tools +SUBDIRS = storage adapter gateway sqllog sql cache network jdbc odbc tools all: all-recursive .SUFFIXES: diff --git a/src/jdbc/Makefile.am b/src/jdbc/Makefile.am index 1b6c5070..be8dd56e 100644 --- a/src/jdbc/Makefile.am +++ b/src/jdbc/Makefile.am @@ -1,7 +1,7 @@ INCLUDES = -I$(top_srcdir)/include $(all_includes) -I$(top_srcdir)/src/sql METASOURCES = AUTO lib_LTLIBRARIES = libcsqljdbc.la -libcsqljdbc_la_LDFLAGS = -avoid-version -module $(top_srcdir)/src/sql/.libs/libcsqlsql $(top_srcdir)/src/server/.libs/libcsql $(top_srcdir)/src/sqllog/.libs/libcsqlsqllog $(top_srcdir)/src/network/.libs/libcsqlnw -lcrypt +libcsqljdbc_la_LDFLAGS = -avoid-version -module $(top_srcdir)/src/sql/.libs/libcsqlsql $(top_srcdir)/src/storage/.libs/libcsql $(top_srcdir)/src/sqllog/.libs/libcsqlsqllog $(top_srcdir)/src/network/.libs/libcsqlnw -lcrypt libcsqljdbc_la_SOURCES = JSqlConnection.cxx JSqlStatement.cxx noinst_HEADERS = JSqlConnection.h JSqlStatement.h diff --git a/src/jdbc/Makefile.in b/src/jdbc/Makefile.in index baa87161..3a402192 100644 --- a/src/jdbc/Makefile.in +++ b/src/jdbc/Makefile.in @@ -185,7 +185,7 @@ target_alias = @target_alias@ INCLUDES = -I$(top_srcdir)/include $(all_includes) -I$(top_srcdir)/src/sql METASOURCES = AUTO lib_LTLIBRARIES = libcsqljdbc.la -libcsqljdbc_la_LDFLAGS = -avoid-version -module $(top_srcdir)/src/sql/.libs/libcsqlsql $(top_srcdir)/src/server/.libs/libcsql $(top_srcdir)/src/sqllog/.libs/libcsqlsqllog $(top_srcdir)/src/network/.libs/libcsqlnw -lcrypt +libcsqljdbc_la_LDFLAGS = -avoid-version -module $(top_srcdir)/src/sql/.libs/libcsqlsql $(top_srcdir)/src/storage/.libs/libcsql $(top_srcdir)/src/sqllog/.libs/libcsqlsqllog $(top_srcdir)/src/network/.libs/libcsqlnw -lcrypt libcsqljdbc_la_SOURCES = JSqlConnection.cxx JSqlStatement.cxx noinst_HEADERS = JSqlConnection.h JSqlStatement.h libcsqljdbc_a_LIBADD = diff --git a/src/odbc/Makefile b/src/odbc/Makefile index fffd4207..c66bdc88 100644 --- a/src/odbc/Makefile +++ b/src/odbc/Makefile @@ -77,14 +77,14 @@ HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = ${SHELL} /home/csql/csql/missing --run aclocal-1.9 +ACLOCAL = ${SHELL} /home/csql/latest/aug/csql/missing --run aclocal-1.9 AMDEP_FALSE = # AMDEP_TRUE = -AMTAR = ${SHELL} /home/csql/csql/missing --run tar +AMTAR = ${SHELL} /home/csql/latest/aug/csql/missing --run tar AR = ar -AUTOCONF = ${SHELL} /home/csql/csql/missing --run autoconf -AUTOHEADER = ${SHELL} /home/csql/csql/missing --run autoheader -AUTOMAKE = ${SHELL} /home/csql/csql/missing --run automake-1.9 +AUTOCONF = ${SHELL} /home/csql/latest/aug/csql/missing --run autoconf +AUTOHEADER = ${SHELL} /home/csql/latest/aug/csql/missing --run autoheader +AUTOMAKE = ${SHELL} /home/csql/latest/aug/csql/missing --run automake-1.9 AWK = gawk CC = gcc CCDEPMODE = depmode=gcc3 @@ -94,7 +94,7 @@ CPPFLAGS = CXX = g++ CXXCPP = g++ -E CXXDEPMODE = depmode=gcc3 -CXXFLAGS = -g -I/usr/java/jdk1.6.0_10/include -I/usr/java/jdk1.6.0_10/include/linux +CXXFLAGS = -g -I/opt/java/jdk1.6.0_04/include -I/opt/java/jdk1.6.0_04/include/linux CYGPATH_W = echo DEFS = -DHAVE_CONFIG_H DEPDIR = .deps @@ -113,14 +113,14 @@ INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s LDFLAGS = LEX = flex -LEXLIB = -lfl +LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBOBJS = LIBS = LIBTOOL = $(SHELL) $(top_builddir)/libtool LN_S = ln -s LTLIBOBJS = -MAKEINFO = ${SHELL} /home/csql/csql/missing --run makeinfo +MAKEINFO = ${SHELL} /home/csql/latest/aug/csql/missing --run makeinfo OBJEXT = o PACKAGE = csql PACKAGE_BUGREPORT = @@ -167,7 +167,7 @@ host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info -install_sh = /home/csql/csql/install-sh +install_sh = /home/csql/latest/aug/csql/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale @@ -176,7 +176,7 @@ mandir = ${datarootdir}/man mkdir_p = mkdir -p -- oldincludedir = /usr/include pdfdir = ${docdir} -prefix = /home/csql/csql/install +prefix = /home/csql/latest/aug/csql/install program_transform_name = s,x,x, psdir = ${docdir} sbindir = ${exec_prefix}/sbin @@ -187,7 +187,7 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/src/sql -I$(top_srcdir)/inclu METASOURCES = AUTO lib_LTLIBRARIES = libcsqlodbc.la libcsqlodbc_la_LDFLAGS = -avoid-version -module \ - $(top_builddir)/src/server/.libs/libcsql \ + $(top_builddir)/src/storage/.libs/libcsql \ $(top_builddir)/src/sql/.libs/libcsqlsql \ $(top_builddir)/src/gateway/.libs/libcsqlgw \ $(top_builddir)/src/network/.libs/libcsqlnw \ diff --git a/src/odbc/Makefile.am b/src/odbc/Makefile.am index 8b8862da..759ff7a2 100644 --- a/src/odbc/Makefile.am +++ b/src/odbc/Makefile.am @@ -2,7 +2,7 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/src/sql -I$(top_srcdir)/inclu METASOURCES = AUTO lib_LTLIBRARIES = libcsqlodbc.la libcsqlodbc_la_LDFLAGS = -avoid-version -module \ - $(top_builddir)/src/server/.libs/libcsql \ + $(top_builddir)/src/storage/.libs/libcsql \ $(top_builddir)/src/sql/.libs/libcsqlsql \ $(top_builddir)/src/gateway/.libs/libcsqlgw \ $(top_builddir)/src/network/.libs/libcsqlnw \ diff --git a/src/odbc/Makefile.in b/src/odbc/Makefile.in index ca787251..910a38ba 100644 --- a/src/odbc/Makefile.in +++ b/src/odbc/Makefile.in @@ -187,7 +187,7 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/src/sql -I$(top_srcdir)/inclu METASOURCES = AUTO lib_LTLIBRARIES = libcsqlodbc.la libcsqlodbc_la_LDFLAGS = -avoid-version -module \ - $(top_builddir)/src/server/.libs/libcsql \ + $(top_builddir)/src/storage/.libs/libcsql \ $(top_builddir)/src/sql/.libs/libcsqlsql \ $(top_builddir)/src/gateway/.libs/libcsqlgw \ $(top_builddir)/src/network/.libs/libcsqlnw \ diff --git a/src/sql/Makefile.am b/src/sql/Makefile.am index e4f699ad..3ab4971e 100644 --- a/src/sql/Makefile.am +++ b/src/sql/Makefile.am @@ -3,7 +3,7 @@ YACC = yacc -vd METASOURCES = AUTO lib_LTLIBRARIES = libcsqlsql.la libcsqlsql_la_LDFLAGS = -avoid-version -module \ - $(top_builddir)/src/server/.libs/libcsql \ + $(top_builddir)/src/storage/.libs/libcsql \ $(top_builddir)/src/gateway/.libs/libcsqlgw \ $(top_builddir)/src/sqllog/.libs/libcsqlsqllog \ $(top_builddir)/src/adapter/.libs/libcsqlodbcadapter @@ -13,6 +13,6 @@ libcsqlsql_la_SOURCES = dmlyacc.yxx dmllex.lxx ParsedData.cxx SelStatement.cxx \ SqlStatement.cxx StatementFactory.cxx SqlFactory.cxx noinst_HEADERS = Parser.h Statement.h -libcsqlsql_a_LIBADD = $(top_builddir)/src/server/libcsql.la \ +libcsqlsql_a_LIBADD = $(top_builddir)/src/storage/libcsql.la \ $(top_builddir)/src/adapter/libcsqlodbcadapter.la \ $(top_builddir)/src/adapter/libcsqlgw.la diff --git a/src/sql/Makefile.in b/src/sql/Makefile.in index 3e3f616b..3f25856f 100644 --- a/src/sql/Makefile.in +++ b/src/sql/Makefile.in @@ -202,7 +202,7 @@ INCLUDES = -I$(top_srcdir)/include $(all_includes) METASOURCES = AUTO lib_LTLIBRARIES = libcsqlsql.la libcsqlsql_la_LDFLAGS = -avoid-version -module \ - $(top_builddir)/src/server/.libs/libcsql \ + $(top_builddir)/src/storage/.libs/libcsql \ $(top_builddir)/src/gateway/.libs/libcsqlgw \ $(top_builddir)/src/sqllog/.libs/libcsqlsqllog \ $(top_builddir)/src/adapter/.libs/libcsqlodbcadapter @@ -213,7 +213,7 @@ libcsqlsql_la_SOURCES = dmlyacc.yxx dmllex.lxx ParsedData.cxx SelStatement.cxx \ SqlStatement.cxx StatementFactory.cxx SqlFactory.cxx noinst_HEADERS = Parser.h Statement.h -libcsqlsql_a_LIBADD = $(top_builddir)/src/server/libcsql.la \ +libcsqlsql_a_LIBADD = $(top_builddir)/src/storage/libcsql.la \ $(top_builddir)/src/adapter/libcsqlodbcadapter.la \ $(top_builddir)/src/adapter/libcsqlgw.la diff --git a/src/storage/AggTableImpl.cxx b/src/storage/AggTableImpl.cxx new file mode 100644 index 00000000..16d23ed7 --- /dev/null +++ b/src/storage/AggTableImpl.cxx @@ -0,0 +1,559 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +AggTableImpl::AggTableImpl() +{ +} +AggTableImpl::~AggTableImpl() +{ +} +DbRetVal AggTableImpl::bindFld(const char *name, void *val) +{ + return ErrBadCall; +} +DbRetVal AggTableImpl::bindFld(const char *fldname, AggType aggType, void *val) +{ + FieldInfo *info = new FieldInfo(); + tableHdl->getFieldInfo(fldname, info); + AggFldDef *def = new AggFldDef(); + strcpy(def->fldName, fldname); + def->type = info->type; + def->length= info->length; + def->appBuf = val; + def->atype=aggType; + def->bindBuf = NULL; + def->alreadyBinded = false; + ListIterator iter = fldList.getIterator(); + AggFldDef *elem; + //If it is already binded, then use the same buffer which is binded. + //this code is to handle statements which have more aggregates on same field + while (iter.hasElement()) + { + elem = (AggFldDef*) iter.nextElement(); + if (strcmp(elem->fldName, fldname)==0) + { + def->bindBuf = elem->bindBuf; + def->alreadyBinded = true; + break; + } + } + if (!def->bindBuf) + { + def->bindBuf = AllDataType::alloc(def->type, def->length); + tableHdl->bindFld(fldname, def->bindBuf); + } + fldList.append(def); + delete info; + return OK; +} +DbRetVal AggTableImpl::setGroup(const char *fldname, void *val) +{ + FieldInfo *info = new FieldInfo(); + tableHdl->getFieldInfo(fldname, info); + strcpy(groupFld.fldName, fldname); + groupFld.type = info->type; + groupFld.length = info->length; + groupFld.appBuf = val; + groupFld.bindBuf = AllDataType::alloc(info->type, info->length); + tableHdl->bindFld(fldname, groupFld.bindBuf); + delete info; + return OK; +} + +DbRetVal AggTableImpl::execute() +{ + ListIterator iter = fldList.getIterator(); + AggFldDef *def; + if (isGroupSet()) + aggNodeSize = AllDataType::size(groupFld.type, groupFld.length); + else + aggNodeSize = 0; + while (iter.hasElement()) + { + def = (AggFldDef*) iter.nextElement(); + aggNodeSize = aggNodeSize + AllDataType::size(def->type, def->length); + if (def->atype == AGG_AVG) aggNodeSize = aggNodeSize + sizeof(int);//for count + } + void *tuple = NULL; + int offset=0; + tableHdl->execute(); + aggNodes.reset(); + while((tuple = tableHdl->fetch()) != NULL) + { + char *buffer = (char*)insertOrGet(); + iter.reset(); + if (isGroupSet()) + offset = AllDataType::size(groupFld.type, groupFld.length); + else + offset = 0; + while (iter.hasElement()) + { + def = (AggFldDef*) iter.nextElement(); + switch(def->atype) + { + case AGG_MIN: { + bool result = AllDataType::compareVal(buffer+offset, + def->bindBuf, OpGreaterThan, def->type, def->length); + if (result) + AllDataType::copyVal(buffer+offset, def->bindBuf, + def->type, def->length); + break; + } + case AGG_MAX: { + bool result = AllDataType::compareVal(buffer+offset, + def->bindBuf, OpLessThan, def->type, def->length); + if (result) + AllDataType::copyVal(buffer+offset, def->bindBuf, + def->type, def->length); + break; + } + case AGG_SUM: { + AllDataType::addVal(buffer+offset, def->bindBuf, def->type); + break; + } + case AGG_AVG: { + AllDataType::addVal(buffer+offset, def->bindBuf, def->type); + (*(int*)(buffer+offset + AllDataType::size(def->type, def->length)))++; + offset = offset +sizeof(int); //->count + break; + } + case AGG_COUNT: + (*(int*)(buffer+offset))++; + break; + } + offset = offset + AllDataType::size(def->type, def->length); + } + } + aggNodeIter = aggNodes.getIterator(); + iter.reset(); + char *element; + while (iter.hasElement()) { + def = (AggFldDef*) iter.nextElement(); + if (isGroupSet()) + offset = AllDataType::size(groupFld.type, groupFld.length); + else + offset = 0; + switch(def->atype) + { + case AGG_AVG: { + while (aggNodeIter.hasElement()) { + element = (char*)aggNodeIter.nextElement(); + AllDataType::divVal(element+offset, + *(int*)(element+offset+AllDataType::size(def->type, def->length)), + def->type); + } + offset = offset +sizeof(int); + } + } + offset = offset + AllDataType::size(def->type, def->length); + } + aggNodeIter.reset(); + tableHdl->close(); + return OK; +} +void* AggTableImpl::insertOrGet() +{ + ListIterator aiter = aggNodes.getIterator(); + char *element; + while (aiter.hasElement()) { + element = (char*)aiter.nextElement(); + + if (!isGroupSet()) return element; + if (AllDataType::compareVal(element, groupFld.bindBuf, OpEquals, + groupFld.type, groupFld.length)) + { + return element; + } + } + element = (char*)malloc(aggNodeSize); + ListIterator iter = fldList.getIterator(); + AggFldDef *def; + char *offset; + if (isGroupSet()) { + AllDataType::copyVal(element, groupFld.bindBuf, groupFld.type, + groupFld.length); + offset = element + AllDataType::size(groupFld.type, groupFld.length); + } + else + offset = element; + + while (iter.hasElement()) + { + def = (AggFldDef*) iter.nextElement(); + switch(def->atype) { + case AGG_MIN: { *(int*)(offset)=INT_MAX; break; } + case AGG_MAX: { *(int*)(offset)=INT_MIN; break; } + case AGG_SUM: { *(int*)(offset)=0; break; } + case AGG_AVG: { + *(int*)(offset)=0; + *(int*)(offset+AllDataType::size(def->type, def->length))=0; //count + offset = offset+ sizeof(int); + break; + } + case AGG_COUNT: { *(int*)(offset)=0; break; } + } + offset = offset + AllDataType::size(def->type, def->length); + } + aggNodes.append(element); + return element; +} + +void* AggTableImpl::fetch() +{ + if(aggNodeIter.hasElement()) + { + void *elem = aggNodeIter.nextElement(); + copyValuesToBindBuffer(elem); + return elem; + } + else + return NULL; + +} +void* AggTableImpl::fetch(DbRetVal &rv) +{ + rv = OK; + return fetch(); +} + +void* AggTableImpl::fetchNoBind() +{ + if(aggNodeIter.hasElement()) + { + void *elem = aggNodeIter.nextElement(); + return elem; + } + else + return NULL; +} + +void* AggTableImpl::fetchNoBind(DbRetVal &rv) +{ + rv = OK; + return fetchNoBind(); +} + +DbRetVal AggTableImpl::copyValuesToBindBuffer(void *elem) +{ + char *element = (char*)elem; + //Iterate through the bind list and copy the value here + ListIterator fIter = fldList.getIterator(); + AggFldDef *def; + AllDataType::copyVal(groupFld.appBuf, elem, groupFld.type, groupFld.length); + char *colPtr = (char*) elem + AllDataType::size(groupFld.type, groupFld.length); + while (fIter.hasElement()) + { + def = (AggFldDef*) fIter.nextElement(); + if (NULL != def->appBuf) { + AllDataType::copyVal(def->appBuf, colPtr, def->type, def->length); + } + colPtr = colPtr + os::align(AllDataType::size(def->type, def->length)); + if(def->atype == AGG_AVG) colPtr = colPtr + sizeof(int); + } + return OK; +} + +long AggTableImpl::numTuples() +{ + return aggNodes.size(); +} +void AggTableImpl::closeScan() +{ + aggNodeIter.reset(); + ListIterator aiter = aggNodes.getIterator(); + char *element; + while (aiter.hasElement()) { + element = (char*)aiter.nextElement(); + free(element); + } + aggNodes.reset(); +} + +DbRetVal AggTableImpl::close() +{ + //free memory allocated. make sure that field buffers are freed only once. + //for stmts which has more than one agg on same field needs to be handled safely + free(groupFld.bindBuf); + ListIterator iter = fldList.getIterator(); + AggFldDef *elem; + while (iter.hasElement()) + { + elem = (AggFldDef*) iter.nextElement(); + if(!elem->alreadyBinded) free(elem->bindBuf); + } + fldList.reset(); + return OK; +} + + + + + + + +//----------------------------------------------------------- + +JoinTableImpl::JoinTableImpl() +{ + isNestedLoop= true; +} +JoinTableImpl::~JoinTableImpl() +{ +} +void JoinTableImpl::getFieldNameAlone(char *fname, char *name) { + bool dotFound= false; + char *fullname = fname; + while(*fullname != '\0') + { + if (*fullname == '.') { dotFound = true; break; } + fullname++; + } + if (dotFound) strcpy(name, ++fullname); else strcpy(name, fname); + +} +void JoinTableImpl::getTableNameAlone(char *fname, char *name) { + strcpy(name, fname); + while(*name != '\0') + { + if (*name == '.') { *name='\0'; break; } + name++; + } + return; +} +DbRetVal JoinTableImpl::bindFld(const char *fldname, void *val) +{ + FieldInfo *info = new FieldInfo(); + char tableName[IDENTIFIER_LENGTH]; + char fieldName[IDENTIFIER_LENGTH]; + getTableNameAlone((char*)fldname, tableName); + getFieldNameAlone((char*)fldname, fieldName); + printf("%s %s \n", tableName, fieldName); + + ListIterator iter = projList.getIterator(); + JoinProjFieldInfo *elem; + while (iter.hasElement()) + { + elem = (JoinProjFieldInfo*) iter.nextElement(); + if (strcmp(elem->fieldName, fieldName)==0 && + strcmp(elem->tableName, tableName) ==0) + { + printError(ErrBadCall, "Field already binded %s\n", fldname); + delete info; + return ErrBadCall; + } + } + JoinProjFieldInfo *def = new JoinProjFieldInfo(); + strcpy(def->tableName, tableName); + strcpy(def->fieldName, fieldName); + def->appBuf = val; + def->bindBuf = AllDataType::alloc(def->type, def->length); + + if (strcmp(tableName, leftTableHdl->getName()) == 0) + { + leftTableHdl->getFieldInfo(fieldName, info); + def->bindBuf = AllDataType::alloc(info->type, info->length); + leftTableHdl->bindFld(fieldName, def->bindBuf); + + }else if (strcmp(tableName, rightTableHdl->getName()) == 0) + { + rightTableHdl->getFieldInfo(fieldName, info); + def->bindBuf = AllDataType::alloc(info->type, info->length); + rightTableHdl->bindFld(fieldName, def->bindBuf); + }else + { + printError(ErrBadCall, "TableName is invalid\n"); + delete info; + return ErrBadCall; + } + def->type = info->type; + def->length= info->length; + projList.append(def); + delete info; + return OK; +} +DbRetVal JoinTableImpl::setJoinCondition(const char *fldname1, + ComparisionOp op, + const char *fldname2) +{ + getTableNameAlone((char*)fldname1, jCondition.tableName1); + getFieldNameAlone((char*)fldname1, jCondition.fieldName1); + getTableNameAlone((char*)fldname2, jCondition.tableName2); + getFieldNameAlone((char*)fldname2, jCondition.fieldName2); + + //check if it is already binded + ListIterator iter = projList.getIterator(); + JoinProjFieldInfo *elem; + jCondition.alreadyBinded1 = false; + jCondition.alreadyBinded2 = false; + jCondition.op = op; + while (iter.hasElement()) + { + elem = (JoinProjFieldInfo*) iter.nextElement(); + if (strcmp(elem->fieldName, jCondition.fieldName1)==0 && + strcmp(elem->tableName, jCondition.tableName1) ==0) + { + jCondition.alreadyBinded1 = true; + jCondition.bindBuf1 = elem->bindBuf; + jCondition.type1 = elem->type; + jCondition.length1 = elem->length; + } + if (strcmp(elem->fieldName, jCondition.fieldName2)==0 && + strcmp(elem->tableName, jCondition.tableName2) ==0) + { + jCondition.alreadyBinded2 = true; + jCondition.bindBuf2 = elem->bindBuf; + jCondition.type2 = elem->type; + jCondition.length2 = elem->length; + } + } + + FieldInfo *info = new FieldInfo(); + if (!jCondition.alreadyBinded1) { + if (strcmp(jCondition.tableName1, leftTableHdl->getName()) == 0) + { + leftTableHdl->getFieldInfo(jCondition.fieldName1, info); + jCondition.bindBuf1 = AllDataType::alloc(info->type, info->length); + leftTableHdl->bindFld(jCondition.fieldName1, jCondition.bindBuf1); + + }else if (strcmp(jCondition.tableName1, rightTableHdl->getName()) == 0) + { + rightTableHdl->getFieldInfo(jCondition.fieldName1, info); + jCondition.bindBuf1 = AllDataType::alloc(info->type, info->length); + rightTableHdl->bindFld(jCondition.fieldName1, jCondition.bindBuf1); + }else + { + printError(ErrBadCall, "TableName is invalid\n"); + delete info; + return ErrBadCall; + } + } + if (!jCondition.alreadyBinded2) { + if (strcmp(jCondition.tableName2, leftTableHdl->getName()) == 0) + { + leftTableHdl->getFieldInfo(jCondition.fieldName2, info); + jCondition.bindBuf2 = AllDataType::alloc(info->type, info->length); + leftTableHdl->bindFld(jCondition.fieldName2, jCondition.bindBuf2); + + }else if (strcmp(jCondition.tableName2, rightTableHdl->getName()) == 0) + { + rightTableHdl->getFieldInfo(jCondition.fieldName2, info); + jCondition.bindBuf2 = AllDataType::alloc(info->type, info->length); + rightTableHdl->bindFld(jCondition.fieldName2, jCondition.bindBuf2); + }else + { + printError(ErrBadCall, "TableName is invalid\n"); + delete info; + return ErrBadCall; + } + } + return OK; +} + + +DbRetVal JoinTableImpl::execute() +{ + isNestedLoop = true; + leftTableHdl->execute(); + rightTableHdl->execute(); + leftTableHdl->fetch(); + //TODO + //if join condition is not set then do nl + //if it is inner join, hen do nl + //nl cannot be done for outer join + return OK; +} + +void* JoinTableImpl::fetch() +{ + if (isNestedLoop) + { + void *rec = rightTableHdl->fetch(); + if (rec==NULL) + { + rightTableHdl->close(); + rightTableHdl->execute(); + rec = rightTableHdl->fetch(); + if (rec == NULL) return NULL; + rec = leftTableHdl->fetch(); + if (rec == NULL) return NULL; + bool result = evaluate(); + if (! result) return fetch(); + copyValuesToBindBuffer(NULL); + return rec; + } + else { + bool result = evaluate(); + if (! result) return fetch(); + copyValuesToBindBuffer(NULL); + return rec; + } + + } + return NULL; +} +bool JoinTableImpl::evaluate() +{ + if (!jCondition.bindBuf1 || !jCondition.bindBuf2) return true; + return AllDataType::compareVal(jCondition.bindBuf1, jCondition.bindBuf2, + jCondition.op, + jCondition.type1, jCondition.length1); +} +void* JoinTableImpl::fetch(DbRetVal &rv) +{ + rv = OK; + return fetch(); +} + +void* JoinTableImpl::fetchNoBind() +{ + return NULL; +} + +void* JoinTableImpl::fetchNoBind(DbRetVal &rv) +{ + rv = OK; + return fetchNoBind(); +} + +DbRetVal JoinTableImpl::copyValuesToBindBuffer(void *elem) +{ + //Iterate through the bind list and copy the value here + ListIterator fIter = projList.getIterator(); + JoinProjFieldInfo *def; + while (fIter.hasElement()) + { + def = (JoinProjFieldInfo*) fIter.nextElement(); + if (NULL != def->appBuf) { + AllDataType::copyVal(def->appBuf, def->bindBuf, def->type, def->length); + } + } + return OK; +} + +long JoinTableImpl::numTuples() +{ + return 0; +} +void JoinTableImpl::closeScan() +{ +} +DbRetVal JoinTableImpl::close() +{ + return OK; +} diff --git a/src/storage/BucketIter.cxx b/src/storage/BucketIter.cxx new file mode 100644 index 00000000..2b6bbdd3 --- /dev/null +++ b/src/storage/BucketIter.cxx @@ -0,0 +1,26 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include + +HashIndexNode* BucketIter::next() +{ + if (iter == NULL) return NULL; + HashIndexNode *node = iter; + iter = iter ->next_; + printDebug(DM_HashIndex,"BucketIter::next returns %x",node); + return node; +} diff --git a/src/storage/BucketList.cxx b/src/storage/BucketList.cxx new file mode 100644 index 00000000..0af88af5 --- /dev/null +++ b/src/storage/BucketList.cxx @@ -0,0 +1,68 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +DbRetVal BucketList::insert(Chunk *chunk, Database *db, void *key, void*tuple) +{ + DbRetVal rv = OK; + HashIndexNode *newNode;// (HashIndexNode*) chunk->allocate(db, &rv); + newNode= (HashIndexNode*) chunk->allocate(db, &rv); + if (NULL == newNode) + { + printError(rv, "Unable to allocate HashIndex node"); + return rv; + } + printDebug(DM_HashIndex,"Hash Index node allocated:%x", newNode); + newNode->ptrToKey_ = key; + newNode->ptrToTuple_ = tuple; + newNode->next_ = NULL; + + //If this is the first node, set it as head + if (NULL == head) + { + printDebug(DM_HashIndex, "BucketList:insert head is null key:%x",key); + head = newNode; + return OK; + } + + HashIndexNode *it = head; + while (NULL != it->next_) it = it->next_; + it->next_ = newNode; + printDebug(DM_HashIndex, "BucketList:insert adding it to the end of list key:%x", key); + return rv; +} +//Returns 2 if the head itself is removed. +DbRetVal BucketList::remove(Chunk *chunk, Database *db, void *keyPtr) +{ + if (NULL == head) return ErrNotFound; + HashIndexNode *ite = head, *prev = head; + while (ite != NULL) + { + if (ite->ptrToKey_ == keyPtr) + { + prev->next_ = ite->next_; + chunk->free(db, ite); + if ( ite == head) { head = NULL; return SplCase; } + return OK; + } + prev = ite; + ite = ite->next_; + } + printError(ErrNotFound, "Node not found in the bucket list"); + return ErrNotFound; +} diff --git a/src/storage/CatalogTables.cxx b/src/storage/CatalogTables.cxx new file mode 100644 index 00000000..032496a0 --- /dev/null +++ b/src/storage/CatalogTables.cxx @@ -0,0 +1,579 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include + +DbRetVal CatalogTableTABLE::insert(const char *name, int id, size_t size, + int numFlds, void* chunk, void *&tptr) +{ + Chunk *tChunk = systemDatabase_->getSystemDatabaseChunk(TableTableId); + DbRetVal rv = OK; + tptr = tChunk->allocate(systemDatabase_, &rv); + if (NULL == tptr) + { + printError(rv, + "Could not allocate memory for for TABLE catalog table"); + return rv; + } + TABLE *tableInfo = (TABLE*)tptr; + strcpy(tableInfo->tblName_, name); + tableInfo->tblID_ = id; + tableInfo->length_ = size; + tableInfo->numFlds_ = numFlds; + tableInfo->numIndexes_ = 0; + tableInfo->chunkPtr_ = chunk; + printDebug(DM_SystemDatabase,"One Row inserted into TABLE %x %s",tptr, name); + return OK; +} + +DbRetVal CatalogTableTABLE::remove(const char *name, void *&chunk, void *&tptr) +{ + Chunk *tChunk = systemDatabase_->getSystemDatabaseChunk(TableTableId); + ChunkIterator iter = tChunk->getIterator(); + + void *data = NULL; + while ((data = iter.nextElement())!= NULL) + { + if (0 == strcmp(((TABLE*)data)->tblName_, name)) + { + //remove this element and store the tblPtr + //there will be only one row for this table(Primary key) + tptr = (void*) data; + chunk = (Chunk*) ((TABLE*)data)->chunkPtr_; + break; + } + } + if (NULL != tptr) + { + tChunk->free(systemDatabase_, tptr); + printDebug(DM_SystemDatabase,"One Row deleted from TABLE %x %s",tptr, name); + } + else + { + printError(ErrNotExists,"Table %s not exists in TABLE catalog table", name); + return ErrNotExists; + } + return OK; +} + +DbRetVal CatalogTableTABLE::getChunkAndTblPtr(const char *name, + void *&chunk, void *&tptr) +{ + Chunk *chk = systemDatabase_->getSystemDatabaseChunk(TableTableId); + ChunkIterator iter = chk->getIterator();; + while (NULL != (tptr = iter.nextElement())) + { + if (strcmp(((TABLE*)tptr)->tblName_, name) == 0) + { + //there will be only one row for this table(Primary key) + chunk = (Chunk*) ((TABLE*)tptr)->chunkPtr_; + return OK; + } + } + //table not found in TABLE + return ErrNotFound; +} + +List CatalogTableTABLE::getTableList() +{ + List tableList; + Chunk *chk = systemDatabase_->getSystemDatabaseChunk(TableTableId); + ChunkIterator iter = chk->getIterator(); + void *tptr; + while (NULL != (tptr = iter.nextElement())) + { + Identifier *elem = new Identifier(); + strcpy(elem->name, ((TABLE*)tptr)->tblName_); + tableList.append(elem); + } + return tableList; +} + +DbRetVal CatalogTableFIELD::insert(FieldIterator &iter, int tblID, void *tptr) +{ + Chunk *fChunk = systemDatabase_->getSystemDatabaseChunk(FieldTableId); + DbRetVal rv = OK; + while (iter.hasElement()) + { + void *fptr = fChunk->allocate(systemDatabase_, &rv); + if (NULL == fptr) + { + printError(rv, + "Could not allocate for FIELD catalog table"); + return rv; + } + FIELD *fldInfo = (FIELD*)fptr; + FieldDef fDef = iter.nextElement(); + strcpy(fldInfo->fldName_, fDef.fldName_); + fldInfo->tblID_ = tblID; + fldInfo->tblPtr_ = tptr; + fldInfo->type_ = fDef.type_; + fldInfo->length_ = fDef.length_; + fldInfo->offset_ = 0; //TODO + os::memcpy(fldInfo->defaultValueBuf_, fDef.defaultValueBuf_, + DEFAULT_VALUE_BUF_LENGTH); + fldInfo->isNull_ = fDef.isNull_; + fldInfo->isPrimary_ = fDef.isPrimary_; + fldInfo->isUnique_ = fDef.isUnique_; + fldInfo->isDefault_ = fDef.isDefault_; + fldInfo->width_ = 0; //TODO + fldInfo->scale_ = 0; //TODO + printDebug(DM_SystemDatabase,"One Row inserted into FIELD %x %s",fldInfo, fDef.fldName_); + + } + return OK; +} + +DbRetVal CatalogTableFIELD::remove(void *tptr) +{ + Chunk *fChunk = systemDatabase_->getSystemDatabaseChunk(FieldTableId); + ChunkIterator fIter = fChunk->getIterator(); + void *data = NULL; + while ((data = fIter.nextElement())!= NULL) + { + if (((FIELD*)data)->tblPtr_ == tptr) + { + //remove this element + fChunk->free(systemDatabase_, data); + printDebug(DM_SystemDatabase,"One Row deleted from FIELD %x",data); + } + } + return OK; +} + +void CatalogTableFIELD::getFieldInfo(void* tptr, FieldList &list) +{ + Chunk *fChunk = systemDatabase_->getSystemDatabaseChunk(FieldTableId); + ChunkIterator fIter = fChunk->getIterator();; + void *data = NULL; + while (NULL != (data = fIter.nextElement())) + { + if (((FIELD*)data)->tblPtr_ == tptr) + { + //add the information to the field list + FIELD *fTuple = (FIELD*)data; + FieldDef fldDef; + strcpy(fldDef.fldName_, fTuple->fldName_); + fldDef.fldName_[IDENTIFIER_LENGTH] = '\0'; + fldDef.type_ = fTuple->type_; + fldDef.length_ = fTuple->length_; + fldDef.isDefault_ = fTuple->isDefault_; + os::memcpy(fldDef.defaultValueBuf_, fTuple->defaultValueBuf_, + DEFAULT_VALUE_BUF_LENGTH); + fldDef.isNull_ = fTuple->isNull_; + fldDef.isUnique_ = fTuple->isUnique_; + fldDef.isPrimary_ = fTuple->isPrimary_; + list.append(fldDef); + } + } + return; +} + +DbRetVal CatalogTableFIELD::getFieldPtrs(FieldNameList &fldList,void *tptr, char **&fptr) +{ + Chunk *fChunk = systemDatabase_->getSystemDatabaseChunk(FieldTableId); + int i=0; + char *fName = NULL; + bool found = false; + fldList.resetIter(); + void *data = NULL; + DbRetVal rv =OK; + while (NULL != (fName = fldList.nextFieldName())) + { + ChunkIterator fIter = fChunk->getIterator(); + found = false; + while (NULL != (data = fIter.nextElement())) + { + if (((FIELD*)data)->tblPtr_ == tptr) + { + if(0 == strcmp((char*)((FIELD*)data)->fldName_, fName)) + { + found = true; + //if (! ((FIELD*)data)->isNull_) rv = ErrBadCall; + fptr[i++] = (char*) data; + break; + } + } + } + if (!found) + { + printError(ErrNotFound, + "No entries found in FIELD catalog table for the table specified"); + return ErrNotFound; + } + } + return rv; +} + +DbRetVal CatalogTableINDEX::insert(const char *name, void *tptr, int numFlds, bool isUnique, + void* chunk, int bucketSize, void *hChunk, void *&tupleptr) +{ + Chunk *tChunk = systemDatabase_->getSystemDatabaseChunk(IndexTableId); + ChunkIterator iter = tChunk->getIterator(); + + //Checking for index having same name, proceed further only + //if no such indexes are + void *data = NULL; + while ((data = iter.nextElement())!= NULL) + { + if (0 == strcmp(((INDEX*)data)->indName_, name)) + { + printError(ErrAlready, "Index with name \'%s\' already exists " + "on the table \'%s\'.", name, ((TABLE *)tptr)->tblName_); + return ErrAlready; + } + + } + + DbRetVal rv =OK; + tupleptr = tChunk->allocate(systemDatabase_, &rv); + if (NULL == tupleptr) + { + printError(rv, + "Could not allocate for INDEX catalog table"); + return rv; + } + INDEX *indexInfo = (INDEX*)tupleptr; + strcpy(indexInfo->indName_, name); + indexInfo->tblID_ = -1; //Not used currently + indexInfo->tblPtr_ = tptr; + indexInfo->numFlds_ = numFlds; + indexInfo->indexType_ = hashIndex; + indexInfo->chunkPtr_ = chunk; + indexInfo->hashNodeChunk_ = hChunk; + indexInfo->noOfBuckets_ = bucketSize; + indexInfo->isUnique_ = isUnique; + printDebug(DM_SystemDatabase,"One Row inserted into INDEX %x %s",tupleptr, name); + return OK; +} + +DbRetVal CatalogTableINDEX::remove(const char *name, void *&chunk, void *&hchunk, void *&iptr) +{ + Chunk *fChunk = systemDatabase_->getSystemDatabaseChunk(IndexTableId); + ChunkIterator iter = fChunk->getIterator(); + + void *data = NULL; + while ((data = iter.nextElement())!= NULL) + { + if (0 == strcmp(((INDEX*)data)->indName_, name)) + { + //remove this element and store the tuple ptr + //there will be only one row for this table(Primary key) + chunk = (Chunk*) ((INDEX*)data)->chunkPtr_; + hchunk = (Chunk*) ((INDEX*)data)->hashNodeChunk_; + iptr = (void*) data; + break; + } + } + if (NULL != iptr) + { + fChunk->free(systemDatabase_, iptr); + printDebug(DM_SystemDatabase,"One Row deleted from INDEX %x %s",iptr, name); + } + else + { + printError(ErrNotExists,"Index %s not exists in INDEX catalog table", name); + return ErrNotExists; + } + return OK; +} +DbRetVal CatalogTableINDEX::get(const char *name, void *&chunk, void *&hchunk, void *&iptr) +{ + Chunk *fChunk = systemDatabase_->getSystemDatabaseChunk(IndexTableId); + ChunkIterator iter = fChunk->getIterator(); + + void *data = NULL; + while ((data = iter.nextElement())!= NULL) + { + if (0 == strcmp(((INDEX*)data)->indName_, name)) + { + //remove this element and store the tuple ptr + //there will be only one row for this table(Primary key) + chunk = (Chunk*) ((INDEX*)data)->chunkPtr_; + hchunk = (Chunk*) ((INDEX*)data)->hashNodeChunk_; + iptr = (void*) data; + break; + } + } + if (NULL == iptr) + { + printError(ErrNotExists,"Index %s not exists in INDEX catalog table", name); + return ErrNotExists; + } + return OK; +} + +int CatalogTableINDEX::getNumIndexes(void *tptr) +{ + Chunk *fChunk = systemDatabase_->getSystemDatabaseChunk(IndexTableId); + ChunkIterator iter = fChunk->getIterator(); + void *iptr = NULL; + int numIndex =0; + while (NULL != (iptr = iter.nextElement())) + { + if (((INDEX*)iptr)->tblPtr_ == tptr) numIndex++; + } + return numIndex; +} + +char* CatalogTableINDEX::getIndexName(void *tptr, int position) +{ + if (position == 0) return NULL; + Chunk *fChunk = systemDatabase_->getSystemDatabaseChunk(IndexTableId); + ChunkIterator iter = fChunk->getIterator(); + void *iptr = NULL; + int numIndex =0; + int curPos =0; + while (NULL != (iptr = iter.nextElement())) + { + if (((INDEX*)iptr)->tblPtr_ == tptr) curPos++; + if ( curPos == position ) return ((INDEX*)iptr)->indName_; + } + return NULL; + +} + +void CatalogTableINDEX::getIndexPtrs(void *tptr, char **&array) +{ + void *iptr = NULL; + Chunk *fChunk = systemDatabase_->getSystemDatabaseChunk(IndexTableId); + ChunkIterator iter = fChunk->getIterator(); + int i=0; + while (NULL != (iptr = iter.nextElement())) + { + if (((INDEX*)iptr)->tblPtr_ == tptr) + { + array[i++] = (char*) iptr; + } + } + return; +} + +ChunkIterator CatalogTableINDEX::getIterator(void *iptr) +{ + INDEX *index = (INDEX*)iptr; + return ((Chunk*)index->chunkPtr_)->getIterator(); +} + + +int CatalogTableINDEX::getNoOfBuckets(void *iptr) +{ + INDEX *index = (INDEX*)iptr; + return index->noOfBuckets_; +} + +int CatalogTableINDEX::getUnique(void *iptr) +{ + INDEX *index = (INDEX*)iptr; + return index->isUnique_; +} +char* CatalogTableINDEX::getName(void *iptr) +{ + INDEX *index = (INDEX*)iptr; + return index->indName_; +} + +DbRetVal CatalogTableINDEXFIELD::insert(FieldNameList &fldList, void *indexPtr, + void *tblPtr, char **&fptr) +{ + + Chunk *fChunk; + fChunk = systemDatabase_->getSystemDatabaseChunk(IndexFieldTableId); + fldList.resetIter(); + int i =0; + char *fName =NULL; + void *data = NULL; + ChunkIterator ifIter = fChunk->getIterator(); + while (NULL != (fName = fldList.nextFieldName())) + { + ifIter = fChunk->getIterator(); + while ((data = ifIter.nextElement()) != NULL) { + if (0 == strcmp(((FIELD *)((INDEXFIELD *) data)->fieldPtr)->fldName_, fName) && ((INDEXFIELD *)data)->tablePtr == tblPtr) { + printError(ErrAlready, "Index on field \'%s\' already exists on table \'%s\' by name \'%s\'", ((FIELD *)((INDEXFIELD *)data)->fieldPtr)->fldName_, ((TABLE *)((INDEXFIELD *)data)->tablePtr)->tblName_, ((INDEX *)((INDEXFIELD *)data)->indexPtr)->indName_); + return ErrAlready; + } + } + DbRetVal rv = OK; + void *fieldptr = fChunk->allocate(systemDatabase_, &rv); + if (NULL == fieldptr) + { + printError(rv, + "Could not allocate for USER catalog table"); + return rv; + } + INDEXFIELD *fldInfo = (INDEXFIELD*)fieldptr; + fldInfo->tablePtr = tblPtr; + fldInfo->fieldPtr = (FIELD*)fptr[i++]; + fldInfo->indexPtr = indexPtr; + printDebug(DM_SystemDatabase,"One Row inserted into INDEXFIELD %x", fldInfo); + } + return OK; +} + +DbRetVal CatalogTableINDEXFIELD::remove(void *iptr) +{ + Chunk *fChunk; + fChunk = systemDatabase_->getSystemDatabaseChunk(IndexFieldTableId); + ChunkIterator fIter = fChunk->getIterator(); + void *data = NULL; + while ((data = fIter.nextElement())!= NULL) + { + if (((INDEXFIELD*)data)->indexPtr == iptr) + { + //remove this element + fChunk->free(systemDatabase_, data); + printDebug(DM_SystemDatabase,"One Row deleted from INDEXFIELD %x", data); + } + } + return OK; +} + +DbRetVal CatalogTableINDEXFIELD::getFieldNameAndType(void *index, + char *&name, DataType &type) +{ + Chunk *ifChunk; + ifChunk = systemDatabase_->getSystemDatabaseChunk(IndexFieldTableId); + ChunkIterator ifIter = ifChunk->getIterator(); + void *data = NULL; + while ((data = ifIter.nextElement())!= NULL) + { + if (((INDEXFIELD*)data)->indexPtr == index) + { + //store the field name + name = ((FIELD*)(((INDEXFIELD*)data)->fieldPtr))->fldName_; + type = ((FIELD*)(((INDEXFIELD*)data)->fieldPtr))->type_; + return OK; + } + } + printError(ErrNotExists,"Index %x not exists in catalog table", index); + return ErrNotExists; +} + +DbRetVal CatalogTableINDEXFIELD::getFieldInfo(void *index, FieldList &list) +{ + Chunk *ifChunk; + ifChunk = systemDatabase_->getSystemDatabaseChunk(IndexFieldTableId); + ChunkIterator ifIter = ifChunk->getIterator(); + void *data = NULL; + int rowCount =0; + while ((data = ifIter.nextElement())!= NULL) + { + if (((INDEXFIELD*)data)->indexPtr == index) + { + //add the information to the field list + FIELD *fTuple = (FIELD*)(((INDEXFIELD*)data)->fieldPtr); + FieldDef fldDef; + strcpy(fldDef.fldName_, fTuple->fldName_); + fldDef.fldName_[IDENTIFIER_LENGTH] = '\0'; + fldDef.type_ = fTuple->type_; + fldDef.length_ = fTuple->length_; + fldDef.isDefault_ = fTuple->isDefault_; + os::memcpy(fldDef.defaultValueBuf_, fTuple->defaultValueBuf_, + DEFAULT_VALUE_BUF_LENGTH); + fldDef.isNull_ = fTuple->isNull_; + fldDef.isUnique_ = fTuple->isUnique_; + fldDef.isPrimary_ = fTuple->isPrimary_; + list.append(fldDef); + } + rowCount++; + } + if (!rowCount) { + printError(ErrNotExists,"Index %x not exists in catalog table", index); + return ErrNotExists; + } + return OK; +} + +DbRetVal CatalogTableUSER::insert(const char *name, const char *pass) +{ + Chunk *tChunk = systemDatabase_->getSystemDatabaseChunk(UserTableId); + DbRetVal rv = OK; + USER *usrInfo = (USER*)tChunk->allocate(systemDatabase_, &rv); + if (NULL == usrInfo) + { + printError(rv, + "Could not allocate for USER catalog table"); + return rv; + } + strcpy(usrInfo->userName_, name); + strcpy(usrInfo->password_, os::encrypt(pass, "A0")); + return OK; + +} + +DbRetVal CatalogTableUSER::authenticate(const char *name, const char *pass, + bool &isAuthenticated, bool &isDba) +{ + Chunk *tChunk = systemDatabase_->getSystemDatabaseChunk(UserTableId); + ChunkIterator iter = tChunk->getIterator(); + void *data = NULL; + while (NULL != (data = iter.nextElement())) + { + if (strcmp(((USER*)data)->userName_, name) == 0) + { + //verify the password + char * enpass = os::encrypt(pass,"A0"); + if (0 == strcmp(enpass, ((USER*)data)->password_)) + { + isAuthenticated = true; + if (0 == strcmp(((USER*)data)->userName_, DBAUSER)) + isDba = true; else isDba = false; + return OK; + } + } + } + isAuthenticated = false; + return OK; +} + +DbRetVal CatalogTableUSER::remove(const char *name) +{ + Chunk *tChunk = systemDatabase_->getSystemDatabaseChunk(UserTableId); + ChunkIterator iter = tChunk->getIterator(); + void *data = NULL; + while ((data = iter.nextElement())!= NULL) + { + if (strcmp(((USER*)data)->userName_, name) == 0) + { + //remove this element + tChunk->free(systemDatabase_, data); + return OK; + } + } + printError(ErrNotExists,"User %s not exists in catalog table", name); + return ErrNotExists; +} + +DbRetVal CatalogTableUSER::changePass(const char *name, const char *pass) +{ + Chunk *tChunk = systemDatabase_->getSystemDatabaseChunk(UserTableId); + ChunkIterator iter = tChunk->getIterator(); + void *data = NULL; + while (NULL != (data = iter.nextElement())) + { + if (strcmp(((USER*)data)->userName_, name) == 0) + { + //change the password + strcpy(((USER*)data)->password_, os::encrypt(pass, "A0")); + return OK; + } + } + printError(ErrNotExists,"User %s not exists in catalog table", name); + return ErrNotExists; +} diff --git a/src/storage/Chunk.cxx b/src/storage/Chunk.cxx new file mode 100644 index 00000000..10983623 --- /dev/null +++ b/src/storage/Chunk.cxx @@ -0,0 +1,703 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include + +// sets the size of the Chunk allocator for fixed size +// allocator +// we need one integer to store book keeping information +// whether the storage allocation unit is used of not +// when it is deleted this flag is only set to unused +void Chunk::setSize(size_t size) +{ + + size_t needSize = size + sizeof(int); + size_t multiple = (size_t) os::floor(needSize / sizeof(size_t)); + size_t rem = needSize % sizeof(size_t); + if (0 == rem) + allocSize_ = needSize; + else + allocSize_ = (multiple + 1) * sizeof(size_t); +} + +void* Chunk::allocateForLargeDataSize(Database *db) +{ + PageInfo* pageInfo = ((PageInfo*)curPage_); + DbRetVal ret = db->getAllocDatabaseMutex(); + if (ret != 0) + { + printError(ErrLockTimeOut,"Unable to acquire alloc database Mutex"); + return NULL; + } + + //check whether we have space in curPage + if (pageInfo->hasFreeSpace_ == 1) + { + char *data = ((char*)curPage_) + sizeof(PageInfo); + pageInfo->hasFreeSpace_ =0; + *((int*)data) = 1; + db->releaseAllocDatabaseMutex(); + return data + sizeof(int); + } + + + //no space in curpage , get new page from database + pageInfo = (PageInfo*)db->getFreePage(allocSize_); + if (NULL == pageInfo) + { + db->releaseAllocDatabaseMutex(); + printError(ErrNoMemory,"No more free pages in the database"); + return NULL; + } + printDebug(DM_Alloc, "Chunk ID:%d Large Data Item newPage:%x", + chunkID_, pageInfo); + int multiple = os::floor(allocSize_ / PAGE_SIZE); + int offset = ((multiple + 1) * PAGE_SIZE); + + pageInfo->setPageAsUsed(offset); + + //create the link + ((PageInfo*)curPage_)->nextPage_ = (Page*) pageInfo; + //Make this as current page + curPage_ = (Page*) pageInfo; + char* data = ((char*)curPage_) + sizeof(PageInfo); + //TODO::check whether it is locked + *((int*)data) = 1; + db->releaseAllocDatabaseMutex(); + return data + sizeof(int); + +} + +void* Chunk::allocateFromFirstPage(Database *db, int noOfDataNodes) +{ + PageInfo *pageIter = ((PageInfo*)firstPage_); + printDebug(DM_Alloc, "Chunk ID:%d. No free page in database", + chunkID_); + printDebug(DM_Alloc, "Scan from firstPage:%x for free nodes", + firstPage_); + char *data = NULL; + int i = 0; + //scan from first page to locate a free node available + while(NULL != pageIter) + { + data = ((char*)pageIter) + sizeof(PageInfo); + if (pageIter->hasFreeSpace_ == 1) + { + for (i = 0; i< noOfDataNodes -1; i++) + { + if (1 == *((int*)data)) + data = data + allocSize_; + else break; + } + if (i != noOfDataNodes -1) break; + } + printDebug(DM_Alloc, "Chunk ID: %d Page :%x does not have free nodes", + chunkID_, pageIter); + pageIter = (PageInfo*)((PageInfo*) pageIter)->nextPage_; + } + if (NULL == pageIter) return NULL; + printDebug(DM_Alloc,"ChunkID:%d Scan for free node End:Page :%x", + chunkID_, pageIter); + *((int*)data) = 1; + return data + sizeof(int); + +} + +void* Chunk::allocateFromNewPage(Database *db) +{ + DbRetVal ret = db->getAllocDatabaseMutex(); + if (ret != 0) + { + printError(ErrLockTimeOut,"Unable to acquire alloc database Mutex"); + return NULL; + } + //get a new page from db + Page *page = db->getFreePage(); + if (page == NULL) + { + db->releaseAllocDatabaseMutex(); + return NULL; + } + printDebug(DM_Alloc, "ChunkID:%d Normal Data Item newPage:%x", + chunkID_, page); + //Initialize pageInfo for this new page + PageInfo *pInfo = (PageInfo*)page; + pInfo->setPageAsUsed(0); + + //create the link between old page and the newly created page + PageInfo* pageInfo = ((PageInfo*)curPage_); + pageInfo->nextPage_ = page; + + //make this new page as the current page + curPage_ = page; + + char* data = ((char*)page) + sizeof(PageInfo); + *((int*)data) = 1; + db->releaseAllocDatabaseMutex(); + return data + sizeof(int); +} + +//Allocates memory to store data +//TODO::check whether it is locked before allocating. +//delete tuple will set the usedflag to true, but locks will be held +//till commit and it shall be rolledback.So make sure that it does not +//allocate deleted tuple which is yet to be commited. + +void* Chunk::allocate(Database *db, DbRetVal *status) +{ + PageInfo* pageInfo = ((PageInfo*)curPage_); + + int noOfDataNodes=os::floor((PAGE_SIZE - sizeof(PageInfo))/allocSize_); + char *data = ((char*)curPage_) + sizeof(PageInfo); + printDebug(DM_Alloc, "Chunk::allocate id:%d curPage:%x noOfDataNodes:%d", + chunkID_, curPage_, noOfDataNodes); + + //1.scan through data list and find if any is free to use in current page + //2.If there is none then + // a) get new free page from db. set the prev->next to point + // to this new page + //4. b) initialize the free page to zero and get first data ptr. + //5.If there is one, return that + + //For allocation more than PAGE_SIZE + if (0 == noOfDataNodes) + { + data = (char*) allocateForLargeDataSize(db); + return data; + } + + int ret = getChunkMutex(db->procSlot); + if (ret != 0) + { + if (status != NULL) *status = ErrLockTimeOut; + printError(ErrLockTimeOut,"Unable to acquire chunk Mutex"); + return NULL; + } + int i = noOfDataNodes; + if (pageInfo->hasFreeSpace_ == 1) + { + for (i = 1; i< noOfDataNodes; i++) + { + if (*((int*)data) == 1) data = data + allocSize_; + else break; + } + + } + printDebug(DM_Alloc, "ChunkID:%d Node which might be free is %d", + chunkID_, i); + //It comes here if the pageInfo->hasFreeSpace ==0 + //or there are no free data space in this page + if (i == noOfDataNodes && *((int*)data) == 1) + { + + printDebug(DM_Alloc, "ChunkID:%d curPage does not have free nodes.", chunkID_); + //there are no free data space in this page + pageInfo->hasFreeSpace_ = 0; + if (chunkID_ == LockTableId || chunkID_ == TransHasTableId) + { + data = (char*) allocateFromFirstPage(db, noOfDataNodes); + if (NULL == data) + { + data = (char*) allocateFromNewPage(db); + if (data == NULL) + { + printError(ErrNoMemory, "No memory in any of the pages:Increase db size"); + if (status != NULL) *status = ErrNoMemory; + } + } + } + else + { + data = (char*) allocateFromNewPage(db); + if (NULL == data) + { + data = (char*) allocateFromFirstPage(db, noOfDataNodes); + if (data == NULL) + { + printError(ErrNoMemory, "No memory in any of the pages:Increase db size"); + if (status != NULL) *status = ErrNoMemory; + } + } + } + releaseChunkMutex(db->procSlot); + return data; + } + *((int*)data) = 1; + releaseChunkMutex(db->procSlot); + return data + sizeof(int); +} + + +void* Chunk::allocateForLargeDataSize(Database *db, size_t size) +{ + //no need to take chunk mutexes for this, as we are taking alloc database mutex + int multiple = os::floor(size / PAGE_SIZE); + int offset = ((multiple + 1) * PAGE_SIZE); + PageInfo* pageInfo = ((PageInfo*)curPage_); + DbRetVal ret = db->getAllocDatabaseMutex(); + if (ret != 0) + { + printError(ErrLockTimeOut,"Unable to acquire alloc database Mutex"); + return NULL; + } + pageInfo = (PageInfo*)db->getFreePage(allocSize_); + if (NULL == pageInfo) + { + db->releaseAllocDatabaseMutex(); + printError(ErrNoMemory,"No more free pages in the database:Increase db size"); + return NULL; + } + printDebug(DM_VarAlloc,"Chunk::allocate Large Data Item id:%d Size:%d curPage:%x ", + chunkID_, size, curPage_); + //TODO:: logic pending + + + //REDESIGN MAY BE REQUIRED:Lets us live with this for now. + //what happens to the space lets say 10000 bytes is allocated + //it needs 2 pages,= 16000 bytes, 6000 bytes should not be wasted + //in this case.So need to take of this. + //Will be coded at later stage as this is developed to support + //undo logging and currently we shall assume that the logs generated + //wont be greater than PAGE_SIZE. + db->releaseAllocDatabaseMutex(); + return NULL; + +} + + + +void* Chunk::allocFromNewPageForVarSize(Database *db, size_t size) +{ + //Should be called only for data items getAllocDatabaseMutex(); + if (ret != 0) + { + printError(ErrLockTimeOut,"Unable to acquire alloc database Mutex"); + return NULL; + } + + void *vnode = varSizeFirstFitAllocate(size); + if (vnode != NULL) + { + db->releaseAllocDatabaseMutex(); + return vnode; + } + + Page *newPage = db->getFreePage(); + db->releaseAllocDatabaseMutex(); + if (NULL == newPage) + { + return NULL; + } + + printDebug(DM_VarAlloc, "ChunkID:%d New Page: %x ", chunkID_, newPage); + PageInfo *pInfo = (PageInfo*) newPage; + pInfo->setPageAsUsed(0); + createDataBucket(newPage, PAGE_SIZE, size); + + ((PageInfo*)curPage_)->nextPage_ = newPage; + curPage_ = newPage; + char *data= ((char*)newPage) + sizeof(PageInfo) + sizeof(VarSizeInfo); + return data; +} + +//Allocates from the current page of the chunk. +//Scans through the VarSizeInfo objects in the page and gets the free slot +void* Chunk::allocateFromCurPageForVarSize(size_t size) +{ + //Should be called only for data items isUsed_) + { + if( size + sizeof(VarSizeInfo) < varInfo->size_) + { + splitDataBucket(varInfo, size); + printDebug(DM_VarAlloc, "Chunkid:%d splitDataBucket: Size: %d Item:%x ", + chunkID_, size, varInfo); + return (char*)varInfo + sizeof(VarSizeInfo); + } + else if (size == varInfo->size_) { + varInfo->isUsed_ = 1; + return (char *) varInfo + sizeof(VarSizeInfo); + } + + } + varInfo = (VarSizeInfo*)((char*)varInfo + sizeof(VarSizeInfo) + +varInfo->size_); + } + return NULL; +} + +//Allocates memory to store data of variable size +void* Chunk::allocate(Database *db, size_t size, DbRetVal *status) +{ + if (0 == size) return NULL; + //check if the size is more than PAGE_SIZE + //if it is more than the PAGE_SIZE, then allocate new + //page using database and then link the curPage to the + //newly allocated page + //if it is less than PAGE_SIZE, then check the curpage for + //free memory of specified size + //if not available, then scan from the firstPage for the free + //space + + //TODO::During the scan, merge nearby nodes if both are free + //if not available then allocate new page + + size_t alignedSize = os::align(size); + void *data = NULL; + int ret = getChunkMutex(db->procSlot); + if (ret != 0) + { + printError(ErrLockTimeOut,"Unable to acquire chunk Mutex"); + *status = ErrLockTimeOut; + return NULL; + } + if (alignedSize > PAGE_SIZE) + { + data = allocateForLargeDataSize(db, alignedSize); + } + else + { + data = allocateFromCurPageForVarSize(alignedSize); + if (NULL == data) { + //No available spaces in the current page. + //allocate new page + data= allocFromNewPageForVarSize(db, alignedSize); + if (NULL == data) { + printError(ErrNoMemory, "No memory in any of the pages:Increase db size"); + if (status != NULL) *status = ErrNoMemory; + } + } + } + releaseChunkMutex(db->procSlot); + return data; +} + +//Assumes chunk mutex is already taken, before calling this +void* Chunk::varSizeFirstFitAllocate(size_t size) +{ + printDebug(DM_VarAlloc, "Chunk::varSizeFirstFitAllocate size:%d firstPage:%x", + size, firstPage_); + + Page *page = ((PageInfo*)firstPage_); + size_t alignedSize = os::align(size); + while(NULL != page) + { + VarSizeInfo *varInfo = (VarSizeInfo*)(((char*)page) + sizeof(PageInfo)); + while ((char*) varInfo < ((char*)page + PAGE_SIZE)) + { + if (0 == varInfo->isUsed_) + { + if( alignedSize +sizeof(VarSizeInfo) < varInfo->size_) + { + splitDataBucket(varInfo, alignedSize); + return ((char*)varInfo) + sizeof(VarSizeInfo); + } + else if (alignedSize == varInfo->size_) { + varInfo->isUsed_ = 1; + printDebug(DM_VarAlloc, "VarSizeFirstFitAllocate returning %x", ((char*)varInfo) +sizeof(VarSizeInfo)); + return ((char *) varInfo) + sizeof(VarSizeInfo); + } + } + varInfo = (VarSizeInfo*)((char*)varInfo + sizeof(VarSizeInfo) + +varInfo->size_); + } + printDebug(DM_VarAlloc, "Chunk:This page does not have free data nodes page:%x", page); + page = ((PageInfo*) page)->nextPage_; + } + return NULL; +} + +void Chunk::freeForVarSizeAllocator(void *ptr, int pslot) +{ + int ret = getChunkMutex(pslot); + if (ret != 0) + { + printError(ErrLockTimeOut,"Unable to acquire chunk Mutex"); + return; + } + VarSizeInfo *varInfo = (VarSizeInfo*)((char*)ptr- sizeof(VarSizeInfo)); + varInfo->isUsed_ = 0; + printDebug(DM_VarAlloc,"chunkID:%d Unset isUsed for %x", chunkID_, varInfo); + releaseChunkMutex(pslot); + return; + +} + +void Chunk::freeForLargeAllocator(void *ptr, int pslot) +{ + //There will be max only one data element in a page. + //PageInfo is stored just before the data. + int ret = getChunkMutex(pslot); + if (ret != 0) + { + printError(ErrLockTimeOut,"Unable to acquire chunk Mutex"); + return; + } + PageInfo *pageInfo = (PageInfo*)(((char*) + ptr) - (sizeof(PageInfo) + sizeof(int))); + PageInfo *pInfo = (PageInfo*)firstPage_, *prev = (PageInfo*)firstPage_; + bool found = false; + while(!found) + { + if (pInfo == pageInfo) {found = true; break; } + prev = pInfo; + pInfo = (PageInfo*)pInfo->nextPage_; + } + if (!found) + { + printError(ErrSysFatal,"Page %x not found in page list:Logical error", pageInfo ); + releaseChunkMutex(pslot); + return ; + } + prev->nextPage_ = pageInfo->nextPage_; + pageInfo->nextPageAfterMerge_ = NULL; + pageInfo->isUsed_ = 0; + os::memset(pageInfo, 0 , allocSize_); + pageInfo->hasFreeSpace_ = 1; + releaseChunkMutex(pslot); + return; +} + +//Frees the memory pointed by ptr +void Chunk::free(Database *db, void *ptr) +{ + if (0 == allocSize_) + { + freeForVarSizeAllocator(ptr, db->procSlot); + return; + } + int noOfDataNodes =os::floor((PAGE_SIZE - sizeof(PageInfo)) / allocSize_); + + if (0 == noOfDataNodes) + { + freeForLargeAllocator(ptr, db->procSlot); + return; + } + int ret = getChunkMutex(db->procSlot); + if (ret != 0) + { + printError(ErrLockTimeOut,"Unable to acquire chunk Mutex"); + return; + } + //below is the code for freeing in fixed size allocator + + //unset the used flag + *((int*)ptr -1 ) = 0; + PageInfo *pageInfo; + pageInfo = getPageInfo(db, ptr); + if (NULL == pageInfo) + { + printError(ErrSysFatal,"Probable Data corruption: pageInfo is NULL", pageInfo ); + releaseChunkMutex(db->procSlot); + return; + } + //set the pageinfo where this ptr points + pageInfo->hasFreeSpace_ = 1; + releaseChunkMutex(db->procSlot); + return; +} + +//returns the pageInfo of the page where this ptr points +//This works only if the data size is less than PAGE_SIZE +//If ptr points to data which is more than PAGE_SIZE,then +//calling this might lead to memory corruption +//Note:IMPORTANT::assumes db lock is taken before calling this +PageInfo* Chunk::getPageInfo(Database *db, void *ptr) +{ + if (allocSize_ < PAGE_SIZE - sizeof(PageInfo)) { + int rem = (long) ptr % 8192; + return (PageInfo*)(((char*)ptr) - rem); + } else { + //large size allocator + char *inPtr = (char*)ptr; + PageInfo* pageInfo = ((PageInfo*)firstPage_); + + while( pageInfo != NULL ) + { + if (inPtr > (char*) pageInfo && pageInfo->nextPageAfterMerge_ >inPtr) + return pageInfo; + pageInfo = (PageInfo*)pageInfo->nextPage_ ; + } + } + return NULL; +} + +//If called on chunk used to store tuples, it returns the total number of rows +//present in the table +long Chunk::getTotalDataNodes() +{ + long totalNodes =0; + if (0 == allocSize_) //->variable size allocator + { + Page *page = ((PageInfo*)firstPage_); + while(NULL != page) + { + VarSizeInfo *varInfo = (VarSizeInfo*)(((char*)page) + sizeof(PageInfo)); + while ((char*) varInfo < ((char*)page + PAGE_SIZE)) + { + if (1 == varInfo->isUsed_) totalNodes++; + varInfo = (VarSizeInfo*)((char*)varInfo + sizeof(VarSizeInfo) + +varInfo->size_); + } + page = ((PageInfo*) page)->nextPage_; + } + return totalNodes; + } + + //TODO::for large size allocator + if (allocSize_ >PAGE_SIZE)//->each page has only one data node + return 0; + + int noOfDataNodes=os::floor((PAGE_SIZE - sizeof(PageInfo))/allocSize_); + PageInfo* pageInfo = ((PageInfo*)firstPage_); + char *data = ((char*)firstPage_) + sizeof(PageInfo); + int i=0; + while( pageInfo != NULL ) + { + data = ((char*)pageInfo) + sizeof(PageInfo); + for (i = 0; i< noOfDataNodes; i++) + { + if (*((int*)data) == 1) { totalNodes++;} + data = data + allocSize_; + } + pageInfo = (PageInfo*)(((PageInfo*)pageInfo)->nextPage_) ; + } + return totalNodes; +} + +//TODO::for other type of allocators +int Chunk::compact() +{ + PageInfo* pageInfo = ((PageInfo*)firstPage_); + PageInfo* prevPage = pageInfo; + if (NULL == pageInfo) + { + return 0; + } + pageInfo = (PageInfo*)pageInfo->nextPage_; + if (0 == allocSize_) + { + while( pageInfo != NULL ) + { + bool flag = false; + VarSizeInfo *varInfo = (VarSizeInfo*)(((char*)pageInfo) + + sizeof(PageInfo)); + while ((char*) varInfo < ((char*)pageInfo + PAGE_SIZE)) + { + if (1 == varInfo->isUsed_) {flag=true; break;} + varInfo = (VarSizeInfo*)((char*)varInfo + sizeof(VarSizeInfo) + +varInfo->size_); + } + if (!flag) { + printDebug(DM_VarAlloc,"Freeing unused page in varsize allocator %x\n", pageInfo); + prevPage->nextPage_ = pageInfo->nextPage_; + pageInfo->isUsed_ = 0; + } + prevPage = pageInfo; + pageInfo = (PageInfo*)(((PageInfo*)pageInfo)->nextPage_) ; + printDebug(DM_VarAlloc,"compact iter %x\n", pageInfo); + } + }else if (allocSize_ < PAGE_SIZE) + { + while( pageInfo != NULL ) + { + bool flag = false; + int noOfDataNodes=os::floor((PAGE_SIZE - sizeof(PageInfo))/allocSize_); + char *data = ((char*)pageInfo) + sizeof(PageInfo); + for (int i = 0; i< noOfDataNodes -1; i++) + { + if (1 == *((int*)data)) { flag = true; break; } + data = data +allocSize_; + } + if (!flag) { + printDebug(DM_Alloc,"Freeing unused page in fixed allocator %x\n", pageInfo); + prevPage->nextPage_ = pageInfo->nextPage_; + pageInfo->isUsed_ = 0; + } + prevPage = pageInfo; + pageInfo = (PageInfo*)(((PageInfo*)pageInfo)->nextPage_) ; + printDebug(DM_Alloc,"compact iter %x\n", pageInfo); + } + } + return 0; +} + +int Chunk::totalPages() +{ + //logic is same for variable size and for large data node allocator. + PageInfo* pageInfo = ((PageInfo*)firstPage_); + int totPages=0; + while( pageInfo != NULL ) + { + totPages++; + pageInfo = (PageInfo*)(((PageInfo*)pageInfo)->nextPage_) ; + } + return totPages; +} + +int Chunk::initMutex() +{ + return chunkMutex_.init("Chunk"); +} +int Chunk::getChunkMutex(int procSlot) +{ + return chunkMutex_.getLock(procSlot); +} +int Chunk::releaseChunkMutex(int procSlot) +{ + return chunkMutex_.releaseLock(procSlot); +} +int Chunk::destroyMutex() +{ + return chunkMutex_.destroy(); +} +void Chunk::splitDataBucket(VarSizeInfo *varInfo, size_t needSize) +{ + int remSpace = varInfo->size_ - sizeof(VarSizeInfo) - needSize; + varInfo->isUsed_ = 1; + varInfo->size_ = needSize; + varInfo = (VarSizeInfo*)((char*)varInfo + + sizeof(VarSizeInfo) + varInfo->size_); + varInfo->isUsed_ = 0; + varInfo->size_ = remSpace; + printDebug(DM_VarAlloc, "Remaining space is %d\n", remSpace); + return; +} + + +void Chunk::createDataBucket(Page *page, size_t totalSize, size_t needSize) +{ + VarSizeInfo *varInfo = (VarSizeInfo*)(((char*)page) + sizeof(PageInfo)); + varInfo->isUsed_ = 0; + varInfo->size_ = PAGE_SIZE - sizeof(PageInfo) - sizeof(VarSizeInfo); + splitDataBucket(varInfo, needSize); + return; +} + + + diff --git a/src/storage/ChunkIterator.cxx b/src/storage/ChunkIterator.cxx new file mode 100644 index 00000000..cfd7e08a --- /dev/null +++ b/src/storage/ChunkIterator.cxx @@ -0,0 +1,103 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include + +//No iterators for variable size allocators +ChunkIterator Chunk::getIterator() +{ + ChunkIterator iter; + iter.chunkID_ = chunkID_; + iter.allocSize_ = allocSize_; + iter.allocType_ = allocType_; + iter.iterPage_ = firstPage_; + iter.nodeOffset_ = 0; + iter.noOfNodes_ = os::floor((PAGE_SIZE - sizeof(PageInfo)) / allocSize_); + return iter; +} + +void* ChunkIterator::nextElement() +{ + if(NULL == iterPage_) + { + printError(ErrNotExists,"No iter page exists."); + return NULL; + } + //No iterators for variable size allocators + if(0 == allocSize_) + { + printError(ErrNotExists,"Iterators are not for variable size allocators"); + return NULL; + } + PageInfo* pageInfo = (PageInfo*)iterPage_; + if (0 == noOfNodes_) + { + //means tuple larger than PAGE_SIZE + iterPage_ = pageInfo->nextPage_; + return (char*)pageInfo + sizeof(PageInfo)+ sizeof(int); + } + + char *data = ((char*)iterPage_) + sizeof(PageInfo) + (nodeOffset_ * allocSize_) ; + + //check whether there are any nodes in the current page + int i = nodeOffset_; + while(nodeOffset_ < noOfNodes_) + { + if (*((int*)data) == 0) + { + //not used, so skip it + data = data + allocSize_; + nodeOffset_++; + if (data >= (char*)iterPage_ + PAGE_SIZE) break; + } + else + { + //used, return element pointer + nodeOffset_++; + printDebug(DM_Iterator,"ChunkID:%d Returning %x nodeOffset:%d", + chunkID_, data + sizeof(int), nodeOffset_); + return data + sizeof(int); + } + } + //go to next page and check till it exhausts + while(pageInfo->nextPage_ != NULL) + { + iterPage_ = pageInfo->nextPage_; + pageInfo = ((PageInfo*)iterPage_); + data = (char*)iterPage_ + sizeof(PageInfo); + nodeOffset_ = 0; + while(nodeOffset_ < noOfNodes_) + { + if (*((int*)data) == 0) + { + //not used, so skip it + data = data + allocSize_; + nodeOffset_++; + } + else + { + nodeOffset_++; + printDebug(DM_Iterator,"ChunkID:%d Returning %x Page:%x nodeOffset:%d", + chunkID_, data + sizeof(int), pageInfo, nodeOffset_); + return data +sizeof(int); + } + } + } + return NULL; +} diff --git a/src/storage/Condition.cxx b/src/storage/Condition.cxx new file mode 100644 index 00000000..0829db0e --- /dev/null +++ b/src/storage/Condition.cxx @@ -0,0 +1,62 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +Condition::Condition() +{ + //pred = new PredicateImpl(); + pred = NULL; +} +void Condition::reset() +{ + if (pred) {delete pred;} + pred = NULL; +} +Condition::~Condition() +{ + if (pred) delete pred; + pred = NULL; +} +void Condition::setTerm(const char* fName1, ComparisionOp op, + const char *fName2) +{ + if (pred) delete pred; + pred = new PredicateImpl(); + pred->setTerm(fName1, op, fName2); +} + +//Operand should be of the same type of the field.This is must +void Condition::setTerm(const char* fName1, ComparisionOp op, void *opnd) +{ + if (pred) delete pred; + pred = new PredicateImpl(); + pred->setTerm(fName1, op, opnd); +} + +void Condition::setTerm(const char* fName1, ComparisionOp op, void **opnd) +{ + if (pred) delete pred; + pred = new PredicateImpl(); + pred->setTerm(fName1, op, opnd); +} + +void Condition::setTerm(Predicate *p1, LogicalOp op, Predicate *p2 ) +{ + if (pred) delete pred; + pred = new PredicateImpl(); + pred->setTerm(p1, op, p2); +} diff --git a/src/storage/Config.cxx b/src/storage/Config.cxx new file mode 100644 index 00000000..05545c3f --- /dev/null +++ b/src/storage/Config.cxx @@ -0,0 +1,366 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include + +Config Conf::config; + +int Config::readLine(FILE *fp, char * buffer) +{ + char c =0; + int count =0; + while (true) + { + c = fgetc(fp); + if (c == '\n') break; + if (c == EOF) return EOF; + buffer[count++] = c; + } + return count; +} +int Config::storeKeyVal(char *key, char *value) +{ + if (strcasestr(key, "PAGE_SIZE") != NULL ) + { cVal.pageSize = atoi(value); } + else if (strcasestr(key, "MAX_PROCS") != NULL) + { cVal.maxProcs = atoi(value); } + else if (strcasestr(key, "MAX_SYS_DB_SIZE") != NULL) + { cVal.maxSysSize = atol(value); } + else if (strcasestr(key, "MAX_DB_SIZE") != NULL) + { cVal.maxDbSize = atol(value); } + else if (strcasestr(key, "SYS_DB_KEY") != NULL) + { cVal.sysDbKey = atoi(value); } + else if (strcasestr(key, "USER_DB_KEY") != NULL) + { cVal.userDbKey = atoi(value); } + else if (strcasestr(key, "LOG_FILE") != NULL) + { strcpy(cVal.logFile , value); } + else if (strcasestr(key, "DATABASE_FILE") != NULL) + { strcpy(cVal.dbFile , value); } + else if (strcasestr(key, "MAP_ADDRESS") != NULL) + { cVal.mapAddr = atol(value); } + else if (strcasestr(key, "MUTEX_TIMEOUT_SECS") != NULL) + { cVal.mutexSecs = atoi(value); } + else if (strcasestr(key, "MUTEX_TIMEOUT_USECS") != NULL) + { cVal.mutexUSecs = atoi(value); } + else if (strcasestr(key, "MUTEX_TIMEOUT_RETRIES") != NULL) + { cVal.mutexRetries = atoi(value); } + else if (strcasestr(key, "LOCK_TIMEOUT_SECS") != NULL) + { cVal.lockSecs = atoi(value); } + else if (strcasestr(key, "LOCK_TIMEOUT_USECS") != NULL) + { cVal.lockUSecs = atoi(value); } + else if (strcasestr(key, "LOCK_TIMEOUT_RETRIES") != NULL) + { cVal.lockRetries = atoi(value); } + else if (strcasestr(key, "DSN") != NULL) + { strcpy(cVal.dsn , value); } + else if (strcasestr(key, "TABLE_CONFIG_FILE") != NULL) + { strcpy(cVal.tableConfigFile , value); } + else if (strcasestr(key, "CACHE_TABLE") != NULL) + { cVal.isCache = os::atobool(value); } + else if (strcasestr(key, "REPLICATION") != NULL) + { cVal.isReplication = os::atobool(value); } + else if (strcasestr(key, "NETWORK_CONFIG_FILE") != NULL) + { strcpy(cVal.replConfigFile , value); } + else if (strcasestr(key, "MAX_LOG_STORE_SIZE") != NULL) + { cVal.logStoreSize = atol(value); } + else if (strcasestr(key, "MY_NETWORK_ID") != NULL) + { cVal.networkID = atoi(value); } + else if (strcasestr(key, "CACHE_NETWORK_ID") != NULL) + { cVal.cacheNetworkID = atoi(value); } + else if (strcasestr(key, "NETWORK_RESPONSE_TIMEOUT") != NULL) + { cVal.nwResponseTimeout = atoi(value); } + else if (strcasestr(key, "NETWORK_CONNECT_TIMEOUT") != NULL) + { cVal.nwConnectTimeout = atoi(value); } + else if (strcasestr(key, "ENABLE_BIDIRECTIONAL_CACHE") != NULL) + { cVal.isTwoWay = os::atobool(value); } + else if (strcasestr(key, "CACHE_RECEIVER_WAIT_SECS") != NULL) + { cVal.cacheWaitSecs = atoi(value); } + else return 1; + return 0; +} +int Config::validateValues() +{ + if (cVal.pageSize < 8192 || cVal.pageSize > 1024 * 1024 * 10 ) + { + printError(ErrBadArg, "PAGE_SIZE should be >= 8192 and <= 10 MB"); + return 1; + } + if (cVal.pageSize % 1024 !=0 ) + { + printError(ErrBadArg, "PAGE_SIZE should be multiples of 1024"); + return 1; + } + if (cVal.maxProcs < 10 || cVal.maxProcs > 8192) + { + printError(ErrBadArg, "MAX_PROCS should be >= 10 and <= 8192"); + return 1; + } + if (cVal.maxSysSize < 1024 * 1024 || cVal.maxSysSize > 1024 *1024 *1024) + { + printError(ErrBadArg, "MAX_SYS_DB_SIZE should be >= 1 MB and <= 1 GB"); + return 1; + } + if (cVal.maxSysSize % 8192 !=0 ) + { + printError(ErrBadArg, "MAX_SYS_DB_SIZE should be multiples of 8192"); + return 1; + } + + if (cVal.maxDbSize < 1024 * 1024 || cVal.maxDbSize > (1024*1024*1024)) + { + printError(ErrBadArg, "MAX_DB_SIZE should be >= 1 MB and <= 2 GB"); + return 1; + } + if (cVal.maxDbSize % 8192 !=0) + { + printError(ErrBadArg, "MAX_DB_SIZE should be multiples of 8192"); + return 1; + } + + if (cVal.sysDbKey < 10 || cVal.sysDbKey > 8192) + { + printError(ErrBadArg, "SYS_DB_KEY should be >= 10 and <= 8192"); + return 1; + } + if (cVal.userDbKey < 10 || cVal.userDbKey > 8192) + { + printError(ErrBadArg, "USER_DB_KEY should be >= 10 and <= 8192"); + return 1; + } + if ( cVal.sysDbKey == cVal.userDbKey) + { + printError(ErrBadArg, "USER_DB_KEY and SYS_DB_KEY have same value %d", cVal.userDbKey); + return 1; + } + if (0 == strcmp(cVal.logFile,"")) + { + //TODO::check whether file exists + printError(ErrBadArg, "LOG_FILE is set to NULL"); + return 1; + } + if (0 == strcmp(cVal.dbFile,"")) + { + printError(ErrBadArg, "LOG_FILE is set to NULL"); + return 1; + } + if (cVal.mapAddr < 400000000 || cVal.mapAddr > 2000000000) + { + printError(ErrBadArg, "MAP_ADDRESS should be >= 400000000 and <= 2000000000"); + return 1; + } + if (cVal.mutexSecs < 0 || cVal.mutexSecs > 360) + { + printError(ErrBadArg, "MUTEX_TIMEOUT_SECS should be >= 0 and <= 360"); + return 1; + } + if (cVal.mutexUSecs < 0 || cVal.mutexUSecs > 1000000) + { + printError(ErrBadArg, "MUTEX_TIMEOUT_USECS should be >= 0 and <= 1000000"); + return 1; + } + if (cVal.mutexRetries < 0 || cVal.mutexRetries > 100) + { + printError(ErrBadArg, "MUTEX_TIMEOUT_RETRY should be >= 0 and <= 100"); + return 1; + } + if (cVal.lockSecs < 0 || cVal.lockSecs > 360) + { + printError(ErrBadArg, "LOCK_TIMEOUT_SECS should be >= 0 and <= 360"); + return 1; + } + if (cVal.lockUSecs < 0 || cVal.lockUSecs > 1000000) + { + printError(ErrBadArg, "LOCK_TIMEOUT_USECS should be >= 0 and <= 1000000"); + return 1; + } + if (cVal.lockRetries < 0 || cVal.lockRetries > 100) + { + printError(ErrBadArg, "LOCK_TIMEOUT_RETRY should be >= 0 and <= 100"); + return 1; + } + if (cVal.isCache && cVal.isReplication) { + printError(ErrBadArg, "Either caching or replication option should be set." + " Both options are not supported together"); + return 1; + } + if (cVal.isCache) { + if (0 == strcmp(cVal.dsn,"")) + { + printError(ErrBadArg, "DSN is set to NULL"); + return 1; + } + } + if (cVal.isReplication || cVal.isCache) { + if (0 == strcmp(cVal.replConfigFile,"")) + { + //TODO::check whether file exists + printError(ErrBadArg, "NETWORK_CONFIG_FILE is set to NULL"); + return 1; + } + if (0 == strcmp(cVal.tableConfigFile,"")) + { + //TODO::check whether file exists + printError(ErrBadArg, "TABLE_CONFIG_FILE is set to NULL"); + return 1; + } + /*FILE *fp = fopen(cVal.replConfigFile,"r"); + if( fp == NULL ) { + printError(ErrSysInit, "Invalid path/filename for NETWORK_CONFIG_FILE.\n"); + return 1; + } + int count =0; + int nwid, port; + char hostname[IDENTIFIER_LENGTH]; + char nwmode; + + while(!feof(fp)) { + fscanf(fp, "%d:%d:%s\n", &nwid, &port, hostname); + count++; + } + if (count >2) { + printError(ErrSysInit, "NETWORK_CONFIG_FILE has more than 2 entries\n"); + return 1; + }*/ + + } + /*if (cVal.isCache) + { + + if (cVal.cacheNetworkID == -1) + { + printError(ErrBadArg, "CACHE_NETWORK_ID should not be -1"); + return 1; + }else { + FILE *fp; + int nwid; + char hostname[IDENTIFIER_LENGTH]; + char nwmode; + int port; + fp = fopen(Conf::config.getReplConfigFile(),"r"); + if( fp == NULL ) { + printError(ErrSysInit, "Invalid path/filename for NETWORK_CONFIG_FILE.\n"); + return 1; + } + bool found = false; + while(!feof(fp)) { + fscanf(fp, "%d:%d:%s\n", &nwid, &port, hostname); + if (cVal.cacheNetworkID == nwid) found = true; + } + if (!found) return 1; + } + }*/ + if (cVal.logStoreSize < 1024 * 1024 || cVal.logStoreSize > 1024 *1024 *1024) + { + printError(ErrBadArg, "MAX_LOG_STORE_SIZE should be >= 1 MB and <= 1 GB"); + return 1; + } + if (cVal.logStoreSize % 8192 !=0) + { + printError(ErrBadArg, "MAX_LOG_STORE_SIZE should be multiples of 8192"); + return 1; + } + if (cVal.nwResponseTimeout <0 || cVal.nwResponseTimeout > 60) + { + printError(ErrBadArg, "NETWORK_RESPONSE_TIMEOUT should be 0 to 60"); + return 1; + } + if (cVal.nwConnectTimeout <0 || cVal.nwConnectTimeout > 60) + { + printError(ErrBadArg, "NETWORK_CONNECT_TIMEOUT should be 0 to 60"); + return 1; + } + if (cVal.cacheWaitSecs <1) + { + printError(ErrBadArg, "CACHE_RECEIVER_WAIT_SECS should be >1"); + return 1; + } + return 0; +} + +int Config::readAllValues(char *fileName) +{ + FILE *fp; + + fp = fopen(fileName,"r"); + if( fp == NULL ) { + printError(ErrSysInit, "Invalid path/filename in CSQL_CONFIG_FILE."); + return 1; + } + + int hasData = 1; + char buffer[1024]; + char key[1024]; + char value[1024]; + while (hasData) + { + memset(buffer, 0, 1024); + //int ret = fscanf(fp,"%s\r",buffer); + int ret = readLine(fp, buffer); + if (ret == EOF) break; + bool isComment= false; + int posEqual =0; + for (int i = 0; i <1024; i++) + { + if (buffer[i] == '=' ) posEqual=i; + else if (buffer[i] == '#' ) { isComment = true; break; } + else if (buffer[i] == '\n') { break; } + else if (buffer[i] == '\0') { break; } + } + if (isComment) continue; + if (!posEqual) continue; + strncpy(key, buffer, posEqual); + key[posEqual] = '\0'; + posEqual++; + strcpy(value, &buffer[posEqual]); + storeKeyVal(key, value); + } + fclose(fp); + if (validateValues()) + { + return 1; + } + + return 0; +} +void Config::print() +{ + printf("ConfigValues\n"); + printf(" getPageSize %d\n", getPageSize()); + printf(" getMaxProcs %d\n", getMaxProcs()); + printf(" getMaxSysDbSize %ld\n", getMaxSysDbSize()); + printf(" getMaxDbSize %ld\n", getMaxDbSize()); + printf(" getSysDbKey %d\n", getSysDbKey()); + printf(" getUserDbKey %d\n", getUserDbKey()); + printf(" getLogFile %s\n", getLogFile()); + printf(" getDatabaseFile %s\n", getDbFile()); + printf(" getMapAddress %ld\n", getMapAddress()); + printf(" getMutexSecs %d\n", getMutexSecs()); + printf(" getMutexUSecs %d\n", getMutexUSecs()); + printf(" getMutexRetries %d\n", getMutexRetries()); + printf(" getLockSecs %d\n", getLockSecs()); + printf(" getLockUSecs %d\n", getLockUSecs()); + printf(" getLockRetries %d\n", getLockRetries()); + printf(" useCache %d\n", useCache()); + printf(" getDSN %s\n", getDSN()); + printf(" getTableConfigFile %s\n", getTableConfigFile()); + printf(" isTwoWayCache %d\n", useTwoWayCache()); + printf(" getCacheWaitSecs %d\n", getCacheWaitSecs()); + //printf(" useReplication %d\n", useReplication()); + //printf(" getReplConfigFile %s\n", getReplConfigFile()); + //printf(" getMaxLogStoreSize %ld\n", getMaxLogStoreSize()); + //printf(" getNetworkID %d\n", getNetworkID()); + //printf(" getCacheNetworkID %d\n", getCacheNetworkID()); +} diff --git a/src/storage/Connection.cxx b/src/storage/Connection.cxx new file mode 100644 index 00000000..b5ef9954 --- /dev/null +++ b/src/storage/Connection.cxx @@ -0,0 +1,97 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +Connection::~Connection() +{ + if (NULL != session) { + session->rollback(); + //session->close(); + delete session; + session = NULL; + } + Index::destroy(); +} + +DbRetVal Connection::open(const char *username, const char *password) +{ + if (username == NULL || password == NULL ) + { + printError(ErrBadArg, "Username or password should not be NULL\n"); + return ErrBadArg; + } + if (strlen(username) > 64 || strlen(password) >64) return ErrBadArg; + if (session == NULL) session = new SessionImpl(); + else + { + printError(ErrAlready, "User already logged in"); + return ErrAlready; + } + DbRetVal rv = session->open(username, password); + if (rv != OK) { delete session; session = NULL; return rv; } + rv = logger.startLogger(Conf::config.getLogFile()); + if (rv != OK) { delete session; session = NULL; return rv; } + logFinest(logger, "User logged in %s",username); + Index::init(); + return OK; +} + +DbRetVal Connection::close() +{ + if (session == NULL) return ErrNoConnection; + logFinest(logger, "User logged out"); + logger.stopLogger(); + session->rollback(); + delete session; // this inturn calls session->close + session = NULL; + return OK; +} + +DatabaseManager* Connection::getDatabaseManager() +{ + if (session == NULL) return NULL; + return session->getDatabaseManager(); +} + +UserManager* Connection::getUserManager() +{ + if (session == NULL) return NULL; + return session->getUserManager(); +} + +DbRetVal Connection::startTransaction(IsolationLevel level) +{ + if (session == NULL) return ErrNoConnection; + if (level == WRITE_OSYNC) level = READ_REPEATABLE; + return session->startTransaction(level); +} + + +DbRetVal Connection::commit() +{ + if (session == NULL) return ErrNoConnection; + return session->commit(); +} + + +DbRetVal Connection::rollback() +{ + if (session == NULL) return ErrNoConnection; + return session->rollback(); +} diff --git a/src/storage/DataType.cxx b/src/storage/DataType.cxx new file mode 100644 index 00000000..29807b55 --- /dev/null +++ b/src/storage/DataType.cxx @@ -0,0 +1,1717 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include + +#define SmallestValJulDate (1721426) + +Date::Date(int year, int month, int day) + { YMDToJulian(year, month, day, julianDate); } +int Date::set(int year, int month, int day) + { return YMDToJulian(year,month,day,julianDate); } +int Date::get(int &year, int &month, int &day) const + { return julianToYMD(julianDate,year,month,day); } + +int Date::parseFrom(const char *s) { + int month,day,year; + int count; + count = sscanf(s,"%d/%d/%d",&year,&month,&day); + if (count < 3) return -1; + + if (year < 100) year += 1900; + + if (!isValidDate(year, month, day)) + return -1; + return set(year,month,day); +} + +int Date::dayOfMonth() const { + int year, month, day; + get(year,month,day); + return day; +} +int Date::month() const { + int year, month, day; + get(year,month,day); + return month; +} +int Date::year() const { + int year, month, day; + get(year,month,day); + return year; +} + +int Date::dayOfWeek() const { return dayOfWeek(julianDate); } + +const char *Date::dayOfWeekName() const + { return dayOfWeekName(dayOfWeek(julianDate)); } + +const char *Date::dayOfWeekAbbr() const + { return dayOfWeekAbbr(dayOfWeek(julianDate)); } + +static const char *day_names[] = { + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" +}; +static const char *day_abbrs[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + +static const char *month_names[] = { + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December" +}; +static const char *month_abbrs[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + + +static int daysBeforeMonth[] = { +0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 +}; +static int days_per_month[] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +const char * Date::dayOfWeekName(int day) + { return (day < 1 || day > 7) ? 0 : day_names[day-1]; } + +const char * Date::dayOfWeekAbbr(int day) + { return (day < 1 || day > 7) ? 0 : day_abbrs[day-1]; } + +const char * Date::monthName() const { return monthName(month()); } +const char * Date::monthAbbr() const { return monthAbbr(month()); } +const char * Date::monthName(int month) + { return (month < 1 || month > 12) ? 0 : month_names[month-1]; } +const char * Date::monthAbbr(int month) + { return (month < 1 || month > 12) ? 0 : month_abbrs[month-1]; } +Date operator+(const Date &d1, int days) + { return Date(d1.julianDate + days); } +Date operator+(int days, const Date &d1) + { return Date(d1.julianDate + days); } +Date operator-(const Date &d1, int days) + { return Date(d1.julianDate - days); } + +int operator-(const Date &d1, const Date& d2) + { return d1.julianDate - d2.julianDate; } + +int operator<(const Date &d1 ,const Date &d2 ) + { return d1.julianDate < d2.julianDate; } +int operator>(const Date &d1 ,const Date &d2 ) + { return d1.julianDate > d2.julianDate; } +int operator<=(const Date &d1 ,const Date &d2 ) + { return d1.julianDate <= d2.julianDate; } +int operator>=(const Date &d1 ,const Date &d2 ) + { return d1.julianDate >= d2.julianDate; } +int operator==(const Date &d1 ,const Date &d2 ) + { return d1.julianDate == d2.julianDate; } +int operator!=(const Date &d1 ,const Date &d2 ) + { return d1.julianDate != d2.julianDate; } + +bool Date::isValid() const + { return julianDate >= SmallestValJulDate; } + +bool Date::isLeapYear(int year) +{ + return (year % 400 == 0) || ((year % 4 == 0) && !(year % 100 == 0)); +} + +int Date::dayOfYear() const { + int year,month,day; + get(year,month,day); + int tmp = daysBeforeMonth[month-1]; + if (month >= 3 && isLeapYear(year)) + tmp++; + return tmp + day; +} + +int Date::daysInMonth(int month, int year) { + --month; + int tmp = days_per_month[month]; + if (month == 1 && isLeapYear(year)) tmp++; + return tmp; +} + +bool Date::isValidDate(int year, int month, int day) { + if (year < 1 || year > 10000) return false; + if (month < 1 || month > 12) return false; + return (day >= 1) && (day <= daysInMonth(month,year)); +} + +// Algorithm Author: Robert G. Tantzen +int Date::YMDToJulian(int year, int mon, int day, JulianRep &jul) { + if (!isValidDate(year, mon, day)) + { jul = (JulianRep)0; return -1; } + + // year, month, day are assumed to be valid + int m = mon, d = day, y = year; + int c, ya, j; + + if (m > 2) m -= 3; + else { m += 9; --y; } + c = y/100; + ya = y - (100 * c); + j = (146097*c)/4 + (1461*ya)/4 + (153*m+2)/5 + d + 1721119; + jul = (JulianRep)j; + return 0; +} + +// Julian date converter. Takes a julian date (the number of days since some +// distant epoch or other), and returns month, day of month, and year in +// integer references. +// Algorithm Author: Robert G. Tantzen +int Date::dayOfWeek(JulianRep jul) { + return (int)((jul+1)%7+1); +} + +int Date::julianToYMD(JulianRep jul, int &year, int &month, int &day) { + int j = jul; + int d, m, y; + + if (j < SmallestValJulDate) + { year = month = day = 0; return -1; } + + j -= 1721119; + y = (4 * j - 1)/146097; + j = 4 * j - 1 - 146097 * y; + d = j/4; + j = (4 * d + 3)/1461; + d = 4 * d + 3 - 1461 * j; + d = (d + 4)/4; + m = (5 * d - 3)/153; + d = 5 * d - 3 - 153 * m; + d = (d + 5) / 5; + y = 100 * y + j; + if (m < 10) m += 3; + else { m -= 9; ++y; } + month = m; + day = d; + year = y; + return 0; +} + +#define MAX_VALID_SECONDS (60 * 60 * 24 -1) +Time::Time(int hours, int mins, int secs, int usec) + { set(hours,mins,secs, usec); } + +int Time::set(int hours, int mins, int secs, int usec) { + if((hours | mins | secs | usec) < 0) { timeVal = -1; return -1; } + if(hours >= 24 | mins >= 60 | secs >= 62) + { timeVal = -1; return -1; } + timeVal = secs + mins * 60 + hours * 3600; + timeVal *= 10000; + if(usec) timeVal += usec/100; + return 0; +} + +int Time::get(int &hours, int &mins, int &secs) const { + if (timeVal < 0) return -1; + int s = timeVal/10000; + secs = s % 60; + s /= 60; + mins = s % 60; + s /= 60; + hours = s; + return 0; +} + +int Time::seconds() const { return (timeVal/10000) % 60; } +int Time::minutes() const { return (timeVal /(60*10000)) % 60; } +int Time::hours() const { return timeVal / (3600*10000); } +int Time::msec() const { return (timeVal % 10000) / 10; } +int Time::usec() const { return (timeVal % 10000) * 100; } + +int Time::setMsec(int ms) { + if(ms < 0 || ms >= 1000) return -1; + timeVal = timeVal+(10*ms); + return 0; +} +int Time::setUsec(int us) { + if(us < 0 || us >= 1000000) return -1; + timeVal = timeVal +us/100; + return 0; +} + +bool Time::isValid() const + { return timeVal >= 0 && timeVal <= (10000*(MAX_VALID_SECONDS+1)-1); } + +bool Time::isValidTime(int hours, int mins, int secs) { + return (hours >= 0 && hours < 24) && + (mins >= 0 && mins < 60) && + (secs >= 0 && secs < 60); +} + +Time operator+(const Time &t1, int seconds) + { return Time(t1.timeVal + seconds*10000); } +Time operator+(int seconds, const Time &t1) + { return Time(t1.timeVal + seconds*10000); } +Time operator-(const Time &t1, int seconds) + { return Time(t1.timeVal - seconds*10000); } + +int operator-(const Time &t1, const Time& t2) + { return (t1.timeVal - t2.timeVal)/10000; } + +int operator<(const Time &t1 ,const Time &t2 ) + { return t1.timeVal < t2.timeVal; } +int operator>(const Time &t1 ,const Time &t2 ) + { return t1.timeVal > t2.timeVal; } +int operator<=(const Time &t1 ,const Time &t2 ) + { return t1.timeVal <= t2.timeVal; } +int operator>=(const Time &t1 ,const Time &t2 ) + { return t1.timeVal >= t2.timeVal; } +int operator==(const Time &t1 ,const Time &t2 ) + { return t1.timeVal == t2.timeVal; } +int operator!=(const Time &t1 ,const Time &t2 ) + { return t1.timeVal != t2.timeVal; } + +int Time::parseFrom(const char *s) { + int hours,mins,secs; + int count; + count = sscanf(s,"%d:%d:%d",&hours,&mins,&secs); + if (count < 2) return -1; + if (count == 2) secs = 0; + + if (!isValidTime(hours,mins,secs)) + return -1; + return set(hours,mins,secs); +} +int TimeStamp::parseFrom(const char *s) { + int hours,mins,secs; + int month,day,year; + int count; + count = sscanf(s,"%d/%d/%d %d:%d:%d",&year,&month,&day, &hours, &mins, &secs); + if (count < 5) return -1; + if (count == 5) secs = 0; + + if (year < 100) year += 1900; + + if (!date.isValidDate(year, month, day)) + return -1; + + setDate(year,month,day); + + + if (!time.isValidTime(hours,mins,secs)) + return -1; + return setTime(hours,mins,secs); +} + +int operator< (const TimeStamp &d1, const TimeStamp &d2) + { return (d1.date != d2.date) ? d1.date < d2.date : d1.time < d2.time; } +int operator> (const TimeStamp &d1, const TimeStamp &d2) + { return (d1.date != d2.date) ? d1.date > d2.date : d1.time > d2.time; } +int operator<=(const TimeStamp &d1, const TimeStamp &d2) + { return (d1.date != d2.date) ? d1.date < d2.date : d1.time <= d2.time; } +int operator>=(const TimeStamp &d1, const TimeStamp &d2) + { return (d1.date != d2.date) ? d1.date > d2.date : d1.time >= d2.time; } +int operator==(const TimeStamp &d1, const TimeStamp &d2) + { return d1.date == d2.date && d1.time == d2.time; } +int operator!=(const TimeStamp &d1, const TimeStamp &d2) + { return d1.date != d2.date && d1.time != d2.time; } + + +long AllDataType::size(DataType type, int length ) +{ + long size = 0; + switch(type) + { + case typeInt: + size = sizeof(int); + break; + case typeLong: + size = sizeof(long); + break; + case typeLongLong: + size = sizeof(long long); + break; + case typeShort: + size = sizeof(short); + break; + case typeByteInt: + size = sizeof(char); + break; + case typeDouble: + size = sizeof(double); + break; + case typeFloat: + size = sizeof(float); + break; + case typeDecimal: + //TODO::for porting + //fldDef.length_ = sizeof(long double); + break; + case typeDate: + size = sizeof(Date); + break; + case typeTime: + size = sizeof(Time); + break; + case typeTimeStamp: + size = sizeof(TimeStamp); + break; + case typeString: + case typeBinary: + size = length; + break; + default: + size = 0; + break; + } + return size; +} +char* AllDataType::getSQLString(DataType type) +{ + switch(type) + { + case typeInt: return "INT"; + case typeLong: return "INT"; + case typeLongLong: return "BIGINT"; + case typeShort: return "SMALLINT"; + case typeByteInt: return "TINYINT"; + case typeDouble: return "REAL"; + case typeFloat: return "FLOAT"; + case typeDate: return "DATE"; + case typeTime: return "TIME"; + case typeTimeStamp: return "TIMESTAMP"; + case typeString: return "CHAR"; + case typeBinary: return "BINARY"; + default: return "UNKNOWN"; + } +} + + +SQLSMALLINT AllDataType::convertToSQLType(DataType type) +{ + switch(type) + { + case typeInt: + return SQL_INTEGER; + case typeLong: + return SQL_INTEGER; + case typeLongLong: + //TODO + return SQL_INTEGER; + case typeShort: + return SQL_SMALLINT; + case typeByteInt: + //TODO + return SQL_INTEGER; + case typeDouble: + return SQL_DOUBLE; + case typeFloat: + return SQL_REAL; + case typeDecimal: + //TODO + return SQL_INTEGER; + case typeDate: + return SQL_TYPE_DATE; + case typeTime: + return SQL_TYPE_TIME; + case typeTimeStamp: + return SQL_TYPE_TIMESTAMP; + case typeString: + return SQL_CHAR; + case typeBinary: + return SQL_BINARY; + } + return SQL_INTEGER; +} +SQLSMALLINT AllDataType::convertToSQL_C_Type(DataType type) +{ + switch(type) + { + case typeInt: + return SQL_C_SLONG; + case typeLong: + return SQL_C_SLONG; + case typeLongLong: + return SQL_C_SBIGINT; + case typeShort: + return SQL_C_SSHORT; + case typeByteInt: + return SQL_C_STINYINT; + case typeDouble: + return SQL_C_DOUBLE; + case typeFloat: + return SQL_C_FLOAT; + case typeDecimal: + //TODO + return SQL_INTEGER; + case typeDate: + return SQL_C_TYPE_DATE; + case typeTime: + return SQL_C_TYPE_TIME; + case typeTimeStamp: + return SQL_C_TYPE_TIMESTAMP; + case typeString: + return SQL_C_CHAR; + case typeBinary: + return SQL_C_BINARY; + } + return SQL_C_SLONG; +} + +DataType AllDataType::convertFromSQLType(SQLSMALLINT type) +{ + switch(type) + { + case SQL_INTEGER : + return typeInt; + case SQL_SMALLINT: + return typeShort; + case SQL_DOUBLE: + return typeDouble; + case SQL_FLOAT: + case SQL_REAL: + return typeFloat; + case SQL_TYPE_DATE: + return typeDate; + case SQL_TYPE_TIME : + return typeTime; + case SQL_TYPE_TIMESTAMP : + return typeTimeStamp; + case SQL_CHAR: + return typeString; + case SQL_VARCHAR: + return typeString; + case SQL_BINARY: + return typeBinary; + } + return typeInt; +} +void AllDataType::copyVal(void* dest, void *src, DataType type, int length) +{ + switch(type) + { + case typeInt: + *(int*)dest = *(int*)src; + break; + case typeLong: + *(long*)dest = *(long*)src; + break; + case typeLongLong: + *(long long*)dest = *(long long*)src; + break; + case typeShort: + *(short*)dest = *(short*)src; + break; + case typeByteInt: + *(char*)dest = *(char*)src; + break; + case typeDouble: + *(double*)dest = *(double*)src; + break; + case typeFloat: + *(float*)dest = *(float*)src; + break; + case typeDecimal: + //TODO::for porting + case typeDate: + *(Date*)dest = *(Date*)src; + break; + case typeTime: + *(Time*)dest = *(Time*)src; + break; + case typeTimeStamp: + *(TimeStamp*)dest = *(TimeStamp*)src; + break; + case typeString: + { + strncpy((char*)dest, (char*)src, length); + char *d =(char*)dest; + d[length-1] = '\0'; + break; + } + case typeBinary: + os::memcpy(dest, src, length); + break; + default: + break; + } +} +void AllDataType::addVal(void* dest, void *src, DataType type) +{ + switch(type) + { + case typeInt: + *(int*)dest = *(int*)dest + *(int*)src; + break; + case typeLong: + *(long*)dest = *(long*)dest + *(long*)src; + break; + case typeLongLong: + *(long long*)dest = *(long long*)dest + *(long long*)src; + break; + case typeShort: + *(short*)dest = *(short*)dest + *(short*)src; + break; + case typeByteInt: + *(char*)dest = *(char*)dest + *(char*)src; + break; + case typeDouble: + *(double*)dest = *(double*)dest + *(double*)src; + break; + case typeFloat: + *(float*)dest = *(float*)dest + *(float*)src; + break; + case typeDecimal: + //TODO::for porting + case typeDate: + case typeTime: + case typeTimeStamp: + case typeBinary: + default: + break; + } + return; +} + +void AllDataType::divVal(void* dest, int src, DataType type) +{ + switch(type) + { + case typeInt: + *(int*)dest = *(int*)dest / src; + break; + case typeLong: + *(long*)dest = *(long*)dest / src; + break; + case typeLongLong: + *(long long*)dest = *(long long*)dest / src; + break; + case typeShort: + *(short*)dest = *(short*)dest / src; + break; + case typeByteInt: + *(char*)dest = *(char*)dest / src; + break; + case typeDouble: + *(double*)dest = *(double*)dest / src; + break; + case typeFloat: + *(float*)dest = *(float*)dest / src; + break; + case typeDecimal: + //TODO::for porting + case typeDate: + case typeTime: + case typeTimeStamp: + case typeBinary: + default: + break; + } + return; +} + + + + +bool AllDataType::compareVal(void *val1, void *val2, ComparisionOp op, + DataType type, long length) +{ + bool result = false; + switch(type) + { + case typeInt: + result = AllDataType::compareIntVal(val1, val2, op ); + break; + case typeLong: + result = AllDataType::compareLongVal(val1, val2, op); + break; + case typeLongLong: + result = AllDataType::compareLongLongVal(val1, val2, op); + break; + case typeShort: + result = AllDataType::compareShortVal(val1, val2, op); + break; + case typeByteInt: + result = AllDataType::compareByteIntVal(val1, val2, op); + break; + case typeDouble: + result = AllDataType::compareDoubleVal(val1, val2, op); + break; + case typeFloat: + result = AllDataType::compareFloatVal(val1, val2, op); + break; + case typeDecimal: + //TODO::for porting + break; + case typeDate: + result = AllDataType::compareDateVal(val1, val2, op); + break; + case typeTime: + result = AllDataType::compareTimeVal(val1, val2, op); + break; + case typeTimeStamp: + result = AllDataType::compareTimeStampVal(val1, val2, op); + break; + case typeString: + result = AllDataType::compareStringVal(val1, val2, op); + break; + case typeComposite: + case typeBinary: + result = AllDataType::compareBinaryVal(val1, val2, op, length); + break; + } + return result; +} + +bool AllDataType::compareIntVal(void* src1, void *src2, ComparisionOp op) +{ + if (src1 == NULL) printf("src1 is null\n"); + if (src2 == NULL) printf("src2 is null\n"); + bool result = false; + switch(op) + { + case OpEquals: + if (*(int*)src1 == *(int*)src2) result = true; + else result = false; + break; + case OpNotEquals: + if (*(int*)src1 != *(int*)src2) result = true; + else result = false; + break; + case OpLessThan: + if (*(int*)src1 < *(int*)src2) result = true; + else result = false; + break; + case OpLessThanEquals: + if (*(int*)src1 <= *(int*)src2) result = true; + else result = false; + break; + case OpGreaterThan: + if (*(int*)src1 > *(int*)src2) result = true; + else result = false; + break; + case OpGreaterThanEquals: + if (*(int*)src1 >= *(int*)src2) result = true; + else result = false; + break; + } + return result; +} + +bool AllDataType::compareLongVal(void* src1, void *src2, ComparisionOp op) +{ + bool result = false; + switch(op) + { + case OpEquals: + if (*(long*)src1 == *(long*)src2) result = true; + else result = false; + break; + case OpNotEquals: + if (*(long*)src1 != *(long*)src2) result = true; + else result = false; + break; + case OpLessThan: + if (*(long*)src1 < *(long*)src2) result = true; + else result = false; + break; + case OpLessThanEquals: + if (*(long*)src1 <= *(long*)src2) result = true; + else result = false; + break; + case OpGreaterThan: + if (*(long*)src1 > *(long*)src2) result = true; + else result = false; + break; + case OpGreaterThanEquals: + if (*(long*)src1 >= *(long*)src2) result = true; + else result = false; + break; + } + return result; +} + +bool AllDataType::compareLongLongVal(void* src1, void *src2, + ComparisionOp op) +{ + bool result = false; + switch(op) + { + case OpEquals: + if (*(long long*)src1 == *(long long*)src2) result = true; + else result = false; + break; + case OpNotEquals: + if (*(long long*)src1 != *(long long*)src2) result = true; + else result = false; + break; + case OpLessThan: + if (*(long long*)src1 < *(long long*)src2) result = true; + else result = false; + break; + case OpLessThanEquals: + if (*(long long*)src1 <= *(long long*)src2) result = true; + else result = false; + break; + case OpGreaterThan: + if (*(long long*)src1 > *(long long*)src2) result = true; + else result = false; + break; + case OpGreaterThanEquals: + if (*(long long*)src1 >= *(long long*)src2) result = true; + else result = false; + break; + } + return result; +} + +bool AllDataType::compareShortVal(void* src1, void *src2, ComparisionOp op) +{ + bool result = false; + switch(op) + { + case OpEquals: + if (*(short*)src1 == *(short*)src2) result = true; + else result = false; + break; + case OpNotEquals: + if (*(short*)src1 != *(short*)src2) result = true; + else result = false; + break; + case OpLessThan: + if (*(short*)src1 < *(short*)src2) result = true; + else result = false; + break; + case OpLessThanEquals: + if (*(short*)src1 <= *(short*)src2) result = true; + else result = false; + break; + case OpGreaterThan: + if (*(short*)src1 > *(short*)src2) result = true; + else result = false; + break; + case OpGreaterThanEquals: + if (*(short*)src1 >= *(short*)src2) result = true; + else result = false; + break; + } + return result; +} + +bool AllDataType::compareByteIntVal(void* src1, void *src2, ComparisionOp op) +{ + bool result = false; + switch(op) + { + case OpEquals: + if (*(ByteInt*)src1 == *(ByteInt*)src2) result = true; + else result = false; + break; + case OpNotEquals: + if (*(ByteInt*)src1 != *(ByteInt*)src2) result = true; + else result = false; + break; + case OpLessThan: + if (*(ByteInt*)src1 < *(ByteInt*)src2) result = true; + else result = false; + break; + case OpLessThanEquals: + if (*(ByteInt*)src1 <= *(ByteInt*)src2) result = true; + else result = false; + break; + case OpGreaterThan: + if (*(ByteInt*)src1 > *(ByteInt*)src2) result = true; + else result = false; + break; + case OpGreaterThanEquals: + if (*(ByteInt*)src1 >= *(ByteInt*)src2) result = true; + else result = false; + break; + } + return result; +} + +bool AllDataType::compareDoubleVal(void* src1, void *src2, ComparisionOp op) +{ + bool result = false; + switch(op) + { + case OpEquals: + if (*(double*)src1 == *(double*)src2) result = true; + else result = false; + break; + case OpNotEquals: + if (*(double*)src1 != *(double*)src2) result = true; + else result = false; + break; + case OpLessThan: + if (*(double*)src1 < *(double*)src2) result = true; + else result = false; + break; + case OpLessThanEquals: + if (*(double*)src1 <= *(double*)src2) result = true; + else result = false; + break; + case OpGreaterThan: + if (*(double*)src1 > *(double*)src2) result = true; + else result = false; + break; + case OpGreaterThanEquals: + if (*(double*)src1 >= *(double*)src2) result = true; + else result = false; + break; + } + return result; +} + +bool AllDataType::compareFloatVal(void* src1, void *src2, ComparisionOp op) +{ + bool result = false; + switch(op) + { + case OpEquals: + if (*(float*)src1 == *(float*)src2) result = true; + else result = false; + break; + case OpNotEquals: + if (*(float*)src1 != *(float*)src2) result = true; + else result = false; + break; + case OpLessThan: + if (*(float*)src1 < *(float*)src2) result = true; + else result = false; + break; + case OpLessThanEquals: + if (*(float*)src1 <= *(float*)src2) result = true; + else result = false; + break; + case OpGreaterThan: + if (*(float*)src1 > *(float*)src2) result = true; + else result = false; + break; + case OpGreaterThanEquals: + if (*(float*)src1 >= *(float*)src2) result = true; + else result = false; + break; + } + return result; +} + +bool AllDataType::compareDateVal(void* src1, void *src2, ComparisionOp op) +{ + bool result = false; + switch(op) + { + case OpEquals: + if (*(Date*)src1 == *(Date*)src2) result = true; + else result = false; + break; + case OpNotEquals: + if (*(Date*)src1 != *(Date*)src2) result = true; + else result = false; + break; + case OpLessThan: + if (*(Date*)src1 < *(Date*)src2) result = true; + else result = false; + break; + case OpLessThanEquals: + if (*(Date*)src1 <= *(Date*)src2) result = true; + else result = false; + break; + case OpGreaterThan: + if (*(Date*)src1 > *(Date*)src2) result = true; + else result = false; + break; + case OpGreaterThanEquals: + if (*(Date*)src1 >= *(Date*)src2) result = true; + else result = false; + break; + } + return result; +} + +bool AllDataType::compareTimeVal(void* src1, void *src2, ComparisionOp op) +{ + bool result = false; + switch(op) + { + case OpEquals: + if (*(Time*)src1 == *(Time*)src2) result = true; + else result = false; + break; + case OpNotEquals: + if (*(Time*)src1 != *(Time*)src2) result = true; + else result = false; + break; + case OpLessThan: + if (*(Time*)src1 < *(Time*)src2) result = true; + else result = false; + break; + case OpLessThanEquals: + if (*(Time*)src1 <= *(Time*)src2) result = true; + else result = false; + break; + case OpGreaterThan: + if (*(Time*)src1 > *(Time*)src2) result = true; + else result = false; + break; + case OpGreaterThanEquals: + if (*(Time*)src1 >= *(Time*)src2) result = true; + else result = false; + break; + } + return result; +} + +bool AllDataType::compareTimeStampVal(void* src1, void *src2, ComparisionOp op) +{ + bool result = false; + switch(op) + { + case OpEquals: + if (*(TimeStamp*)src1 == *(TimeStamp*)src2) result = true; + else result = false; + break; + case OpNotEquals: + if (*(TimeStamp*)src1 != *(TimeStamp*)src2) result = true; + else result = false; + break; + case OpLessThan: + if (*(TimeStamp*)src1 < *(TimeStamp*)src2) result = true; + else result = false; + break; + case OpLessThanEquals: + if (*(TimeStamp*)src1 <= *(TimeStamp*)src2) result = true; + else result = false; + break; + case OpGreaterThan: + if (*(TimeStamp*)src1 > *(TimeStamp*)src2) result = true; + else result = false; + break; + case OpGreaterThanEquals: + if (*(TimeStamp*)src1 >= *(TimeStamp*)src2) result = true; + else result = false; + break; + } + return result; +} + +bool AllDataType::compareStringVal(void* src1, void *src2, ComparisionOp op) +{ + bool result = false; + int ret = strcmp((char*)src1, (char*)src2); + switch(op) + { + case OpEquals: + if (ret == 0 ) result= true; else result = false; + break; + case OpNotEquals: + if (ret != 0 ) result= true; else result = false; + break; + case OpLessThan: + if (ret < 0 ) result= true; else result = false; + break; + case OpLessThanEquals: + printf("Illegal Operator:Not Supported for String\n"); + break; + case OpGreaterThan: + if (ret > 0 ) result= true; else result = false; + break; + case OpGreaterThanEquals: + printf("Illegal Operator:Not Supported for String\n"); + break; + } + return result; +} + +bool AllDataType::compareBinaryVal(void* src1, void *src2, + ComparisionOp op, int length) +{ + bool result = false; + int ret = os::memcmp(src1, src2, length); + switch(op) + { + case OpEquals: + if (ret == 0 ) result= true; else result = false; + break; + case OpNotEquals: + if (ret != 0 ) result= true; else result = false; + break; + case OpLessThan: + if (ret < 0 ) result= true; else result = false; + break; + case OpLessThanEquals: + printf("Illegal Operator:Not Supported for Binary\n"); + break; + case OpGreaterThan: + if (ret > 0 ) result= true; else result = false; + break; + case OpGreaterThanEquals: + printf("Illegal Operator:Not Supported for Binary\n"); + break; + } + return result; +} + + + +ComparisionOp AllDataType::getComparisionOperator(char *str) +{ + ComparisionOp op; + if (strcmp(str, "<=") == 0) + op = OpLessThanEquals; + else if (strcmp(str, ">=") == 0) + op = OpGreaterThanEquals; + else if (strcmp(str, "<") == 0) + op = OpLessThan; + else if (strcmp(str, ">") == 0) + op = OpGreaterThan; + else if (strcmp(str, "=") == 0) + op = OpEquals; + else if (strcmp(str, "!=") == 0 || strcmp(str, "<>") == 0 ) + op = OpNotEquals; + else if (strcasecmp(str, "LIKE") == 0 ) + op = OpLike; + else + op = OpInvalidComparisionOp; + return op; +} + +void* AllDataType::alloc(DataType type, int length) +{ + void *dest; + switch(type) + { + case typeInt: + dest = malloc(sizeof(int)); + break; + case typeLong: + dest = malloc(sizeof(long)); + break; + case typeLongLong: + dest = malloc(sizeof(long long)); + break; + case typeShort: + dest = malloc(sizeof(short)); + break; + case typeByteInt: + dest = malloc(sizeof(char)); + break; + case typeDouble: + dest = malloc(sizeof(double)); + break; + case typeFloat: + dest = malloc(sizeof(float)); + break; + case typeDecimal: + //TODO::for porting + //fldDef.length_ = sizeof(long double); + break; + case typeString: + if (length == 0 ) return NULL; + dest = malloc(length); + break; + case typeBinary: + if (length == 0 || length > 256 ) return NULL; + dest = malloc(length); + memset(dest, 0, length); + break; + case typeDate: + dest = malloc(sizeof(Date)); + break; + case typeTime: + dest = malloc(sizeof(Time)); + break; + case typeTimeStamp: + dest = malloc(sizeof(TimeStamp)); + break; + } + return dest; +} +DbRetVal AllDataType::strToValue(void* dest, char *src, DataType type, int length) +{ + switch(type) + { + case typeInt: { + int val; + sscanf( src, "%d", &val); + *(int*)dest = val; + break; } + case typeLong: { + long val; + sscanf( src, "%ld", &val); + *(long*)dest = val; + break; } + case typeLongLong: { + long long val; + sscanf( src, "%lld", &val); + *(long long*)dest = val; + break; } + case typeShort: { + short val; + sscanf( src, "%hd", &val); + *(short*)dest = val; + break; } + case typeByteInt: { + char val; + sscanf( src, "%c", &val); + *(char*)dest = val; + break; } + case typeDouble: { + double val; + sscanf( src, "%lg", &val); + *(double*)dest = val; + break; } + case typeFloat: { + float val; + sscanf( src, "%f", &val); + *(float*)dest = val; + break; } + case typeDecimal: + //TODO::for porting + case typeString: { + strncpy((char*)dest, (char*)src, length); + char *d =(char*)dest; + d[length-1] = '\0'; + break;} + case typeDate: { + int d,m,y,res=0; + res = sscanf( src, "%d-%d-%d", &y, &m, &d ); + if( res != 3 ) + res = sscanf( src, "%d/%d/%d", &y, &m, &d ); + if( res != 3 ) + { + fprintf(stderr,"Error reading date. yyyy{-/}mm{-/}dd is the valid format."); + d=m=y=0; + } + Date dateObj(y,m,d); + *(Date*)dest = dateObj; + break; } + case typeTime: { + int h,m,s,res=0; + res = sscanf( src, "%d:%d:%d", &h, &m, &s ); + if( res != 3 ) + { + fprintf(stderr, "Error reading time, hh:mm:ss is the valid format."); + h=m=s=0; + } + Time timeObj(h,m,s); + *(Time*)dest = timeObj; + break; } + case typeTimeStamp: { + int d,m,y, h,mn,s, res=0; + res = sscanf( src, "%d-%d-%d %d:%d:%d", &y, &m, &d, &h, &mn, &s ); + if( res != 6 ) + res = sscanf( src, "%d-%d-%d, %d:%d:%d", &y, &m, &d, &h, &mn, &s ); + if( res != 6 ) + res = sscanf( src, "%d/%d/%d %d:%d:%d", &y, &m, &d, &h, &mn, &s ); + if( res != 6 ) + res = sscanf( src, "%d/%d/%d, %d:%d:%d", &y, &m, &d, &h, &mn, &s ); + if( res != 6 ) + { + fprintf(stderr, "Error reading timestamp, yyyy{-/}mm{-/}dd[,] hh:mm:ss is the valid format."); + d=m=y=h=mn=s=0; + } + TimeStamp timeStampObj(y,m,d,h,mn,s); + *(TimeStamp*)dest = timeStampObj; + break; } + case typeBinary: { + memset ((void *) dest, 0, length * 2); + unsigned char c = 0; + const char *str = (const char *)src; + unsigned char *val = (unsigned char *)dest; + int i = 0; + while (i < length * 2) { + c = *str++; i++; + if (c == '\0') { *val = *val | c; break; } + if (!isxdigit((int)c)) { + printError(ErrBadArg, "Invalid hexadecimal value"); + return ErrBadArg; + } + if (c <= '9') c -= '0'; + else if (c >= 'a') c = c - 'a' + 10; + else c = c - 'A' + 10; + if (i % 2) { *val = c; *val <<= 4; } + else { *val = *val | c; val++; } + } + break; + } + default: + break; + } + return OK; +} + + +void AllDataType::convert(DataType srcType, void *src, + DataType destType, void *dest, int length) +{ + switch ((DataType) destType ) + { + case typeInt: convertToInt(dest, src, srcType); break; + case typeLong: convertToLong(dest, src, srcType); break; + case typeLongLong: convertToLongLong(dest, src, srcType); break; + case typeShort: convertToShort(dest, src, srcType); break; + case typeByteInt: convertToByteInt(dest, src, srcType); break; + + case typeFloat: convertToFloat(dest, src, srcType); break; + case typeDouble: convertToDouble(dest, src, srcType); break; + + //TODO + case typeDecimal: convertToDouble(dest, src, srcType); break; + + case typeString: convertToString(dest, src, srcType); break; + case typeBinary: convertToBinary(dest, src, srcType,length); break; + case typeDate: convertToDate(dest, src, srcType); break; + case typeTime: convertToTime(dest, src, srcType); break; + case typeTimeStamp: convertToTimeStamp(dest, src, srcType); break; + default: return; + } +} + +void AllDataType::convertToInt( void* dest, void* src, DataType srcType ) +{ + switch(srcType) + { + case typeInt: *(int *)dest = *(int *)src; break; + case typeLong: *(int *)dest =(int) *(long *)src; break; + case typeLongLong: *(int *)dest =(int) *(long long *)src; break; + case typeShort: *(int *)dest =(int) *(short *)src; break; + case typeByteInt: *(int *)dest =(int) *(char *)src; break; + + case typeFloat: *(int *)dest = (int) *(float *)src; break; + case typeDouble: *(int *)dest =(int) *(double *)src; break; + + case typeString: sscanf((const char*)src, "%d", (int*) dest); break; + + case typeDate: + case typeTime: + case typeTimeStamp: + case typeBinary: + default: *(int *)dest = (int) 0; + } +} + +void AllDataType::convertToLong( void* dest, void* src, DataType srcType ) +{ + switch(srcType) + { + case typeInt: *(long *)dest =(long) *(int *)src; break; + case typeLong: *(long *)dest = *(long *)src; break; + case typeLongLong: *(long *)dest =(long) *(long long *)src; break; + case typeShort: *(long *)dest =(long) *(short *)src; break; + case typeByteInt: *(long *)dest =(long) *(char *)src; break; + + case typeFloat: *(long *)dest = (long) *(float *)src; break; + case typeDouble: *(long *)dest =(long) *(double *)src; break; + + case typeString: sscanf((const char*)src, "%ld", (long*) dest); break; + + case typeDate: + case typeTime: + case typeTimeStamp: + case typeBinary: + default: *(long *)dest = (long) 0; + } +} + + +void AllDataType::convertToLongLong( void* dest, void* src, DataType srcType ) +{ + switch(srcType) + { + case typeInt: *(long long *)dest =(long long) *(int *)src; break; + case typeLong: *(long long *)dest = (long long) *(long *)src; break; + case typeLongLong: *(long long *)dest = *(long long *)src; break; + case typeShort: *(long long *)dest =(long long) *(short *)src; break; + case typeByteInt: *(long long *)dest =(long long) *(char *)src; break; + + case typeFloat: *(long long *)dest = (long long) *(float *)src; break; + case typeDouble: *(long long *)dest =(long long) *(double *)src; break; + + case typeString: sscanf((const char*)src, "%lld", (long long*) dest); break; + + case typeDate: + case typeTime: + case typeTimeStamp: + case typeBinary: + default: *(long long *)dest = (long long) 0; + } +} + +void AllDataType::convertToShort( void* dest, void* src, DataType srcType ) +{ + switch(srcType) + { + case typeInt: *(short*)dest =(short) *(int*)src; break; + case typeLong: *(short*)dest = (short) *(long*)src; break; + case typeLongLong: *(short*)dest = (short) *(long long*)src; break; + case typeShort: *(short*)dest = *(short*)src; break; + case typeByteInt: *(short*)dest =(short) *(char *)src; break; + + case typeFloat: *(short*)dest = (short) *(float *)src; break; + case typeDouble: *(short*)dest =(short) *(double *)src; break; + + case typeString: sscanf((const char*)src, "%hd", (short*) dest); break; + + case typeDate: + case typeTime: + case typeTimeStamp: + case typeBinary: + default: *(short*)dest = (short) 0; + } +} + +void AllDataType::convertToByteInt( void* dest, void* src, DataType srcType ) +{ + switch(srcType) + { + case typeInt: *(char*)dest = (char) *(int*)src; break; + case typeLong: *(char*)dest = (char) *(long*)src; break; + case typeLongLong: *(char*)dest = (char) *(long long*)src; break; + case typeShort: *(char*)dest = (char) *(short*)src; break; + case typeByteInt: *(char*)dest = *(char *)src; break; + + case typeFloat: *(char*)dest = (char) *(float *)src; break; + case typeDouble: *(char*)dest =(char) *(double *)src; break; + + case typeString: sscanf((const char*)src, "%c", (char*) dest); break; + + case typeDate: + case typeTime: + case typeTimeStamp: + case typeBinary: + default: *(char*)dest = (char) 0; + } +} + +void AllDataType::convertToFloat( void* dest, void* src, DataType srcType ) +{ + switch(srcType) + { + case typeInt: *(float *)dest =(float) *(int *)src; break; + case typeLong: *(float *)dest =(float) *(long *)src; break; + case typeLongLong: *(float *)dest =(float) *(long long *)src; break; + case typeShort: *(float *)dest =(float) *(short *)src; break; + case typeByteInt: *(float *)dest =(float) *(char *)src; break; + + case typeFloat: *(float *)dest = *(float *)src; break; + case typeDouble: *(float *)dest =(float) *(double *)src; break; + + case typeString: sscanf((const char*)src, "%f", (float*) dest); break; + + case typeDate: + case typeTime: + case typeTimeStamp: + case typeBinary: + default: *(float *)dest = (float) 0; + } +} + +void AllDataType::convertToDouble( void* dest, void* src, DataType srcType ) +{ + switch(srcType) + { + case typeInt: *(double *)dest =(double) *(int *)src; break; + case typeLong: *(double *)dest =(double) *(long *)src; break; + case typeLongLong: *(double *)dest =(double) *(long long *)src; break; + case typeShort: *(double *)dest =(double) *(short *)src; break; + case typeByteInt: *(double *)dest =(double) *(char *)src; break; + + case typeFloat: *(double *)dest =(double) *(float *)src; break; + case typeDouble: *(double *)dest = *(double *)src; break; + + case typeString: sscanf((const char*)src, "%lf", (double*) dest); break; + + case typeDate: + case typeTime: + case typeTimeStamp: + case typeBinary: + default: *(double *)dest = (double) 0; + } +} + +void AllDataType::convertToString( void* dest, void* src, DataType srcType, int length ) +{ + switch(srcType) + { + case typeInt: + { + sprintf ((char *)dest, "%d", *(int *)src); + break; + } + case typeLong: + { + sprintf ((char *)dest, "%ld", *(long *)src); + break; + } + case typeLongLong: + { + sprintf ((char *)dest, "%lld", *(long long *)src); + break; + } + case typeShort: + { + sprintf ((char *)dest, "%hd", *(short *)src); + break; + } + case typeByteInt: + { + sprintf ((char *)dest, "%hd", *(char *)src); + break; + } + + case typeFloat: + { + sprintf ((char *)dest, "%f", *(float *)src); + break; + } + case typeDouble: + { + sprintf ((char *) dest, "%lf", *(double *)src); + break; + } + + case typeString: + { + strcpy((char*)dest, (char*)src); + break; + } + case typeDate: + { + Date* dt = (Date*)src; + sprintf((char*) dest, "%d/%d/%d", dt->year(), + dt->month(), dt->dayOfMonth()); + break; + } + case typeTime: + { + Time* tm = (Time*)src; + sprintf((char*)dest,"%d:%d:%d.%d", tm->hours(), tm->minutes(), tm->seconds(), 0); + break; + } + case typeTimeStamp: + { + TimeStamp* tm = (TimeStamp*)src; + sprintf((char*)dest, "%d/%d/%d %d:%d:%d.%d", tm->year(), + tm->month(), tm->dayOfMonth(), tm->hours(), + tm->minutes(), tm->seconds(), 0 ); + break; + } + case typeBinary: + { + unsigned char *c = (unsigned char *) src; + unsigned char *str = (unsigned char *) dest; + unsigned char p = 0; + int i = 0; + while (i < length) { + p = *c >> 4; + if (p < 10) sprintf ((char *)str++, "%c", '0' + p); + else sprintf((char *)str++, "%c", 'A' + p - 10); + p = *c & 0xF; + if (p < 10) sprintf ((char *)str++, "%c", '0' + p); + else sprintf((char *)str++, "%c", 'A' + p - 10); + i++; c++; + } + break; + } + + default: ((char*)dest)[0] = '\0'; + } + +} +void AllDataType::convertToDate( void* dest, void* src, DataType srcType ) +{ + switch(srcType) + { + case typeInt: + case typeLong: + case typeLongLong: + case typeShort: + case typeByteInt: + case typeFloat: + case typeDouble: + case typeDate: + case typeTime: + case typeTimeStamp: + case typeString: + { + Date *dt = (Date*) dest; + dt->parseFrom((char*)src); + break; + } + default: ((char*)dest)[0] = '\0'; + } +} + +void AllDataType::convertToTime( void* dest, void* src, DataType srcType ) +{ + switch(srcType) + { + case typeInt: + case typeLong: + case typeLongLong: + case typeShort: + case typeByteInt: + case typeFloat: + case typeDouble: + case typeDate: + case typeTime: + case typeTimeStamp: + case typeString: + { + Time *dt = (Time*) dest; + dt->parseFrom((char*)src); + break; + } + default: ((char*)dest)[0] = '\0'; + } +} + +void AllDataType::convertToTimeStamp( void* dest, void* src, DataType srcType ) +{ + switch(srcType) + { + case typeInt: + case typeLong: + case typeLongLong: + case typeShort: + case typeByteInt: + case typeFloat: + case typeDouble: + case typeDate: + case typeTime: + case typeTimeStamp: + case typeString: + { + TimeStamp *dt = (TimeStamp*) dest; + dt->parseFrom((char*)src); + break; + } + default: ((char*)dest)[0] = '\0'; + } +} + +void AllDataType::convertToBinary(void *dest, void *src, DataType srcType, int length) +{ + switch(srcType) + { + case typeString: + { + unsigned char c = 0; + const char *str = (const char *)src; + unsigned char *val = (unsigned char *)dest; + int i = 0; + while (i < length * 2) { + c = *str++; i++; + if (c == '\0') { *val = *val | c; break; } + if (c <= '9') c -= '0'; + else if (c >= 'a') c = c - 'a' + 10; + else c = c - 'A' + 10; + if (i % 2) { *val = c; *val <<= 4; } + else { *val = *val | c; val++; } + } + break; + } + } +} + +int AllDataType::printVal(void* src, DataType srcType, int length ) +{ + int count = 0; + switch(srcType) + { + case typeInt: + { + count = printf ("%d", *(int *)src); + break; + } + case typeLong: + { + count = printf ("%ld", *(long *)src); + break; + } + case typeLongLong: + { + count = printf ("%lld", *(long long *)src); + break; + } + case typeShort: + { + count = printf("%hd", *(short *)src); + break; + } + case typeByteInt: + { + count = printf("%hd", *(char *)src); + break; + } + + case typeFloat: + { + count = printf("%f", *(float *)src); + break; + } + case typeDouble: + { + count = printf("%lf", *(double *)src); + break; + } + + case typeString: + { + count = printf("%s", (char*)src); + break; + } + case typeDate: + { + Date* dt = (Date*)src; + count = printf("%d/%d/%d", dt->year(), + dt->month(), dt->dayOfMonth()); + break; + } + case typeTime: + { + Time* tm = (Time*)src; + count = printf("%d:%d:%d.%d", tm->hours(), tm->minutes(), tm->seconds(), 0); + break; + } + case typeTimeStamp: + { + TimeStamp* tm = (TimeStamp*)src; + count = printf("%d/%d/%d %d:%d:%d.%d", tm->year(), + tm->month(), tm->dayOfMonth(), tm->hours(), + tm->minutes(), tm->seconds(), 0 ); + break; + } + case typeBinary: + { + unsigned char *c = (unsigned char *) src; + unsigned char p = 0; + int i = 0; + while (i < length) { + p = *c >> 4; + if (p < 10) printf ("%c", '0' + p); + else printf("%c", 'A' + p - 10); + p = *c & 0xF; + if (p < 10) printf ("%c", '0' + p); + else printf("%c", 'A' + p - 10); + i++; c++; + } + count = length * 2; + break; + } + default: { printf("DataType not supported\n"); break; } + } + return count; +} + + + diff --git a/src/storage/Database.cxx b/src/storage/Database.cxx new file mode 100644 index 00000000..ad7881cb --- /dev/null +++ b/src/storage/Database.cxx @@ -0,0 +1,486 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +const char* Database::getName() +{ + return metaData_->dbName_; +} + +int Database::getDatabaseID() +{ + return metaData_->dbID_; +} + +long Database::getMaxSize() +{ + return metaData_->maxSize_; +} + +long Database::getCurrentSize() +{ + return metaData_->curSize_; + +} +Page* Database::getCurrentPage() +{ + return metaData_->curPage_; + +} +Page* Database::getFirstPage() +{ + return metaData_->firstPage_; + +} +int Database::getNoOfChunks() +{ + return metaData_->noOfChunks_; +} +Chunk* Database::getHashIndexChunk() +{ + return metaData_->hashIndexChunk_; +} + +void Database::setDatabaseID(int id) +{ + metaData_->dbID_ = id; +} +void Database::setName(const char *name) +{ + strcpy(metaData_->dbName_ , name); +} +void Database::setCurrentSize(long size) +{ + metaData_->curSize_ = size; +} +void Database::setCurrentPage(Page *page) +{ + metaData_->curPage_ = page; +} +void Database::setFirstPage(Page *page) +{ + metaData_->firstPage_ = page; +} +void Database::setMaxSize(long size) +{ + metaData_->maxSize_ = size; +} +void Database::setNoOfChunks(int chunks) +{ + metaData_->noOfChunks_ = chunks; +} +void Database::setHashIndexChunk(Chunk *ch) +{ + metaData_->hashIndexChunk_ = ch; +} + + +int Database::initAllocDatabaseMutex() +{ + return metaData_->dbAllocMutex_.init("allocdb"); +} +DbRetVal Database::getAllocDatabaseMutex(bool procAccount) +{ + int ret= metaData_->dbAllocMutex_.getLock(procAccount); + if (ret) return ErrLockTimeOut; else return OK; +} +DbRetVal Database::releaseAllocDatabaseMutex(bool procAccount) +{ + metaData_->dbAllocMutex_.releaseLock(procAccount); + return OK; +} + + + +int Database::initTransTableMutex() +{ + return metaData_->dbTransTableMutex_.init("transtable"); +} +DbRetVal Database::getTransTableMutex() +{ + int ret = metaData_->dbTransTableMutex_.getLock(procSlot); + if (ret) return ErrLockTimeOut; else return OK; +} +DbRetVal Database::releaseTransTableMutex() +{ + metaData_->dbTransTableMutex_.releaseLock(procSlot); + return OK; +} + + + +int Database::initProcessTableMutex() +{ + return metaData_->dbProcTableMutex_.init("proctable"); +} +DbRetVal Database::getProcessTableMutex(bool procAccount) +{ + int ret = metaData_->dbProcTableMutex_.getLock(-1, procAccount); + if (ret) return ErrLockTimeOut; else return OK; +} +DbRetVal Database::releaseProcessTableMutex(bool procAccount) +{ + metaData_->dbProcTableMutex_.releaseLock(-1, procAccount); + return OK; +} + + + +int Database::initDatabaseMutex() +{ + return metaData_->dbMutex_.init("db"); +} +DbRetVal Database::getDatabaseMutex(bool procAccount) +{ + int ret = metaData_->dbMutex_.getLock(procSlot, procAccount); + if (ret) return ErrLockTimeOut; else return OK; +} +DbRetVal Database::releaseDatabaseMutex(bool procAccount) +{ + metaData_->dbMutex_.releaseLock(procSlot, procAccount); + return OK; +} + +// Gets the free page +// Each page is segmented by PAGE_SIZE, so it checks the pageInfo +// of each page to determine if the page is free +// Algorithm is to scan through the pageInfo objects stored at +// address (db start address + i * PAGE_SIZE) where i = 1..n till end +// database +// But in case of large tuples, pages are merged, so there wont be +// PageInfo object on pages which are merged. +// These pages are skipped by checking the nextPageAfterMerge_ of PageInfo + +//NOTE::IMPORTANT::assumes alloc database lock is taken before calling this +Page* Database::getFreePage() +{ + //Page* page = getFirstPage(); + Page* page = getCurrentPage(); + //printDebug(DM_Alloc, "Database::getFreePage firstPage:%x",page); + printDebug(DM_Alloc, "Database::getFreePage currentpage:%x",page); + PageInfo* pageInfo = ((PageInfo*)page); + char* endAddr = ((char*)getMetaDataPtr()) + getMaxSize(); + int pageSize = PAGE_SIZE; + while( 1 == pageInfo->isUsed_) + { + //If any pages are merged to store data larger than PAGE_SIZE + //move to the next page after the merge and check whether it is used + if ( pageInfo->nextPageAfterMerge_ == NULL) { + pageInfo = (PageInfo*)((char*)pageInfo + pageSize); + printDebug(DM_Alloc,"Normal Page:Moving to page:%x",pageInfo); + } + else { + pageInfo = (PageInfo*)pageInfo->nextPageAfterMerge_; + printDebug(DM_Alloc,"Merged Page:Moving to page:%x",pageInfo); + } + if ((char*)pageInfo >= endAddr) + { + //printError(ErrSysInternal,"Invalid address %x",pageInfo); + return NULL; + } + + } + if (!isValidAddress(((char*) pageInfo) + pageSize)) + { + printError(ErrSysInternal, "Invalid address %x",((char*) pageInfo) + pageSize); + return NULL; + } + setCurrentPage((Page*) pageInfo); + printDebug(DM_Alloc,"Database::getFreePage returning page:%x",pageInfo); + return (Page*) pageInfo ; +} + +//Used by tuples more than PAGE_SIZE +//NOTE::IMPORTANT::assumes alloc database lock is taken before calling this +Page* Database::getFreePage(size_t size) +{ + Page* page = getFirstPage(); + PageInfo* pageInfo = ((PageInfo*)page); + int multiple = size / PAGE_SIZE; + int offset = ((multiple + 1) * PAGE_SIZE); + printDebug(DM_Alloc, "Database::getFreePage firstPage:%x size:%ld",page, size); + char* endAddr = ((char*)getMetaDataPtr()) + getMaxSize(); + int pageSize = PAGE_SIZE; + while(true){ + while( 1 == pageInfo->isUsed_) + { + //If any pages are merged to store data larger than PAGE_SIZE + //move to the next page after the merge and check whether it is used + if ( pageInfo->nextPageAfterMerge_ == NULL) { + pageInfo = (PageInfo*)((char*)pageInfo + pageSize); + printDebug(DM_Alloc,"Normal Page:Moving to page:%x",pageInfo); + } + else { + pageInfo = (PageInfo*)pageInfo->nextPageAfterMerge_; + printDebug(DM_Alloc,"Merged Page:Moving to page:%x",pageInfo); + } + } + int i = 0; + PageInfo *pInfo = pageInfo; + if ((((char*)pInfo) + offset) >= endAddr) + { + printError(ErrSysInternal,"Invalid address %x",((char*)pInfo) + offset); + return NULL; + } + for (i = 0; i< multiple + 1; i++) + { + if (1 == pInfo->isUsed_) break; + pInfo = (PageInfo*)((char*)pInfo + pageSize); + } + if ( i == (multiple + 1)) break; + pageInfo = (PageInfo*)((char*)pInfo + pageSize); + } + + printDebug(DM_Alloc,"Database::getFreePage returning page:%x",pageInfo); + setCurrentPage((Page*) pageInfo); + return (Page*) pageInfo ; +} + +void Database::printStatistics() +{ + Page* page = getFirstPage(); + PageInfo* pageInfo = ((PageInfo*)page); + int usedPageCount =0, usedMergedPageCount =0, totalPages=0; + printf("\n"); + printf(" %s \n", getName()); + printf(" %ld \n", getMaxSize()); + printf(" %x \n", getFirstPage()); + while(isValidAddress((char*) pageInfo)) + { + if (pageInfo == NULL) break; + if (1 == pageInfo->isUsed_) { + if ( pageInfo->nextPageAfterMerge_ == NULL) { + pageInfo = (PageInfo*)((char*)pageInfo + PAGE_SIZE); + usedPageCount++; totalPages++; + printDebug(DM_Alloc, "Normal Page:Moving to page:%x\n",pageInfo); + continue; + } + else { + pageInfo = (PageInfo*)pageInfo->nextPageAfterMerge_; + usedMergedPageCount++; totalPages++; + printDebug(DM_Alloc,"Merged Page:Moving to page:%x\n",pageInfo); + continue; + } + } + pageInfo = (PageInfo*)((char*)pageInfo + PAGE_SIZE); + printDebug(DM_Alloc,"Normal Page not used:Moving to page:%x\n",pageInfo); + totalPages++; + } + printf(" %d \n", totalPages); + printf(" %d \n", usedPageCount); + printf(" %d \n", usedMergedPageCount); + printf(" %d \n", getNoOfChunks()); + printf("\n"); + + return ; +} + + +//called only in case of system database to create and initialize the chunk +//information +DbRetVal Database::createSystemDatabaseChunk(AllocType type, size_t size, int id) +{ + + Chunk *chunk; + if (-1 == id ) + { + printError(ErrSysFatal, "Database ID corrupted"); + return ErrSysFatal; + } + chunk = getSystemDatabaseChunk(id); + + if (FixedSizeAllocator == type) chunk->setSize(size); + //getDatabaseMutex(); + if (chunk->allocSize_ > PAGE_SIZE) + chunk->curPage_ = getFreePage(chunk->allocSize_); + else + chunk->curPage_ = getFreePage(); + if ( chunk->curPage_ == NULL) + { + //releaseDatabaseMutex(); + printError(ErrNoMemory, "No free pages in database: Database full"); + return ErrNoMemory; + } + + chunk->firstPage_ = chunk->curPage_; + PageInfo* firstPageInfo = ((PageInfo*)chunk->firstPage_); + firstPageInfo->setFirstPageAsUsed(); + chunk->setChunkID(id); + chunk->setAllocType(type); + printDebug(DM_Database, "Creating System Database Chunk:%d Size:%d",id, chunk->allocSize_); + if (chunk->allocSize_ > PAGE_SIZE) + { + int multiple = os::floor(chunk->allocSize_ / PAGE_SIZE); + int offset = ((multiple + 1) * PAGE_SIZE); + firstPageInfo->nextPageAfterMerge_ = ((char*)firstPageInfo)+ offset; + } + + if (0 == size) + { + VarSizeInfo *varInfo = (VarSizeInfo*)(((char*)firstPageInfo) + sizeof(PageInfo)); + varInfo->isUsed_ = 0; + varInfo->size_ = PAGE_SIZE - sizeof(PageInfo) - sizeof(VarSizeInfo); + + } + incrementChunk(); + //releaseDatabaseMutex(); + return OK; +} + +//This is never called currently. If situation arises will be coded later. +DbRetVal Database::deleteSystemDatabaseChunk(int id) +{ + + Chunk *chunk = getSystemDatabaseChunk(id); + chunk->setChunkID(-1); + chunk->setSize(0); + chunk->setAllocType(UnknownAllocator); + //TODO:: + //chunk->pageList_ + //walk though the pageList ptr and get all the page pointers + //then free all the pages used to store this by setting the + //start of page to notused + chunk->firstPage_ = NULL; + chunk->curPage_ = NULL; + decrementChunk(); + return OK; +} + + +void Database::createAllCatalogTables() +{ + //These are special chunks which hold catalog tables and other information + // + // chunk id 0 ->userChunkTable + // chunk id 1 ->lockBucketHash + // chunk id 2 ->lockTable + // + // chunk id 10->DATABASE + // chunk id 11->USER + // chunk id 12->TABLE + // chunk id 13->FIELD + // chunk id 14->ACCESS + + createSystemTables(); + createMetaDataTables(); +} +void Database::createSystemTables() +{ + createSystemDatabaseChunk(FixedSizeAllocator, + sizeof(Chunk), UserChunkTableId); + createSystemDatabaseChunk(FixedSizeAllocator, + sizeof(Bucket) * LOCK_BUCKET_SIZE, + LockTableHashBucketId); + createSystemDatabaseChunk(FixedSizeAllocator, + sizeof(Mutex)* LOCK_BUCKET_SIZE, + LockTableMutexId); + createSystemDatabaseChunk(FixedSizeAllocator, + sizeof(LockHashNode), LockTableId); + createSystemDatabaseChunk(FixedSizeAllocator, + sizeof(TransHasNode), TransHasTableId); + + createSystemDatabaseChunk(VariableSizeAllocator, + 0, UndoLogTableID); +} +void Database::createMetaDataTables() +{ + createSystemDatabaseChunk(FixedSizeAllocator, + sizeof(DATABASEFILE), DatabaseTableId); + createSystemDatabaseChunk(FixedSizeAllocator, + sizeof(USER), UserTableId); + createSystemDatabaseChunk(FixedSizeAllocator, + sizeof(TABLE), TableTableId); + createSystemDatabaseChunk(FixedSizeAllocator, + sizeof(FIELD), FieldTableId); + createSystemDatabaseChunk(FixedSizeAllocator, + sizeof(ACCESS), AccessTableId); + createSystemDatabaseChunk(FixedSizeAllocator, + sizeof(INDEX), IndexTableId); + createSystemDatabaseChunk(FixedSizeAllocator, + sizeof(INDEXFIELD), IndexFieldTableId); +} + +//used in case of system database +Chunk* Database::getSystemDatabaseChunk(int id) +{ + size_t offset = os::alignLong(sizeof (DatabaseMetaData)) + + id * sizeof (Chunk); + return (Chunk*)(((char*) metaData_) + offset); +} + + +//used in case of system database +Transaction* Database::getSystemDatabaseTrans(int slot) +{ + size_t offset = os::alignLong(sizeof (DatabaseMetaData)) + + os::alignLong(MAX_CHUNKS * sizeof (Chunk)) + + slot * sizeof (Transaction); + return (Transaction*)(((char*) metaData_) + offset); +} + +//used in case of system database +ThreadInfo* Database::getThreadInfo(int slot) +{ +/* size_t offset = os::alignLong(sizeof (DatabaseMetaData)); + offset = offset + os::alignLong( MAX_CHUNKS * sizeof (Chunk)); + offset = offset + os::alignLong( Conf::config.getMaxProcs() * sizeof(Transaction)); + offset = offset + slot * sizeof (ThreadInfo); + return (ThreadInfo*)(((char*) metaData_) + offset); +*/ + + static size_t offset = os::alignLong(sizeof (DatabaseMetaData)) + + os::alignLong( MAX_CHUNKS * sizeof (Chunk)) + + os::alignLong( Conf::config.getMaxProcs()*sizeof(Transaction)); + + size_t off = offset + slot * sizeof (ThreadInfo); + return (ThreadInfo*)(((char*) metaData_) + off); + +} + +bool Database::isValidAddress(void* addr) +{ + if ((char*) addr >= ((char*)getMetaDataPtr()) + getMaxSize()) + return false; + else + return true; +} + +//should be called only on system database +void* Database::allocLockHashBuckets() +{ + Chunk *chunk = getSystemDatabaseChunk(LockTableHashBucketId); + void *ptr = chunk->allocate(this); + if (NULL == ptr) + { + printError(ErrNoMemory, "Chunk Allocation failed for lock hash bucket catalog table"); + } + return ptr; +} + +Bucket* Database::getLockHashBuckets() +{ + Chunk *tChunk = getSystemDatabaseChunk(LockTableHashBucketId); + ChunkIterator iter = tChunk->getIterator(); + return (Bucket*)iter.nextElement(); +} + diff --git a/src/storage/DatabaseManagerImpl.cxx b/src/storage/DatabaseManagerImpl.cxx new file mode 100644 index 00000000..b82890f6 --- /dev/null +++ b/src/storage/DatabaseManagerImpl.cxx @@ -0,0 +1,1120 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +DatabaseManagerImpl::~DatabaseManagerImpl() +{ + //Note:Databases are closed by the session interface + Table *tbl = NULL; + ListIterator iter = tableHandleList.getIterator(); + while ((tbl = (Table *)iter.nextElement()) != NULL) delete tbl; + tableHandleList.reset(); + delete tMgr_; + delete lMgr_; +} + +void DatabaseManagerImpl::createLockManager() +{ + lMgr_ = new LockManager(systemDatabase_); + return; +} + +void DatabaseManagerImpl::createTransactionManager() +{ + + tMgr_ = new TransactionManager(); + tMgr_->setFirstTrans(systemDatabase_->getSystemDatabaseTrans(0)); + return; +} +void DatabaseManagerImpl::setProcSlot() +{ +systemDatabase_->setProcSlot(procSlot); +db_->setProcSlot(procSlot); +} +DbRetVal DatabaseManagerImpl::openSystemDatabase() +{ + DbRetVal rv = openDatabase(SYSTEMDB); + if (rv != OK) return rv; + systemDatabase_ = db_; + db_ = NULL; + printDebug(DM_Database, "Opened system database"); + logFinest(logger, "Opened system database"); + return OK; +} + +DbRetVal DatabaseManagerImpl::closeSystemDatabase() +{ + Database *db = db_; + //make them to point to system database file descriptor + //and database pointer + db_ = systemDatabase_; + closeDatabase(); + db_ = db; + printDebug(DM_Database, "Closed system database"); + logFinest(logger, "Closed System database"); + return OK; +} + +DbRetVal DatabaseManagerImpl::createDatabase(const char *name, size_t size) +{ + if (NULL != db_ ) + { + printError(ErrAlready, "Database is already created"); + return ErrAlready; + } + caddr_t rtnAddr = (caddr_t) NULL; + shared_memory_id shm_id = 0; + + char *startaddr = (char*)Conf::config.getMapAddress(); + shared_memory_key key = 0; + if (0 == strcmp(name, SYSTEMDB)) + { + + key = Conf::config.getSysDbKey(); + } + else + { + startaddr = startaddr + Conf::config.getMaxSysDbSize(); + key = Conf::config.getUserDbKey(); + } + shm_id = os::shm_create(key, size, 0666); + if (-1 == shm_id) + { + if (errno == EEXIST) { + printError(ErrOS, "Shared Memory already exists"); + } + printError(ErrOS, "Shared memory create failed"); + return ErrOS; + } + + void *shm_ptr = os::shm_attach(shm_id, startaddr, SHM_RND); + rtnAddr = (caddr_t) shm_ptr; + if (rtnAddr < 0 || shm_ptr == (char*)0xffffffff) + { + printError(ErrOS, "Shared memory attach returned -ve value %d", rtnAddr); + return ErrOS; + } + memset(shm_ptr, 0, size ); + db_ = new Database(); + printDebug(DM_Database, "Creating database:%s",name); + + //TODO:for user database do not have transtable and processtable mutex + db_->setMetaDataPtr((DatabaseMetaData*)rtnAddr); + db_->setDatabaseID(1); + db_->setName(name); + db_->setMaxSize(size); + db_->setNoOfChunks(0); + db_->initAllocDatabaseMutex(); + db_->initTransTableMutex(); + db_->initDatabaseMutex(); + db_->initProcessTableMutex(); + + //compute the first page after book keeping information + size_t offset = os::alignLong(sizeof (DatabaseMetaData)); + //Only for system db chunk array, trans array and proc array will be there + if (0 == strcmp(name, SYSTEMDB)) + { + offset = offset + os::alignLong( MAX_CHUNKS * sizeof (Chunk)); + offset = offset + os::alignLong( Conf::config.getMaxProcs() * sizeof(Transaction)); + offset = offset + os::alignLong( Conf::config.getMaxProcs() * sizeof(ThreadInfo)); + } + int multiple = os::floor(offset / PAGE_SIZE); + char *curPage = (((char*)rtnAddr) + ((multiple + 1) * PAGE_SIZE)); + + db_->setCurrentPage(curPage); + db_->setFirstPage(curPage); + + if (0 == strcmp(name, SYSTEMDB)) return OK; + + /*Allocate new chunk to store hash index nodes + Chunk *chunkInfo = createUserChunk(sizeof(HashIndexNode)); + if (NULL == chunkInfo) + { + printError(ErrSysInternal, "Failed to allocate hash index nodes chunk"); + return ErrSysInternal; + } + printDebug(DM_Database, "Creating Chunk for storing Hash index nodes %x", + chunkInfo); + + db_->setHashIndexChunk(chunkInfo);*/ + logFinest(logger, "Created database %s" , name); + + return OK; +} + +DbRetVal DatabaseManagerImpl::deleteDatabase(const char *name) +{ + shared_memory_id shm_id = 0; + if (0 == strcmp(name, SYSTEMDB)) + { + shm_id = os::shm_open(Conf::config.getSysDbKey(), 100, 0666); + os::shmctl(shm_id, IPC_RMID); + delete systemDatabase_; + systemDatabase_ = NULL; + } else { + shm_id = os::shm_open(Conf::config.getUserDbKey(), 100, 0666); + os::shmctl(shm_id, IPC_RMID); + delete db_; + db_ = NULL; + } + logFinest(logger, "Deleted database %s" , name); + return OK; +} + +DbRetVal DatabaseManagerImpl::openDatabase(const char *name) +{ + long size = Conf::config.getMaxSysDbSize(); + char *startaddr = (char*)Conf::config.getMapAddress(); + if (0 == strcmp(name , SYSTEMDB)) + { + if (NULL !=systemDatabase_) + { + printError(ErrAlready, "System Database already open"); + return ErrAlready; + } + } + else + { + if (NULL ==systemDatabase_) + { + printError(ErrNotOpen, "System Database not open"); + return ErrNotOpen; + } + size = Conf::config.getMaxDbSize(); + startaddr = startaddr + Conf::config.getMaxSysDbSize(); + } + if (NULL != db_) + { + printError(ErrAlready, "User Database already open"); + return ErrAlready; + } + //system db should be opened before user database files + caddr_t rtnAddr = (caddr_t) NULL; + + shared_memory_id shm_id = 0; + shared_memory_key key = 0; + + if (0 == strcmp(name, SYSTEMDB)) + key = Conf::config.getSysDbKey(); + else + key = Conf::config.getUserDbKey(); + + + int ret = ProcessManager::mutex.getLock(-1, false); + //If you are not getting lock ret !=0, it means somebody else is there. + //he will close the database. + if (ret != 0) + { + printError(ErrSysInternal, "Another thread calling open:Wait and then Retry\n"); + return ErrSysInternal; + } + void *shm_ptr = NULL; + bool firstThread = false; + //printf("PRABA::DEBUG:: opendb %d %s\n", ProcessManager::noThreads, name); + if (ProcessManager::noThreads == 0 && 0 == strcmp(name, SYSTEMDB) + || ProcessManager::noThreads == 1 && 0 != strcmp(name, SYSTEMDB) ) { + shm_id = os::shm_open(key, size, 0666); + if (shm_id == -1 ) + { + printError(ErrOS, "Shared memory open failed"); + ProcessManager::mutex.releaseLock(-1, false); + return ErrOS; + } + shm_ptr = os::shm_attach(shm_id, startaddr, SHM_RND); + if (0 == strcmp(name, SYSTEMDB)) + { + firstThread = true; + ProcessManager::sysAddr = (char*) shm_ptr; + } + else + { + ProcessManager::usrAddr = (char*) shm_ptr; + } + } else { + if (0 == strcmp(name, SYSTEMDB)) + shm_ptr = ProcessManager::sysAddr; + else + shm_ptr = ProcessManager::usrAddr; + } + ProcessManager::mutex.releaseLock(-1, false); + + + rtnAddr = (caddr_t) shm_ptr; + + if (rtnAddr < 0 || shm_ptr == (char*)0xffffffff) + { + printError(ErrOS, "Shared memory attach returned -ve value %x %d", shm_ptr, errno); + return ErrOS; + } + db_ = new Database(); + db_->setMetaDataPtr((DatabaseMetaData*)rtnAddr); + + if (firstThread) ProcessManager::systemDatabase = db_; + + printDebug(DM_Database, "Opening database: %s", name); + logFinest(logger, "Opened database %s" , name); + return OK; +} + +DbRetVal DatabaseManagerImpl::closeDatabase() +{ + + if (NULL == db_) + { + //Database is already closed + return OK; + } + printDebug(DM_Database, "Closing database: %s",(char*)db_->getName()); + //check if this is the last thread to be deregistered + int ret = ProcessManager::mutex.getLock(-1, false); + //If you are not getting lock ret !=0, it means somebody else is there. + //he will close the database. + if (ret == 0) { + //printf("PRABA::FOR DEBUG closedb %d %s\n", ProcessManager::noThreads, (char*)db_->getName()); + if (ProcessManager::noThreads == 0 && 0 == strcmp((char*)db_->getName(), SYSTEMDB) + || ProcessManager::noThreads == 1 && 0 != strcmp((char*)db_->getName(), SYSTEMDB) ) { + os::shm_detach((char*)db_->getMetaDataPtr()); + } + } + ProcessManager::mutex.releaseLock(-1, false); + logFinest(logger, "Closed database"); + delete db_; + db_ = NULL; + return OK; +} +//Assumes that system database mutex is taken before calling this. +Chunk* DatabaseManagerImpl::createUserChunk(size_t size) +{ + //Allocate new node in system database to store + Chunk *chunk = getSystemTableChunk(UserChunkTableId); + DbRetVal rv = OK; + void *ptr = chunk->allocate(systemDatabase_, &rv); + if (NULL == ptr) + { + printError(rv, "Allocation failed for User chunk catalog table"); + return NULL; + } + Chunk *chunkInfo = (Chunk*)ptr; + chunkInfo->initMutex(); + if (0 != size) chunkInfo->setSize(size); + if (chunkInfo->allocSize_ > PAGE_SIZE) + chunkInfo->curPage_ = db_->getFreePage(chunkInfo->allocSize_); + else + chunkInfo->curPage_ = db_->getFreePage(); + if ( NULL == chunkInfo->curPage_) + { + chunkInfo->destroyMutex(); + chunk->free(db_, ptr); + printError(ErrNoMemory, "Database full: No space to allocate from database"); + return NULL; + } + PageInfo* firstPageInfo = ((PageInfo*)chunkInfo->curPage_); + if (chunkInfo->allocSize_ > PAGE_SIZE) + { + int multiple = os::floor(chunkInfo->allocSize_ / PAGE_SIZE); + int offset = ((multiple + 1) * PAGE_SIZE); + firstPageInfo->setPageAsUsed(offset); + } + else + { + firstPageInfo->setPageAsUsed(chunkInfo->allocSize_); + char *data = ((char*)firstPageInfo) + sizeof(PageInfo); + *(int*)data =0; + } + if (0 == size) + { + VarSizeInfo *varInfo = (VarSizeInfo*)(((char*)firstPageInfo) + sizeof(PageInfo)); + varInfo->isUsed_ = 0; + varInfo->size_ = PAGE_SIZE - sizeof(PageInfo) - sizeof(VarSizeInfo); + + } + chunkInfo->firstPage_ = chunkInfo->curPage_; + + if (0 == size) + chunkInfo->setAllocType(VariableSizeAllocator); + else + chunkInfo->setAllocType(FixedSizeAllocator); + + //TODO::Generate chunkid::use tableid + chunkInfo->setChunkID(-1); + db_->incrementChunk(); + printDebug(DM_Database, "Creating new User chunk chunkID:%d size: %d firstPage:%x", + -1, chunkInfo->allocSize_, firstPageInfo); + + return chunkInfo; +} + +//Assumes that system database mutex is taken before calling this. +DbRetVal DatabaseManagerImpl::deleteUserChunk(Chunk *chunk) +{ + //Go to the pages and set them to notUsed + Page *page = chunk->firstPage_; + PageInfo* pageInfo = ((PageInfo*)page); + //Here...sure that atleast one page will be there even no tuples + //are inserted.so not checking if pageInfo == NULL + while( pageInfo->nextPage_ != NULL) + { + PageInfo *prev = pageInfo; + pageInfo = (PageInfo*)(pageInfo->nextPage_); + //sets pageInfo->isUsed_ = 0 and pageInfo->hasFreeSpace_ = 0 + //and initializes the page content to zero + if(NULL == pageInfo->nextPageAfterMerge_) + os::memset(prev, 0, PAGE_SIZE); + else + { + int size = (char*) pageInfo->nextPageAfterMerge_ - (char*) pageInfo; + os::memset(prev, 0, size); + } + printDebug(DM_Database,"deleting user chunk:%x clearing page %x",chunk, prev); + } + //The above loop wont execute for the last page + //and for the case where table has only one page + if(NULL == pageInfo->nextPageAfterMerge_) + os::memset(pageInfo, 0, PAGE_SIZE); + else + { + int size = (char*) pageInfo->nextPageAfterMerge_ - (char*) pageInfo; + os::memset(pageInfo, 0, size); + } + printDebug(DM_Database,"deleting user chunk:%x clearing page %x",chunk, pageInfo); + chunk->chunkID_ = -1; + chunk->allocSize_ = 0; + chunk->curPage_ = NULL; + chunk->firstPage_ = NULL; + chunk->destroyMutex(); + db_->decrementChunk(); + printDebug(DM_Database,"deleting user chunk:%x",chunk); + return OK; +} + +//-1 -> Unable to create chunk. No memory +//-2 -> Unable to update the catalog tables +DbRetVal DatabaseManagerImpl::createTable(const char *name, TableDef &def) +{ + DbRetVal rv = OK; + int fldCount = def.getFieldCount(); + //If total field count is less than 32, then 1 integer is used to store all null + //information, if it is more then 1 char is used to store null information + //of each field + //This is to done to reduce cpu cycles for small tables + int addSize = 0; + if (fldCount < 31) addSize = 4; else addSize = os::align(fldCount); + size_t sizeofTuple = os::align(def.getTupleSize())+addSize; + + rv = systemDatabase_->getDatabaseMutex(); + if (OK != rv ) { + printError(rv, "Unable to get Database mutex"); + return rv; + } + + void *tptr =NULL; + void *chunk = NULL; + + //check whether table already exists + CatalogTableTABLE cTable(systemDatabase_); + cTable.getChunkAndTblPtr(name, chunk, tptr); + if (NULL != tptr) + { + systemDatabase_->releaseDatabaseMutex(); + printError(ErrAlready, "Table %s already exists", name); + return ErrAlready; + } + + //create a chunk to store the tuples + Chunk *ptr = createUserChunk(sizeofTuple); + if (NULL == ptr) + { + systemDatabase_->releaseDatabaseMutex(); + printError(ErrNoResource, "Unable to create user chunk"); + return ErrNoResource; + } + printDebug(DM_Database,"Created UserChunk:%x", ptr); + + //add row to TABLE + int tblID = ((Chunk*)ptr)->getChunkID(); + rv = cTable.insert(name, tblID, sizeofTuple, + def.getFieldCount(), ptr, tptr); + if (OK != rv) + { + deleteUserChunk(ptr); + systemDatabase_->releaseDatabaseMutex(); + printError(ErrSysInternal, "Unable to update catalog table TABLE"); + return ErrSysInternal; + } + printDebug(DM_Database,"Inserted into TABLE:%s",name); + //add rows to FIELD + FieldIterator iter = def.getFieldIterator(); + CatalogTableFIELD cField(systemDatabase_); + rv = cField.insert(iter, tblID ,tptr); + if (OK != rv) + { + deleteUserChunk(ptr); + void *cptr, *ttptr;//Dummy as remove below needs both these OUT params + cTable.remove(name, cptr, ttptr); + systemDatabase_->releaseDatabaseMutex(); + printError(ErrSysInternal, "Unable to update catalog table FIELD"); + return ErrSysInternal; + } + printDebug(DM_Database,"Inserted into FIELD:%s",name); + systemDatabase_->releaseDatabaseMutex(); + printDebug(DM_Database,"Table Created:%s",name); + logFinest(logger, "Table Created %s" , name); + return OK; +} + +//TODO::If any operation fails in between, then we may have some +//dangling tuples, say we have have rows in INDEX table +//which will not have any corresponding entries in TABLE +//CHANGE the sequence so that it deletes from the bottom as +//opposed to start from top as is written now +DbRetVal DatabaseManagerImpl::dropTable(const char *name) +{ + void *chunk = NULL; + void *tptr =NULL; + DbRetVal rv = systemDatabase_->getDatabaseMutex(); + if (OK != rv) { + printError(ErrSysInternal, "Unable to get database mutex"); + return ErrSysInternal; + } + + //remove the entry in TABLE + CatalogTableTABLE cTable(systemDatabase_); + rv = cTable.getChunkAndTblPtr(name, chunk, tptr); + if (OK != rv) { + systemDatabase_->releaseDatabaseMutex(); + printError(ErrSysInternal, "Table %s does not exist", name); + return ErrSysInternal; + } + rv = lMgr_->getExclusiveLock(chunk, NULL); + if (rv !=OK) + { + systemDatabase_->releaseDatabaseMutex(); + printError(ErrLockTimeOut, "Unable to acquire exclusive lock on the table\n"); + return rv; + } + + rv = cTable.remove(name, chunk, tptr); + if (OK != rv) { + systemDatabase_->releaseDatabaseMutex(); + printError(ErrSysInternal, "Unable to update catalog table TABLE"); + return ErrSysInternal; + } + printDebug(DM_Database,"Deleted from TABLE:%s",name); + + //remove the entries in the FIELD table + CatalogTableFIELD cField(systemDatabase_); + rv = cField.remove(tptr); + if (OK != rv) { + systemDatabase_->releaseDatabaseMutex(); + printError(ErrSysInternal, "Unable to update catalog table FIELD"); + return ErrSysInternal; + } + printDebug(DM_Database,"Deleted from FIELD:%s",name); + + rv = deleteUserChunk((Chunk*)chunk); + if (OK != rv) { + systemDatabase_->releaseDatabaseMutex(); + printError(rv, "Unable to delete the chunk"); + return rv; + } + printDebug(DM_Database,"Deleted UserChunk:%x", chunk); + + //TODO::check whether indexes are available and drop that also. + CatalogTableINDEX cIndex(systemDatabase_); + int noIndexes = cIndex.getNumIndexes(tptr); + for (int i =1 ; i<= noIndexes; i++) { + char *idxName = cIndex.getIndexName(tptr, 1); + dropIndexInt(idxName, false); + } + Chunk *chunkNode = systemDatabase_->getSystemDatabaseChunk(UserChunkTableId); + chunkNode->free(systemDatabase_, (Chunk *) chunk); + systemDatabase_->releaseDatabaseMutex(); + printDebug(DM_Database, "Deleted Table %s" , name); + logFinest(logger, "Deleted Table %s" , name); + rv = lMgr_->releaseLock(chunk); + if (rv !=OK) + { + printError(ErrLockTimeOut, "Unable to release exclusive lock on the table\n"); + return rv; + } + return OK; +} + +//Return values: NULL for table not found +Table* DatabaseManagerImpl::openTable(const char *name) +{ + DbRetVal ret = OK; + //TODO::store table handles in list so that if it is + //not closed by the application. destructor shall close it. + TableImpl *table = new TableImpl(); + table->setDB(db_); + table->setSystemDB(systemDatabase_); + table->setLockManager(lMgr_); + table->setTrans(ProcessManager::getThreadTransAddr(systemDatabase_->procSlot)); + + //to store the chunk pointer of table + void *chunk = NULL; + + //to store the tuple pointer of the table + void *tptr =NULL; + + //TODO::need to take shared lock on the table so that + //all ddl operation will be denied on that table + //which includes index creation, alter table + + DbRetVal rv = systemDatabase_->getDatabaseMutex(); + if (OK != rv) { + printError(ErrSysInternal, "Unable to get database mutex"); + delete table; + return NULL; + } + CatalogTableTABLE cTable(systemDatabase_); + ret = cTable.getChunkAndTblPtr(name, chunk, tptr); + if ( OK != ret) + { + systemDatabase_->releaseDatabaseMutex(); + delete table; + printError(ErrNotExists, "Table not exists %s", name); + return NULL; + } + TABLE *tTuple = (TABLE*)tptr; + table->setTableInfo(tTuple->tblName_, tTuple->tblID_, tTuple->length_, + tTuple->numFlds_, tTuple->numIndexes_, tTuple->chunkPtr_); + /*rv = table->lock(true); //take shared lock + if (rv !=OK) + { + printError(ErrLockTimeOut, "Unable to acquire shared lock on the table\n"); + systemDatabase_->releaseDatabaseMutex(); + delete table; + return NULL; + }*/ + + + if (tTuple->numFlds_ < 31) + { + table->isIntUsedForNULL = true; + table->iNullInfo = 0; + table->iNotNullInfo =0; + } + else + { + table->isIntUsedForNULL = false; + int noFields = os::align(tTuple->numFlds_); + table->cNullInfo = (char*) malloc(noFields); + table->cNotNullInfo = (char*) malloc(noFields); + for (int i =0 ; i < noFields; i++) table->cNullInfo[i] =0; + for (int i =0 ; i < noFields; i++) table->cNotNullInfo[i] =0; + + } + + //get field information from FIELD table + CatalogTableFIELD cField(systemDatabase_); + cField.getFieldInfo(tptr, table->fldList_); + + //populate the notnull info + FieldIterator fIter = table->fldList_.getIterator(); + int fldpos=1; + while (fIter.hasElement()) + { + FieldDef def = fIter.nextElement(); + if (table->isIntUsedForNULL) { + if (def.isNull_) SETBIT(table->iNotNullInfo, fldpos); + } + else { + if (def.isNull_) table->cNotNullInfo[fldpos-1] = 1; + } + fldpos++; + } + + //get the number of indexes on this table + //and populate the indexPtr array + CatalogTableINDEX cIndex(systemDatabase_); + table->numIndexes_ = cIndex.getNumIndexes(tptr); + if (table->numIndexes_) { + table->indexPtr_ = new char*[table->numIndexes_]; + table->idxInfo = new IndexInfo*[table->numIndexes_]; + } + else + { + table->indexPtr_ = NULL; + } + cIndex.getIndexPtrs(tptr, table->indexPtr_); + for (int i =0 ; i < table->numIndexes_; i++ ) + { + HashIndexInfo *hIdxInfo = new HashIndexInfo(); + CatalogTableINDEXFIELD cIndexField(systemDatabase_); + cIndexField.getFieldInfo(table->indexPtr_[i], hIdxInfo->idxFldList); + ChunkIterator citer = CatalogTableINDEX::getIterator(table->indexPtr_[i]); + hIdxInfo->indexPtr = table->indexPtr_[i]; + hIdxInfo->noOfBuckets = CatalogTableINDEX::getNoOfBuckets(table->indexPtr_[i]); + FieldIterator fIter = hIdxInfo->idxFldList.getIterator(); + bool firstFld = true; + while (fIter.hasElement()) + { + FieldDef def = fIter.nextElement(); + if (firstFld) + { + hIdxInfo->fldOffset = table->fldList_.getFieldOffset(def.fldName_); + hIdxInfo->type = table->fldList_.getFieldType(def.fldName_); + hIdxInfo->compLength = table->fldList_.getFieldLength(def.fldName_); + firstFld = false; + }else { + hIdxInfo->type = typeComposite; + hIdxInfo->compLength = hIdxInfo->compLength + + table->fldList_.getFieldLength(def.fldName_); + } + } + + hIdxInfo->isUnique = CatalogTableINDEX::getUnique(table->indexPtr_[i]); + hIdxInfo->buckets = (Bucket*)citer.nextElement(); + table->idxInfo[i] = (IndexInfo*) hIdxInfo; + } + systemDatabase_->releaseDatabaseMutex(); + // lMgr-> tTuple->chunkPtr_ + printDebug(DM_Database,"Opening table handle name:%s chunk:%x numIndex:%d", + name, chunk, table->numIndexes_); + logFinest(logger, "Opening Table %s" , name); + + tableHandleList.append(table); + + return table; +} + + + +List DatabaseManagerImpl::getAllTableNames() +{ + DbRetVal ret = OK; + //to store the tuple pointer of the table + void *tptr =NULL; + + DbRetVal rv = systemDatabase_->getDatabaseMutex(); + if (OK != rv) { + printError(ErrSysInternal, "Unable to get database mutex"); + List tableList; + return tableList; + } + CatalogTableTABLE cTable(systemDatabase_); + List tableList = cTable.getTableList(); + systemDatabase_->releaseDatabaseMutex(); + return tableList; +} + + + + +//Return values: -1 for table not found +void DatabaseManagerImpl::closeTable(Table *table) +{ + printDebug(DM_Database,"Closing table handle: %x", table); + if (NULL == table) return; + //table->unlock(); + tableHandleList.remove(table, false); + logFinest(logger, "Closing Table"); +} + +DbRetVal DatabaseManagerImpl::createIndex(const char *indName, IndexInitInfo *info) +{ + DbRetVal rv = OK; + if (!info->isUnique && info->isPrimary) + { + printError(ErrBadCall, "Primary key cannot be non unique\n"); + return ErrBadCall; + } + if (info->indType == hashIndex) + { + //Assumes info is of type HashIndexInitInfo + HashIndexInitInfo *hInfo = (HashIndexInitInfo*) info; + rv = createHashIndex(indName, info->tableName, info->list, hInfo->bucketSize, + info->isUnique, info->isPrimary); + } + else if (info->indType == treeIndex) + { + //TODO::tree index + printError(ErrNotYet, "Tree Index not supported\n"); + return ErrNotYet; + }else { + printError(ErrBadCall, "Index type not supported\n"); + return ErrBadCall; + } + return rv; +} + + +//-1 -> Table does not exists +//-2 -> Field does not exists +//-3 -> bucketSize is not valid +DbRetVal DatabaseManagerImpl::createHashIndex(const char *indName, const char *tblName, + FieldNameList &fldList, int bucketSize, bool isUnique, bool isPrimary) +{ + //validate the bucket size + if (bucketSize < 100 || bucketSize > 200000) + { + printError(ErrBadRange, "Index Bucket size %d not in range 100-200000", + bucketSize); + return ErrBadRange; + } + int totFlds = fldList.size(); + if (totFlds == 0) + { + printError(ErrBadCall, "No Field name specified"); + return ErrBadCall; + } + void *tptr =NULL; + void *chunk = NULL; + DbRetVal rv = systemDatabase_->getDatabaseMutex(); + if (OK != rv) + { + printError(ErrSysInternal, "Unable to get database mutex"); + return ErrSysInternal; + } + + //check whether table exists + CatalogTableTABLE cTable(systemDatabase_); + cTable.getChunkAndTblPtr(tblName, chunk, tptr); + if (NULL == tptr) + { + systemDatabase_->releaseDatabaseMutex(); + printError(ErrNotExists, "Table does not exist %s", tblName); + return ErrNotExists; + } + + //check whether field exists + char **fptr = new char* [totFlds]; + CatalogTableFIELD cField(systemDatabase_); + rv = cField.getFieldPtrs(fldList, tptr, fptr); + if (OK != rv) + { + delete[] fptr; + systemDatabase_->releaseDatabaseMutex(); + //TODO::check test cases of dbapi/Index, they give wrong results + //if (rv == ErrBadCall) { + //// if (isPrimary) printError(ErrBadCall, "Field can have NULL values"); + //} else { + //printError(ErrNotExists, "Field does not exist"); + //} + //return ErrBadCall; + if (rv != ErrBadCall) { + printError(ErrNotExists, "Field does not exist"); + return ErrNotExists; + } + } + for (int i=0; i type_ == typeFloat || fInfo->type_ == typeDouble || fInfo->type_ == typeTimeStamp) + { + printError(ErrBadArg, "HashIndex cannot be created for float or double or timestamp type"); + delete[] fptr; + systemDatabase_->releaseDatabaseMutex(); + return ErrBadArg; + } + if (!fInfo->isNull_ && isPrimary ) + { + printError(ErrBadArg, "Primary Index cannot be created on field without NOTNULL constraint"); + delete[] fptr; + systemDatabase_->releaseDatabaseMutex(); + return ErrBadArg; + } + } + //create chunk to store the meta data of the index created + //for latches and bucket pointers + printDebug(DM_HashIndex, "Creating chunk for storing hash buckets of size %d\n", + bucketSize * sizeof(Bucket)); + Chunk* chunkInfo = createUserChunk(bucketSize * sizeof(Bucket)); + if (NULL == chunkInfo) + { + delete[] fptr; + systemDatabase_->releaseDatabaseMutex(); + printError(ErrSysInternal, "Unable to create chunk"); + return ErrSysInternal; + } + //create memory for holding the bucket pointers + void *buckets = chunkInfo->allocate(db_, &rv); + if (NULL == buckets) + { + delete[] fptr; + deleteUserChunk(chunkInfo); + systemDatabase_->releaseDatabaseMutex(); + printError(rv, "Unable to allocate memory for bucket"); + return rv; + } + Bucket *buck = (Bucket*) buckets; + initHashBuckets(buck, bucketSize); + + //create chunk to store the hash index nodes + Chunk* hChunk = createUserChunk(sizeof(HashIndexNode)); + if (NULL == hChunk) + { + delete[] fptr; + deleteUserChunk(chunkInfo); + systemDatabase_->releaseDatabaseMutex(); + printError(ErrSysInternal, "Unable to create chunk for storing hash index nodes"); + return ErrSysInternal; + } + + //add row to INDEX + void *tupleptr = NULL; + CatalogTableINDEX cIndex(systemDatabase_); + rv = cIndex.insert(indName, tptr, fldList.size(), isUnique, + chunkInfo, bucketSize, hChunk, tupleptr); + if (OK != rv) + { + delete[] fptr; + deleteUserChunk(hChunk); + deleteUserChunk(chunkInfo); + systemDatabase_->releaseDatabaseMutex(); + printError(ErrSysInternal, "Catalog table updation failed in INDEX table"); + return ErrSysInternal; + } + //add rows to INDEXFIELD + CatalogTableINDEXFIELD cIndexField(systemDatabase_); + rv = cIndexField.insert(fldList, tupleptr, tptr, fptr); + + if (OK != rv) + { + delete[] fptr; + cIndex.remove(indName, (void *&)chunkInfo, (void *&)hChunk, (void *&)tupleptr); + deleteUserChunk(hChunk); + deleteUserChunk(chunkInfo); + systemDatabase_->releaseDatabaseMutex(); + printError(ErrSysInternal, "Catalog table updation failed in INDEXFIELD table"); + return ErrSysInternal; + } + delete[] fptr; + systemDatabase_->releaseDatabaseMutex(); + + //TODO:: Take table lock + + // Following code is written by Kishor Amballi + TableImpl *tbl = (TableImpl *) openTable(tblName); + if (! tbl->numTuples()) { + printDebug(DM_Database, "Creating Hash Index Name:%s tblname:%s buckets:%x", indName, tblName, buckets); + logFinest(logger, "Creating HashIndex %s on %s with bucket size %d", indName, tblName, buckets); + return OK; + } + HashIndexInfo *indxInfo = NULL; + int i = 0; + for (i = 0; i < tbl->numIndexes_; i++) { + if(((HashIndexInfo *)tbl->idxInfo[i])->indexPtr == tupleptr) { + indxInfo = (HashIndexInfo *) tbl->idxInfo[i]; + break; + } + } + void *recPtr = NULL; + ChunkIterator chIter = ((Chunk *)chunk)->getIterator(); + while ((recPtr = chIter.nextElement()) != NULL) { + rv = tbl->insertIndexNode(*tbl->trans, tupleptr, indxInfo, recPtr); + if (rv == ErrUnique) { + closeTable(tbl); + dropIndex(indName); + return rv; + } + } + closeTable(tbl); + printDebug(DM_Database, "Creating Hash Index Name:%s tblname:%s buckets:%x", indName, tblName, buckets); + logFinest(logger, "Creating HashIndex %s on %s with bucket size %d", indName, tblName, buckets); + return OK; +} + +void DatabaseManagerImpl::initHashBuckets(Bucket *buck, int bucketSize) +{ + os::memset((void*)buck, 0, bucketSize * sizeof(Bucket)); + + for (int i=0; i < bucketSize ; i++) + { + buck[i].mutex_.init("Bucket"); + } + return; +} + +DbRetVal DatabaseManagerImpl::dropIndex(const char *name) +{ + return dropIndexInt(name, true); +} + +DbRetVal DatabaseManagerImpl::dropIndexInt(const char *name, bool takeLock) +{ + DbRetVal rv = OK; + void *chunk = NULL, *hchunk = NULL; + void *tptr =NULL; + int ret = 0; + if (takeLock) { + rv = systemDatabase_->getDatabaseMutex(); + if (OK != rv) + { + printError(ErrSysInternal, "Unable to get database mutex"); + return ErrSysInternal; + } + } + + //remove the entry in INDEX + CatalogTableINDEX cIndex(systemDatabase_); + rv = cIndex.remove(name, chunk, hchunk, tptr); + if (OK != rv) + { + if (takeLock) systemDatabase_->releaseDatabaseMutex(); + printError(ErrSysInternal, "Catalog table updation failed for INDEX table"); + return ErrSysInternal; + } + printDebug(DM_Database, "Removing from INDEX %s",name); + //remove the entries in the INDEXFIELD table + CatalogTableINDEXFIELD cIndexField(systemDatabase_); + rv = cIndexField.remove(tptr); + if (OK != rv) + { + if (takeLock) systemDatabase_->releaseDatabaseMutex(); + printError(ErrSysInternal, "Catalog table updation failed for INDEX table"); + return ErrSysInternal; + } + printDebug(DM_Database, "Removing from INDEXFIELD %s",name); + + //delete the index chunk + rv = deleteUserChunk((Chunk*)chunk); + if (OK != rv) + { + if (takeLock) systemDatabase_->releaseDatabaseMutex(); + printError(ErrSysInternal, "Unable to delete the index chunk"); + return ErrSysInternal; + } + //delete the index hash node chunk + rv = deleteUserChunk((Chunk*)hchunk); + if (OK != rv) + { + if (takeLock) systemDatabase_->releaseDatabaseMutex(); + printError(ErrSysInternal, "Unable to delete the index hash node chunk"); + return ErrSysInternal; + } + if (takeLock) systemDatabase_->releaseDatabaseMutex(); + Chunk *chunkNode = systemDatabase_->getSystemDatabaseChunk(UserChunkTableId); + chunkNode->free(systemDatabase_, (Chunk *) chunk); + chunkNode->free(systemDatabase_, (Chunk *) hchunk); + + //TODO::If tuples present in this table, then + //free all hash index nodes for this table. + //free all nodes in list of all buckets + //Take table lock + + printDebug(DM_Database, "Dropped hash index %s",name); + logFinest(logger, "Deleted Index %s", name); + return OK; +} +DbRetVal DatabaseManagerImpl::printIndexInfo(char *name) +{ + CatalogTableINDEX cIndex(systemDatabase_); + DbRetVal rv = OK; + void *chunk = NULL, *hchunk = NULL; + void *tptr =NULL; + rv = cIndex.get(name, chunk, hchunk, tptr); + if (OK != rv) return rv; + printf(" %s \n", name); + printf(" %d \n", CatalogTableINDEX::getUnique(tptr)); + Chunk *ch = (Chunk*) chunk; + printf("\n"); + printf(" %d \n", ch->totalPages()); + printf(" %d \n", CatalogTableINDEX::getNoOfBuckets(tptr)); + printf("\n"); + + ch = (Chunk*) hchunk; + printf("\n"); + printf(" %d \n", ch->totalPages()); + printf(" %d \n", ch->getTotalDataNodes()); + printf("\n"); + return OK; +} + +DbRetVal DatabaseManagerImpl::registerThread() +{ + DbRetVal rv = OK; + if (pMgr_ != NULL) + { + printError(ErrAlready, "Process already registered\n"); + return ErrAlready; + } + pMgr_ = new ProcessManager(); + rv = pMgr_->registerThread(); + if (rv ==OK) { procSlot = pMgr_->getProcSlot(); + printDebug(DM_Process, "Process registed with slot %d\n", procSlot); + } + return rv; +} + +DbRetVal DatabaseManagerImpl::deregisterThread() +{ + DbRetVal rv = OK; + if (pMgr_ != NULL) + { + rv = pMgr_->deregisterThread(procSlot); + delete pMgr_; + pMgr_ = NULL; + } + return rv; +} + +bool DatabaseManagerImpl::isAnyOneRegistered() +{ + if (pMgr_ != NULL) return pMgr_->isAnyOneRegistered(); + return true; +} + + +void DatabaseManagerImpl::printUsageStatistics() +{ + pMgr_->printUsageStatistics(); + tMgr_->printUsageStatistics(); + lMgr_->printUsageStatistics(); +} + +void DatabaseManagerImpl::printDebugLockInfo() +{ + lMgr_->printDebugInfo(); +} + +void DatabaseManagerImpl::printDebugTransInfo() +{ + tMgr_->printDebugInfo(systemDatabase_); +} +void DatabaseManagerImpl::printDebugProcInfo() +{ + pMgr_->printDebugInfo(); +} +void DatabaseManagerImpl::printDebugChunkInfo() +{ + printf(" \n"); +} +ChunkIterator DatabaseManagerImpl::getSystemTableIterator(CatalogTableID id) +{ + Chunk *fChunk = systemDatabase_->getSystemDatabaseChunk(id); + return fChunk->getIterator(); +} + +Chunk* DatabaseManagerImpl::getSystemTableChunk(CatalogTableID id) +{ + return systemDatabase_->getSystemDatabaseChunk(id); +} diff --git a/src/storage/Debug.cxx b/src/storage/Debug.cxx new file mode 100644 index 00000000..dfaaaab4 --- /dev/null +++ b/src/storage/Debug.cxx @@ -0,0 +1,102 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include + +int DebugDM_Alloc = 0; +int DebugDM_VarAlloc = 0; +int DebugDM_Lock = 0; +int DebugDM_Transaction = 0; +int DebugDM_UndoLog = 0; +int DebugDM_RedoLog = 0; +int DebugDM_Index = 0; +int DebugDM_HashIndex = 0; +int DebugDM_SystemDatabase = 0; +int DebugDM_Database = 0; +int DebugDM_Table = 0; +int DebugDM_Predicate = 0; +int DebugDM_TableIterator = 0; +int DebugDM_Process=0; +int DebugDM_Network=0; +int DebugDM_Gateway=0; +int DebugDM_Adapter=0; +int DebugDM_SqlLog=0; + +int printError1(DbRetVal val, char* fname, int lno, char *format, ...) +{ + va_list ap; + char mesgBuf[1024]; + + sprintf(mesgBuf, "%d:%lu:%s:%d:", + os::getpid(), os::getthrid(), fname, lno); + os::write(2, mesgBuf, strlen(mesgBuf)); + + va_start(ap, format); + + int err = ::vsnprintf(mesgBuf, sizeof(mesgBuf), format,ap); + if(err < 0) { + return err; + } + os::write(2, mesgBuf, strlen(mesgBuf)); + strcpy(mesgBuf,"\n"); + os::write(2, mesgBuf, strlen(mesgBuf)); + //2->stderr + return 0; +} + + + +int printDebug1(int module, char *fname, int lno, char *format, ...) +{ + switch(module) { + case DM_Alloc: { if (!DebugDM_Alloc) return 1; break; } + case DM_VarAlloc: { if (!DebugDM_VarAlloc) return 1; break; } + case DM_Lock: { if (!DebugDM_Lock) return 1; break; } + case DM_Transaction: { if (!DebugDM_Transaction) return 1; break; } + case DM_UndoLog: { if (!DebugDM_UndoLog) return 1; break; } + case DM_RedoLog: { if (!DebugDM_RedoLog) return 1; break; } + case DM_HashIndex: { if (!DebugDM_HashIndex) return 1; break; } + case DM_SystemDatabase: { if (!DebugDM_SystemDatabase) return 1; break; } + case DM_Database: { if (!DebugDM_Database) return 1; break; } + case DM_Table: { if (!DebugDM_Table) return 1; break; } + case DM_Iterator: { if (!DebugDM_TableIterator) return 1; break; } + case DM_Predicate: { if (!DebugDM_Predicate) return 1; break; } + case DM_Process: { if (!DebugDM_Process) return 1; break; } + case DM_Network: { if (!DebugDM_Network) return 1; break; } + case DM_Gateway: { if (!DebugDM_Gateway) return 1; break; } + case DM_Adapter: { if (!DebugDM_Adapter) return 1; break; } + case DM_SqlLog: { if (!DebugDM_SqlLog) return 1; break; } + + } + + va_list ap; + char mesgBuf[1024]; + + sprintf(mesgBuf, "D:%s:%d:%lu:%s:%d:", moduleNames[module], + os::getpid(), os::getthrid(), fname, lno); + os::write(1, mesgBuf, strlen(mesgBuf)); + + va_start(ap, format); + + int err = ::vsnprintf(mesgBuf, sizeof(mesgBuf), format,ap); + if(err < 0) { + return err; + } + os::write(1, mesgBuf, strlen(mesgBuf)); + strcpy(mesgBuf,"\n"); + os::write(1, mesgBuf, strlen(mesgBuf)); + //1->stdout + return 0; +} diff --git a/src/storage/FieldList.cxx b/src/storage/FieldList.cxx new file mode 100644 index 00000000..cde18189 --- /dev/null +++ b/src/storage/FieldList.cxx @@ -0,0 +1,326 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include + +//does not check for duplicates +DbRetVal FieldList::append(FieldDef fDef) +{ + FieldNode *newNode = new FieldNode(); + newNode->fldDef = fDef; + newNode->next = NULL; + //If this is the first node, set it as head + if (NULL == head) { head = newNode; return OK; } + + FieldNode *iter = head; + while (NULL != iter->next) iter = iter->next; + iter->next = newNode; + return OK; +} + + +DbRetVal FieldList::remove(const char* fldName) +{ + if (NULL == head) + { + printError(ErrNotExists, "There are no elements in the list. Empty list"); + return ErrNotExists; + } + FieldNode *iter = head, *prev = head; + while (iter->next != NULL) + { + if (0 == strcmp(iter->fldDef.fldName_, fldName)) + { + prev->next = iter->next; + delete iter; + } + prev = iter; + iter = iter->next; + } + if( iter == head) // there is only one node in the list + { + if (0 == strcmp(iter->fldDef.fldName_, fldName)) + { + delete head; + head = NULL; + return OK; + } + + } + if( prev == head) // there are only two node in the list + { + if (0 == strcmp(iter->fldDef.fldName_, fldName)) + { + head->next = NULL; + delete iter; + return OK; + } + } + printError(ErrNotFound, "There are no elements in the list"); + return ErrNotFound; +} + +DbRetVal FieldList::removeAll() +{ + if (NULL == head) return OK; + FieldNode *iter = head, *next = head; + while (iter->next != NULL) + { + next = iter->next; + delete iter; + iter = next; + } + delete iter; //deleting the last element + head = NULL; + return OK; +} + +//-1->if val is passed NULL +//-2->if fld is not present +DbRetVal FieldList::updateBindVal(const char *fldName, void *val ) +{ + if (NULL == val) + { + printError(ErrBadArg, "Value passed is NULL"); + return ErrBadArg; + } + FieldNode *iter = head; + while(NULL != iter) + { + if (strcmp(iter->fldDef.fldName_, fldName) == 0) + { + iter->fldDef.bindVal_ = val; + return OK; + } + iter = iter ->next; + } + printError(ErrNotFound, "Field not present in the list"); + return ErrNotFound; +} + +DbRetVal FieldList::getFieldInfo(const char *fldName, FieldInfo *&info) +{ + FieldNode *iter = head; + while(iter != NULL) + { + if (0 == strcmp(iter->fldDef.fldName_, fldName)) + { + strcpy(info->fldName , iter->fldDef.fldName_); + info->length = iter->fldDef.length_; + info->type = iter->fldDef.type_; + info->offset = getFieldOffset(fldName); + info->isDefault = iter->fldDef.isDefault_; + strcpy(info->defaultValueBuf, iter->fldDef.defaultValueBuf_); + info->isNull = iter->fldDef.isNull_; + info->isPrimary = iter->fldDef.isPrimary_; + return OK; + + } + iter = iter ->next; + } + return ErrNotFound; +} + +int FieldList::getFieldOffset(const char *fldName) +{ + FieldNode *iter = head; + int offset = 0; + while(iter != NULL) + { + if (0 == strcmp(iter->fldDef.fldName_, fldName)) + { + return offset; + } + offset = offset + os::align(iter->fldDef.length_); + iter = iter ->next; + } + return -1; +} +int FieldList::getFieldOffset(int fldpos) +{ + if (fldpos < 1) return -1; + FieldNode *iter = head; + int offset = 0; + int counter =0; + while(iter != NULL) + { + if (counter == fldpos -1) + { + return offset; + } + offset = offset + os::align(iter->fldDef.length_); + iter = iter ->next; + counter++; + } + return -1; +} + +//Returns position of field in the list +//Count starting from 1 +//-1 if field not found in the list +int FieldList::getFieldPosition(const char *fldName) +{ + int position = 1; + FieldNode *iter = head; + while(iter != NULL) + { + if (0 == strcmp(iter->fldDef.fldName_, fldName)) + return position; + position++; + iter = iter->next; + } + + return -1; +} + +int FieldList::getTupleSize() +{ + FieldNode *iter = head; + int offset = 0; + while(iter != NULL) + { + offset = offset + os::align(iter->fldDef.length_); + iter = iter ->next; + } + return offset; +} + + + +DataType FieldList::getFieldType(const char *fldName) +{ + FieldNode *iter = head; + int offset = 0; + while(iter != NULL) + { + if (0 == strcmp(iter->fldDef.fldName_, fldName)) + { + return iter->fldDef.type_; + } + iter = iter ->next; + } + return typeUnknown; +} + +//-1->if field not present in list +size_t FieldList::getFieldLength(const char *fldName) +{ + FieldNode *iter = head; + int offset = 0; + while(iter != NULL) + { + if (0 == strcmp(iter->fldDef.fldName_, fldName)) + { + return iter->fldDef.length_; + } + iter = iter ->next; + } + return -1; +} + + +//No check for duplicates +//TODO::User exposed so check for duplicates +DbRetVal FieldNameList::append(const char *name) +{ + FieldNameNode *newNode = new FieldNameNode(); + strcpy(newNode->fldName, name); + newNode->next = NULL; + //If this is the first node, set it as head + if (NULL == head) { head = newNode; return OK; } + + FieldNameNode *it = head; + while (NULL != it->next) it = it->next; + it->next = newNode; + return OK; +} +//-1 -> if there is nothing in list +//-2 -> if it is not present in list +DbRetVal FieldNameList::remove(const char* name) +{ + if (NULL == head) + { + printError(ErrNotExists, "List is empty"); + return ErrNotExists; + } + FieldNameNode *ite = head, *prev = head; + while (ite->next != NULL) + { + if (0 == strcmp(ite->fldName, name)) + { + prev->next = ite->next; + delete ite; + } + prev = ite; + ite = ite->next; + } + if( ite == head) // there is only one node in the list + { + if (0 == strcmp(ite->fldName, name)) + { + delete head; + head = NULL; + return OK; + } + + } + if( prev == head) // there are only two node in the list + { + if (0 == strcmp(ite->fldName, name)) + { + head->next = NULL; + delete ite; + return OK; + } + } + printError(ErrNotFound, "Field name %s not present in the list", name); + return ErrNotFound; +} + +DbRetVal FieldNameList::removeAll() +{ + if (NULL == head) return OK; + FieldNameNode *iter = head, *next = head; + while (iter->next != NULL) + { + next = iter->next; + delete iter; + iter = next; + } + delete iter; //deleting the last element + head = NULL; + return OK; +} + +char* FieldNameList::nextFieldName() +{ + if (iter == NULL) return NULL; + FieldNameNode *node = iter; + iter = iter ->next; + return node->fldName; +} + +int FieldNameList::size() +{ + FieldNameNode *it = head; + if (NULL == it) return 0; + int count = 1; + while (NULL != it->next) {it = it->next; count++;} + return count; +} diff --git a/src/storage/HashIndex.cxx b/src/storage/HashIndex.cxx new file mode 100644 index 00000000..735902fc --- /dev/null +++ b/src/storage/HashIndex.cxx @@ -0,0 +1,447 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +/* Defines `hashpjw' function by P.J. Weinberger + [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, + */ + +unsigned int hashString(char *strVal) +{ + unsigned int hval, g; + hval = 0; + char *str =strVal; + while (*str != '\0') + { + hval <<= 4; + hval += (unsigned int) *str++; + g = hval & ((unsigned int) 0xf << (32 - 4)); + if (g != 0) + { + hval ^= g >> (32 - 8); + hval ^= g; + } + } + return hval; +} +unsigned int hashBinary(char *strVal, int length) +{ + unsigned int hval, g; + hval = 0; + char *str =strVal; + int iter = 0; + while (iter != length) + { + hval <<= 4; + hval += (unsigned int) *str++; + g = hval & ((unsigned int) 0xf << (32 - 4)); + if (g != 0) + { + hval ^= g >> (32 - 8); + hval ^= g; + } + iter++; + } + return hval; +} + +unsigned int HashIndex::computeHashBucket(DataType type, void *key, int noOfBuckets, int length) + +{ + switch(type) + { + case typeInt: + { + int val = *(int*)key; + return val % noOfBuckets; + break; + } + case typeLong: + { + long val = *(long*)key; + return val % noOfBuckets; + break; + } + case typeULong: + { + unsigned long val = *(unsigned long*)key; + return val % noOfBuckets; + break; + } + case typeLongLong: + { + long long val = *(long long*)key; + return val % noOfBuckets; + break; + } + case typeShort: + { + short val = *(short*)key; + return val % noOfBuckets; + break; + } + case typeByteInt: + { + ByteInt val = *(ByteInt*)key; + return val % noOfBuckets; + break; + } + case typeDate: + { + int val = *(int*)key; + return val % noOfBuckets; + break; + } + case typeTime: + { + int val = *(int*)key; + return val % noOfBuckets; + break; + } + case typeTimeStamp: + { + TimeStamp val = *(TimeStamp*)key; + //TODO return val % noOfBuckets; + break; + } + case typeDouble: + { + //TODO + break; + } + case typeFloat: + { + //TODO + break; + } + case typeDecimal: + { + //TODO::for porting + } + case typeString: + { + unsigned int val = hashString((char*)key); + return val % noOfBuckets; + } + case typeComposite: + case typeBinary: + { + unsigned int val = hashBinary((char*)key, length); + return val % noOfBuckets; + } + default: + { + break; + } + } + return -1; +} + +DbRetVal HashIndex::insert(TableImpl *tbl, Transaction *tr, void *indexPtr, IndexInfo *indInfo, void *tuple, bool undoFlag) +{ + HashIndexInfo *info = (HashIndexInfo*) indInfo; + INDEX *iptr = (INDEX*)indexPtr; + DbRetVal rc = OK; + int noOfBuckets = info->noOfBuckets; + int offset = info->fldOffset; + DataType type = info->type; + printDebug(DM_HashIndex, "Inserting hash index node for %s", iptr->indName_); + ChunkIterator citer = CatalogTableINDEX::getIterator(indexPtr); + Bucket* buckets = (Bucket*)citer.nextElement(); + void *keyPtr =(void*)((char*)tuple + offset); + + int bucketNo = computeHashBucket(type, + keyPtr, noOfBuckets, info->compLength); + printDebug(DM_HashIndex, "HashIndex insert bucketno %d", bucketNo); + Bucket *bucket = &(buckets[bucketNo]); + + int ret = bucket->mutex_.getLock(tbl->db_->procSlot); + if (ret != 0) + { + printError(ErrLockTimeOut,"Unable to acquire bucket Mutex for bucket %d",bucketNo); + return ErrLockTimeOut; + } + HashIndexNode *head = (HashIndexNode*) bucket->bucketList_; + if (info->isUnique) + { + BucketList list(head); + BucketIter iter = list.getIterator(); + HashIndexNode *node; + void *bucketTuple; + printDebug(DM_HashIndex, "HashIndex insert Checking for unique"); + while((node = iter.next()) != NULL) + { + bucketTuple = node->ptrToTuple_; + if (AllDataType::compareVal((void*)((char*)bucketTuple +offset), + (void*)((char*)tuple +offset), OpEquals,type, info->compLength)) + { + printError(ErrUnique, "Unique key violation"); + bucket->mutex_.releaseLock(tbl->db_->procSlot); + return ErrUnique; + } + } + } + + printDebug(DM_HashIndex, "HashIndex insert into bucket list"); + if (!head) + { + printDebug(DM_HashIndex, "HashIndex insert head is empty"); + DbRetVal rv = OK; + HashIndexNode *firstNode= (HashIndexNode*)(((Chunk*)iptr->hashNodeChunk_)->allocate(tbl->db_, &rv)); + if (firstNode == NULL) + { + bucket->mutex_.releaseLock(tbl->db_->procSlot); + return rv; + } + firstNode->ptrToKey_ = keyPtr; + firstNode->ptrToTuple_ = tuple; + firstNode->next_ = NULL; + bucket->bucketList_ = (HashIndexNode*)firstNode; + printDebug(DM_HashIndex, "HashIndex insert new node %x in empty bucket", bucket->bucketList_); + } + else + { + BucketList list(head); + rc = list.insert((Chunk*)iptr->hashNodeChunk_, tbl->db_, keyPtr, tuple); + if (rc !=OK) { + bucket->mutex_.releaseLock(tbl->db_->procSlot); + return rc; + } + + } + if (undoFlag) { + + rc = tr->appendLogicalUndoLog(tbl->sysDB_, InsertHashIndexOperation, + tuple, sizeof(void*), indexPtr); + if (rc !=OK) + { + BucketList list(head); + rc = list.remove((Chunk*)iptr->hashNodeChunk_, tbl->db_, keyPtr); + if (rc !=OK) printError(ErrSysFatal, "double failure on undo log insert followed by hash bucket list remove\n"); + } + } + + bucket->mutex_.releaseLock(tbl->db_->procSlot); + return rc; +} + + +DbRetVal HashIndex::remove(TableImpl *tbl, Transaction *tr, void *indexPtr, IndexInfo *indInfo, void *tuple, bool undoFlag) +{ + INDEX *iptr = (INDEX*)indexPtr; + + HashIndexInfo *info = (HashIndexInfo*) indInfo; + DataType type = info->type; + int offset = info->fldOffset; + int noOfBuckets = info->noOfBuckets; + + ChunkIterator citer = CatalogTableINDEX::getIterator(indexPtr); + Bucket* buckets = (Bucket*)citer.nextElement(); + void *keyPtr =(void*)((char*)tuple + offset); + + int bucket = HashIndex::computeHashBucket(type, keyPtr, noOfBuckets, info->compLength); + + Bucket *bucket1 = &buckets[bucket]; + + int ret = bucket1->mutex_.getLock(tbl->db_->procSlot); + if (ret != 0) + { + printError(ErrLockTimeOut,"Unable to acquire bucket Mutex for bucket %d",bucket); + return ErrLockTimeOut; + } + HashIndexNode *head = (HashIndexNode*) bucket1->bucketList_; + + if (!head) { printError(ErrNotExists, "Hash index does not exist:should never happen\n"); return ErrNotExists; } + BucketList list(head); + printDebug(DM_HashIndex, "Removing hash index node from head %x", head); + + DbRetVal rc = list.remove((Chunk*)iptr->hashNodeChunk_, tbl->db_, keyPtr); + if (SplCase == rc) + { + printDebug(DM_HashIndex, "Removing hash index node from head with only none node"); + bucket1->bucketList_ = 0; + rc = OK; + } + if (undoFlag) { + rc =tr->appendLogicalUndoLog(tbl->sysDB_, DeleteHashIndexOperation, + tuple, sizeof(void*), indexPtr); + if (rc !=OK) + { + //TODO::add it back to the bucketlist + } + } + bucket1->mutex_.releaseLock(tbl->db_->procSlot); + + return rc; +} + +DbRetVal HashIndex::update(TableImpl *tbl, Transaction *tr, void *indexPtr, IndexInfo *indInfo, void *tuple, bool undoFlag) +{ + INDEX *iptr = (INDEX*)indexPtr; + + HashIndexInfo *info = (HashIndexInfo*) indInfo; + DataType type = info->type; + int offset = info->fldOffset; + int noOfBuckets = info->noOfBuckets; + + //check whether the index key is updated or not + //if it is not updated return from here + void *keyPtr =(void*)((char*)tuple + offset); + char *kPtr= (char*)keyPtr; + //Iterate through the bind list and check + FieldIterator idxFldIter = info->idxFldList.getIterator(); + char *keyBindBuffer = (char*) malloc(info->compLength); + void *keyStartBuffer = (void*) keyBindBuffer; + bool keyUpdated = false; + while (idxFldIter.hasElement()) + { + FieldDef idef = idxFldIter.nextElement(); + FieldIterator fldIter = tbl->fldList_.getIterator(); + while (fldIter.hasElement()) + { + FieldDef def = fldIter.nextElement(); + if (0 == strcmp(def.fldName_, idef.fldName_)) + { + if (NULL != def.bindVal_) { + AllDataType::copyVal(keyBindBuffer, def.bindVal_, + def.type_, def.length_); + keyBindBuffer = keyBindBuffer + AllDataType::size(def.type_, + def.length_); + keyUpdated = true; + break; + } + } + } + } + if (!keyUpdated) + { + //printf("PRABA::key not updated\n"); + free(keyStartBuffer); + return OK; + } + //printf("PRABA::it is wrong coming here\n"); + bool result = AllDataType::compareVal(kPtr, keyStartBuffer, + OpEquals, info->type, info->compLength); + if (result) return OK; + + printDebug(DM_HashIndex, "Updating hash index node: Key value is updated"); + + ChunkIterator citer = CatalogTableINDEX::getIterator(indexPtr); + + Bucket* buckets = (Bucket*)citer.nextElement(); + + //remove the node whose key is updated + int bucketNo = computeHashBucket(type, + keyPtr, noOfBuckets, info->compLength); + printDebug(DM_HashIndex, "Updating hash index node: Bucket for old value is %d", bucketNo); + Bucket *bucket = &buckets[bucketNo]; + + //it may run into deadlock, when two threads updates tuples which falls in + //same buckets.So take both the mutex one after another, which will reduce the + //deadlock window. + int ret = bucket->mutex_.getLock(tbl->db_->procSlot); + if (ret != 0) + { + printError(ErrLockTimeOut,"Unable to acquire bucket Mutex for bucket %d",bucketNo); + return ErrLockTimeOut; + } + //insert node for the updated key value + int newBucketNo = computeHashBucket(type, + keyStartBuffer, noOfBuckets); + printDebug(DM_HashIndex, "Updating hash index node: Bucket for new value is %d", newBucketNo); + + Bucket *bucket1 = &buckets[newBucketNo]; + bucket1->mutex_.getLock(tbl->db_->procSlot); + if (ret != 0) + { + printError(ErrLockTimeOut,"Unable to acquire bucket Mutex for bucket %d",newBucketNo); + return ErrLockTimeOut; + } + + HashIndexNode *head1 = (HashIndexNode*) bucket->bucketList_; + if (head1) + { + BucketList list1(head1); + printDebug(DM_HashIndex, "Updating hash index node: Removing node from list with head %x", head1); + list1.remove((Chunk*)iptr->hashNodeChunk_, tbl->db_, keyPtr); + } + else + { + printError(ErrSysInternal,"Update: Bucket list is null"); + return ErrSysInternal; + } + DbRetVal rc = OK; + if (undoFlag) { + rc = tr->appendLogicalUndoLog(tbl->sysDB_, DeleteHashIndexOperation, + tuple, sizeof(void*), indexPtr); + if (rc !=OK) + { + //TODO::add it back to the bucket list + bucket1->mutex_.releaseLock(tbl->db_->procSlot); + bucket->mutex_.releaseLock(tbl->db_->procSlot); + return rc; + } + } + HashIndexNode *head2 = (HashIndexNode*) bucket1->bucketList_; + //Note:: the tuple will be in the same address location + //so not changing the keyptr and tuple during append + //only bucket where this node resides will only change + //if the index key is updated. + if (!head2) + { + DbRetVal rv = OK; + HashIndexNode *firstNode= (HashIndexNode*)(((Chunk*)iptr->hashNodeChunk_)->allocate(tbl->db_, &rv)); + if (firstNode == NULL) + { + printError(rv, "Error in allocating hash node"); + bucket1->mutex_.releaseLock(tbl->db_->procSlot); + bucket->mutex_.releaseLock(tbl->db_->procSlot); + return rv; + } + firstNode->ptrToKey_ = keyPtr; + firstNode->ptrToTuple_ = tuple; + firstNode->next_ = NULL; + bucket1->bucketList_ = (HashIndexNode*)firstNode; + printDebug(DM_HashIndex, "Updating hash index node: Adding new node %x:Head is empty", firstNode); + } + else + { + BucketList list2(head2); + printDebug(DM_HashIndex, "Updating hash index node: Adding node to list with head %x", head2); + list2.insert((Chunk*)iptr->hashNodeChunk_, tbl->db_, keyPtr, tuple); + } + if (undoFlag) { + + rc = tr->appendLogicalUndoLog(tbl->sysDB_, InsertHashIndexOperation, + tuple, sizeof(void*), indexPtr); + if (rc !=OK) + { + //TODO::revert back the changes:delete and add the node + remove the logical undo log + //of the DeleteHashIndexOperation + } + } + bucket1->mutex_.releaseLock(tbl->db_->procSlot); + bucket->mutex_.releaseLock(tbl->db_->procSlot); + + return rc; +} diff --git a/src/storage/Index.cxx b/src/storage/Index.cxx new file mode 100644 index 00000000..01d886c0 --- /dev/null +++ b/src/storage/Index.cxx @@ -0,0 +1,34 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include + +HashIndex* Index::hIdx = NULL; +long Index::usageCount = 0; + +Index* Index::getIndex(IndexType type) +{ + if (type == hashIndex) + { + if (NULL == hIdx) hIdx = new HashIndex(); + return hIdx; + } + return NULL; +} + + diff --git a/src/storage/LockListIter.cxx b/src/storage/LockListIter.cxx new file mode 100644 index 00000000..640e5925 --- /dev/null +++ b/src/storage/LockListIter.cxx @@ -0,0 +1,29 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include + +LockHashNode* LockListIter::next() +{ + if (iter == NULL) return NULL; + LockHashNode *node = iter; + iter = iter ->next_; + return node; +} diff --git a/src/storage/LockManager.cxx b/src/storage/LockManager.cxx new file mode 100644 index 00000000..4e08eec6 --- /dev/null +++ b/src/storage/LockManager.cxx @@ -0,0 +1,675 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +Bucket* LockManager::getLockBucket(void *tuple) +{ + int noOfBuckets = LOCK_BUCKET_SIZE; + Bucket* buckets = systemDatabase_->getLockHashBuckets(); + unsigned long key =(unsigned long)tuple ; + int bucketNo = HashIndex::computeHashBucket(typeULong, &key, noOfBuckets); + + Bucket *bucket = &(buckets[bucketNo]); + printDebug(DM_Lock, "getLockBucket bucketno:%d bucket:%x",bucketNo, bucket); + return bucket; +} + +void LockManager::printUsageStatistics() +{ + Bucket* buckets = systemDatabase_->getLockHashBuckets(); + Bucket* bucket; + LockHashNode *lockNode; + int nodeCount =0, bucketCount =0; + for (int i =0; i< LOCK_BUCKET_SIZE; i++) + { + bucket = &(buckets[i]); + lockNode = (LockHashNode*) bucket->bucketList_; + if (lockNode) bucketCount++; else continue; + while (NULL != lockNode) { nodeCount++; lockNode = lockNode->next_; } + } + printf("\n"); + printf(" %d \n", LOCK_BUCKET_SIZE); + printf(" %d \n", bucketCount); + printf(" %d \n", nodeCount); + printf("\n"); + +} + +void LockManager::printDebugInfo() +{ + Bucket* buckets = systemDatabase_->getLockHashBuckets(); + Bucket* bucket; + LockHashNode *lockNode; + int nodeCount =0, bucketCount =0; + printf("\n"); + for (int i =0; i< LOCK_BUCKET_SIZE; i++) + { + nodeCount =0; + bucket = &(buckets[i]); + //if (bucket) bucketCount++; else continue; + lockNode = (LockHashNode*) bucket->bucketList_; + + while (NULL != lockNode) + { + nodeCount++; + lockNode->print(); + lockNode = lockNode->next_; + } + if (nodeCount) { + bucketCount++; + printf(" \n"); + printf(" %d \n", i); + printf(" %d \n", nodeCount); + printf(" \n"); + } + } + + printf(" %d \n", bucketCount); + Chunk *chunk = systemDatabase_->getSystemDatabaseChunk(LockTableId); + printf(" %d \n", chunk->totalPages()); + printf("\n"); + +} + +DbRetVal LockManager::getSharedLock(void *tuple, Transaction **trans) +{ + //get the bucket list + //take the bucket mutex for read + //go the the next level bucket list + //get the bucket iterator + //go the node where the lock info resides + //check which mode the lock is taken + // if shared then + // upgrade the bucket mutex to write + // take it and increment the readers count + // release bucket mutex and exit + // if exclusive then + // go into the loop + // upgrade the bucket mutex to write + // increment waitReaders count + // release the bucket mutex + // wait for timeout period or (takes shared lock and release it ) till it becomes free. + // if times out + // take bucket mutex for write + // decrement waitReaders count + // releaese bucket mutex + + // return + // if it becomes free + // take bucket mutex for write + // increment readers + // releaese bucket mutex + + // return + LockInfo linfo; + linfo.noOfReaders_ = 1; + //keeping it ready for the allocation, because when + //lock node is not present in the list, then it means we are the first + //to acquire lock so for sure we will get it. + printDebug(DM_Lock, "LockManager::getSharedLock Begin"); + Bucket *bucket = getLockBucket(tuple); + int lockRet = bucket->mutex_.getLock(systemDatabase_->procSlot); + if (lockRet != 0) + { + printDebug(DM_Lock, "LockManager::getSharedLock:End-Unable to get mutex"); + printError(ErrLockTimeOut,"Unable to acquire bucket mutex"); + return ErrLockTimeOut; + } + LockHashNode *lockNode = (LockHashNode*) bucket->bucketList_; + if (NULL == lockNode) + { + DbRetVal rv = OK; + LockHashNode *node = allocLockNode(linfo, tuple, &rv); + if (NULL == node) + { + printError(rv, "Could not allocate Lock node"); + return rv; + } + printDebug(DM_Lock, "Bucket list is null: Allocating new LockHashNode %x", node); + bucket->bucketList_ = (void*)node; //make it as head + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + rv = OK; + if (trans != NULL) + rv = (*trans)->insertIntoHasList(systemDatabase_, node); + if (rv !=OK) linfo.noOfReaders_--; + printDebug(DM_Lock, "LockManager::getSharedLock End"); + return rv; + } + LockHashNode *cachedLockNode = NULL; + + LockHashNode *iter = lockNode; + //Iterate though the list and find the element's lock info + while(iter != NULL) + { + if(iter->ptrToTuple_ == tuple) + { + if (iter->lInfo_.noOfReaders_ == -1) + { + + iter->lInfo_.waitReaders_++; + cachedLockNode = iter; + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + if (trans != NULL) (*trans)->updateWaitLock(iter); + printDebug(DM_Lock, "lock node:%x exclusive locked",iter); + break; + } + else if (iter->lInfo_.noOfReaders_ == 0) + { + if(iter->lInfo_.waitWriters_ >0) + { + iter->lInfo_.waitReaders_++; + cachedLockNode = iter; + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + if (trans != NULL) (*trans)->updateWaitLock(iter); + printDebug(DM_Lock, "lock node:%x Writers waiting.",iter); + break; + } + else + { + iter->lInfo_.noOfReaders_++; + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + DbRetVal rv = OK; + if (trans != NULL) + rv = (*trans)->insertIntoHasList(systemDatabase_, iter); + if (rv != OK) iter->lInfo_.noOfReaders_--; + printDebug(DM_Lock, "lock node:%x First to take shared lock", + iter); + printDebug(DM_Lock, "LockManager::getSharedLock End"); + return rv; + } + }else + { + iter->lInfo_.noOfReaders_++; + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + DbRetVal rv = OK; + if (trans != NULL) + rv = (*trans)->insertIntoHasList(systemDatabase_, iter); + if (rv != OK) iter->lInfo_.noOfReaders_--; + printDebug(DM_Lock, "lock node:%x incr readers",iter); + printDebug(DM_Lock, "LockManager::getSharedLock End"); + return rv; + } + } + printDebug(DM_Lock, "Finding the lock node. iter:%x",iter); + iter = iter->next_; + } + if (NULL == cachedLockNode) + { + DbRetVal rv =OK; + LockHashNode *node = allocLockNode(linfo, tuple, &rv); + if (NULL == node) + { + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + printError(rv, "Could not allocate Lock node"); + if (trans != NULL) (*trans)->removeWaitLock(); + return rv; + } + printDebug(DM_Lock,"Not Found.Created new lock node:%x",node); + LockHashNode *it = lockNode; + while (NULL != it->next_) it = it->next_; + it->next_ = node; + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + rv = OK; + if (trans != NULL) + rv = (*trans)->insertIntoHasList(systemDatabase_, node); + if (rv != OK) linfo.noOfReaders_--; + if (trans != NULL) (*trans)->removeWaitLock(); + printDebug(DM_Lock, "LockManager::getSharedLock End"); + return rv; + } + //bucket->mutex_.releaseLock(); + int tries = 0; + int ret = 0; + struct timeval timeout; + timeout.tv_sec = Conf::config.getLockSecs(); + timeout.tv_usec = Conf::config.getLockUSecs(); + + //printDebug(DM_Lock, "Trying to get mutex: for bucket %x\n", bucket); + while (tries < Conf::config.getLockRetries()) + { + lockRet = bucket->mutex_.getLock(systemDatabase_->procSlot); + if (lockRet != 0) + { + printDebug(DM_Lock, "Mutex is waiting for long time:May be deadlock"); + printDebug(DM_Lock, "LockManager::getSharedLock End"); + printError(ErrLockTimeOut, "Unable to get bucket mutex"); + if (trans != NULL) (*trans)->removeWaitLock(); + return ErrLockTimeOut; + } + if (cachedLockNode->lInfo_.noOfReaders_ == 0) + { + //if there are waiters allow then to take the lock + if (cachedLockNode->lInfo_.waitWriters_ <0) + { + cachedLockNode->lInfo_.noOfReaders_++; + cachedLockNode->lInfo_.waitReaders_--; + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + DbRetVal rv = OK; + if (trans != NULL) + rv = (*trans)->insertIntoHasList(systemDatabase_, cachedLockNode); + if (rv !=OK) { + cachedLockNode->lInfo_.noOfReaders_--; + cachedLockNode->lInfo_.waitReaders_++; + if (trans != NULL) (*trans)->removeWaitLock(); + return rv; + } + if (trans != NULL) (*trans)->removeWaitLock(); + printDebug(DM_Lock, "LockManager::getSharedLock End"); + return OK; + } + } else if (cachedLockNode->lInfo_.noOfReaders_ == -1) + { + if (trans !=NULL && (*trans)->findInHasList(systemDatabase_, cachedLockNode)) + { + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + if (trans != NULL) (*trans)->removeWaitLock(); + printDebug(DM_Lock, "LockManager::getSharedLock End"); + return OK; + } + } else + { + cachedLockNode->lInfo_.noOfReaders_++; + cachedLockNode->lInfo_.waitReaders_--; + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + DbRetVal rv =OK; + if (trans != NULL) + rv = (*trans)->insertIntoHasList(systemDatabase_, cachedLockNode); + if (rv !=OK) { + cachedLockNode->lInfo_.noOfReaders_--; + cachedLockNode->lInfo_.waitReaders_++; + } + if (trans != NULL) (*trans)->removeWaitLock(); + printDebug(DM_Lock, "LockManager::getSharedLock End"); + return rv; + } + + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + os::select(0, 0, 0, 0, &timeout); + tries++; + printDebug(DM_Lock, "Trying to lock the lock node:%x iteration:%d",cachedLockNode, tries); + } + printDebug(DM_Lock, "Mutex is waiting for long time:May be deadlock"); + printDebug(DM_Lock, "LockManager::getSharedLock End"); + printError(ErrLockTimeOut, "Unable to acquire lock for long time.Timed out"); + if (trans != NULL) (*trans)->removeWaitLock(); + return ErrLockTimeOut; + +} + +DbRetVal LockManager::getExclusiveLock(void *tuple, Transaction **trans) +{ + LockInfo linfo; + linfo.noOfReaders_ = -1; + printDebug(DM_Lock, "LockManager::getExclusiveLock Begin"); + //keeping it ready for the allocation, because when + //lock node is not present in the list, then it means we are the first + //to acquire lock so for sure we will get it. + + Bucket *bucket = getLockBucket(tuple); + int lockRet = bucket->mutex_.getLock(systemDatabase_->procSlot); + if (lockRet != 0) + { + printDebug(DM_Lock, "Unable to acquire bucket mutex:May be deadlock"); + printError(ErrLockTimeOut, "Unable to acquire bucket mutex"); + return ErrLockTimeOut; + } + LockHashNode *lockNode = (LockHashNode*) bucket->bucketList_; + if (NULL == lockNode) + { + DbRetVal rv = OK; + LockHashNode *node = allocLockNode(linfo, tuple, &rv); + if (NULL == node) + { + printError(rv, "Could not allocate Lock node"); + return rv; + } + printDebug(DM_Lock, "No head. So new lock node allocated:%x",node); + bucket->bucketList_ = (void*)node; //make it as head + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + rv =OK; + if (trans != NULL) + rv = (*trans)->insertIntoHasList(systemDatabase_, node); + if (rv !=OK) linfo.noOfReaders_ = 0; + printDebug(DM_Lock, "LockManager::getExclusiveLock End"); + return rv; + + } + LockHashNode *cachedLockNode = NULL; + + LockHashNode *iter = lockNode; + //Iterate though the list and find the element's lock info + while(iter != NULL) + { + if(iter->ptrToTuple_ == tuple) + { + if (iter->lInfo_.noOfReaders_ != 0) + { + iter->lInfo_.waitWriters_++; + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + if (trans != NULL) (*trans)->updateWaitLock(iter); + cachedLockNode = iter; + printDebug(DM_Lock, "Either some one has exclusive or shared lock:%x",iter); + break; + } + else + { + iter->lInfo_.noOfReaders_ = -1; + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + DbRetVal rv =OK; + if (trans != NULL) + rv = (*trans)->insertIntoHasList(systemDatabase_, iter); + if (rv != OK) iter->lInfo_.noOfReaders_ = 0; + printDebug(DM_Lock, "LockManager::getExclusiveLock End"); + return rv; + } + } + printDebug(DM_Lock, "Finding the lock node. iter:%x",iter); + iter = iter->next_; + } + if (NULL == cachedLockNode) + { + DbRetVal rv =OK; + LockHashNode *node = allocLockNode(linfo, tuple, &rv); + if (NULL == node) + { + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + if (trans != NULL) (*trans)->updateWaitLock(NULL); + printError(rv, "Could not allocate Lock node"); + return rv; + } + printDebug(DM_Lock, "Not Found:Creating new lock node:%x",node); + LockHashNode *it = lockNode; + while (NULL != it->next_) it = it->next_; + it->next_ = node; + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + rv = OK; + if (trans != NULL) + rv = (*trans)->insertIntoHasList(systemDatabase_, node); + if (rv != OK) linfo.noOfReaders_ = 0; + if (trans != NULL) (*trans)->removeWaitLock(); + printDebug(DM_Lock, "LockManager::getExclusiveLock End"); + return rv; + } + //bucket->mutex_.releaseLock(); + int tries = 0; + int ret = 0; + struct timeval timeout; + timeout.tv_sec = Conf::config.getLockSecs(); + timeout.tv_usec = Conf::config.getLockUSecs(); + + while (tries < Conf::config.getLockRetries()) + { + lockRet = bucket->mutex_.getLock(systemDatabase_->procSlot); + if (lockRet != 0) + { + printError(ErrLockTimeOut, "Unable to get bucket mutex"); + return ErrLockTimeOut; + } + if (cachedLockNode->lInfo_.noOfReaders_ == 0) + { + cachedLockNode->lInfo_.noOfReaders_ = -1; + cachedLockNode->lInfo_.waitWriters_--; + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + DbRetVal rv ; + if (trans != NULL) + rv = (*trans)->insertIntoHasList(systemDatabase_, cachedLockNode); + if (trans != NULL) (*trans)->removeWaitLock(); + printDebug(DM_Lock, "LockManager::getExclusiveLock End"); + return rv; + }else if ( cachedLockNode->lInfo_.noOfReaders_ == 1) + { + if (trans !=NULL && (*trans)->findInHasList(systemDatabase_, cachedLockNode)) + { + printDebug(DM_Lock, "upgrading shared to exclusive lock:%x", + cachedLockNode); + //upgrade it to exclusive lock + cachedLockNode->lInfo_.noOfReaders_ = -1; + cachedLockNode->lInfo_.waitWriters_--; + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + if (trans != NULL) (*trans)->removeWaitLock(); + printDebug(DM_Lock, "LockManager::getExclusiveLock End"); + return OK; + } + if (trans ==NULL && ProcessManager::hasLockList.exists(cachedLockNode->ptrToTuple_)) + { + printDebug(DM_Lock, "upgrading shared to exclusive lock:%x", + cachedLockNode); + //upgrade it to exclusive lock + cachedLockNode->lInfo_.noOfReaders_ = -1; + cachedLockNode->lInfo_.waitWriters_--; + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + if (trans != NULL) (*trans)->removeWaitLock(); + printDebug(DM_Lock, "LockManager::getExclusiveLock End"); + return OK; + } + }else if ( cachedLockNode->lInfo_.noOfReaders_ == -1) + { + if (trans !=NULL && (*trans)->findInHasList(systemDatabase_, cachedLockNode)) + { + printDebug(DM_Lock, "You already have exclusive lock:%x", + cachedLockNode); + cachedLockNode->lInfo_.waitWriters_--; + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + if (trans != NULL) (*trans)->removeWaitLock(); + printDebug(DM_Lock, "LockManager::getExclusiveLock End"); + return OK; + } + if (trans ==NULL && ProcessManager::hasLockList.exists(cachedLockNode->ptrToTuple_)) + { + printDebug(DM_Lock, "You already have exclusive lock:%x", + cachedLockNode); + cachedLockNode->lInfo_.waitWriters_--; + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + if (trans != NULL) (*trans)->removeWaitLock(); + printDebug(DM_Lock, "LockManager::getExclusiveLock End"); + return OK; + } + } + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + os::select(0, 0, 0, 0, &timeout); + tries++; + printDebug(DM_Lock, "Trying to lock the lock node:%x iteration:%d",cachedLockNode, tries); + } + printDebug(DM_Lock, "LockManager::getExclusiveLock End"); + if (trans != NULL) (*trans)->removeWaitLock(); + printError(ErrLockTimeOut, "Unable to acquire lock for long time.Timed out"); + return ErrLockTimeOut; +} + +DbRetVal LockManager::releaseLock(void *tuple) +{ + LockInfo linfo; + linfo.noOfReaders_ = 0; + //keeping it ready for the allocation, because when + //lock node is not present in the list, then it means we are the first + //to acquire lock so for sure we will get it. + printDebug(DM_Lock, "LockManager:releaseLock Start"); + Bucket *bucket = getLockBucket(tuple); + printDebug(DM_Lock,"Bucket is %x", bucket); + int lockRet = bucket->mutex_.getLock(systemDatabase_->procSlot); + if (lockRet != 0) + { + printDebug(DM_Lock, "Mutex is waiting for long time:May be deadlock"); + printDebug(DM_Lock, "LockManager:releaseLock End"); + printError(ErrLockTimeOut, "Unable to get bucket mutex"); + return ErrLockTimeOut; + } + LockHashNode *lockNode = (LockHashNode*) bucket->bucketList_; + if (NULL == lockNode) + { + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + printDebug(DM_Lock, "LockManager:releaseLock End"); + printError(ErrSysFatal, "Lock Element Not found: Probable Data Corruption.\n"); + return ErrSysFatal; + } + + LockHashNode *iter = lockNode; + //Iterate though the list and find the element's lock info + while(iter != NULL) + { + if(iter->ptrToTuple_ == tuple) + { + + if (iter->lInfo_.noOfReaders_ == -1) + { + iter->lInfo_.noOfReaders_ = 0; + if (iter->lInfo_.waitWriters_ == 0 || iter->lInfo_.waitReaders_ ==0) + { + deallocLockNode(iter, bucket); + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + printDebug(DM_Lock, "Releasing exclusive lock and dealloc node:%x", + iter); + printDebug(DM_Lock, "LockManager:releaseLock End"); + return OK; + } + else + { + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + printDebug(DM_Lock, "Releasing exclusive lock"); + printDebug(DM_Lock, "LockManager:releaseLock End"); + return OK; + } + } + else if (iter->lInfo_.noOfReaders_ == 1) + { + iter->lInfo_.noOfReaders_ = 0; + if (iter->lInfo_.waitWriters_ == 0 || iter->lInfo_.waitReaders_ ==0) + { + deallocLockNode(iter, bucket); + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + printDebug(DM_Lock, "Releasing read lock and dealloc node:%x",iter); + printDebug(DM_Lock, "LockManager:releaseLock End"); + return OK; + } + } + else + { + iter->lInfo_.noOfReaders_--; + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + printDebug(DM_Lock, "Decrementing read lock:%x",iter); + printDebug(DM_Lock, "LockManager:releaseLock End"); + return OK; + } + + } + printDebug(DM_Lock, "Finding the lock node. iter:%x",iter); + iter = iter->next_; + } + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + printError(ErrSysFatal, "Lock Element Not found: Probable Data Corruption"); + return ErrSysFatal; +} + +DbRetVal LockManager::isExclusiveLocked(void *tuple, Transaction **trans, bool &status) +{ + Bucket *bucket = getLockBucket(tuple); + printDebug(DM_Lock,"Bucket is %x", bucket); + int lockRet = bucket->mutex_.getLock(systemDatabase_->procSlot); + if (lockRet != 0) + { + printDebug(DM_Lock, "Mutex is waiting for long time:May be deadlock"); + printDebug(DM_Lock, "LockManager:releaseLock End"); + printError(ErrLockTimeOut, "Unable to get bucket mutex"); + return ErrLockTimeOut; + } + LockHashNode *lockNode = (LockHashNode*) bucket->bucketList_; + if (NULL == lockNode) + { + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + printDebug(DM_Lock, "bucketList is empty. so data element not locked"); + status = false; + return OK; + } + + LockHashNode *iter = lockNode; + //Iterate though the list and find the element's lock info + //Only exclusive locks are checked. shared locks are not considered for this + while(iter != NULL) + { + if(iter->ptrToTuple_ == tuple) + { + if (iter->lInfo_.noOfReaders_ == -1) + { + if (trans != NULL && (*trans)->findInHasList(systemDatabase_, iter)) + { + printDebug(DM_Lock, "You already have exclusive Lock: %x", iter); + status = false; + } + else + status = true; + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + return OK; + } + } + printDebug(DM_Lock, "Finding the lock node. iter:%x",iter); + iter = iter->next_; + } + bucket->mutex_.releaseLock(systemDatabase_->procSlot); + status = false; + return OK; +} + +LockHashNode* LockManager::allocLockNode(LockInfo &info, void *tuple, DbRetVal *rv) +{ + //allocate lock node + Chunk *chunk = systemDatabase_->getSystemDatabaseChunk(LockTableId); + LockHashNode *node = (LockHashNode*)chunk->allocate(systemDatabase_, rv); + if (NULL == node) + { + printError(*rv, "Could not allocate Lock node"); + return NULL; + } + node->ptrToTuple_ = tuple; + node->lInfo_ = info; + node->next_ = NULL; + return node; +} + +void LockManager::deallocLockNode(LockHashNode *node, Bucket *bucket) +{ + Chunk *chunk = systemDatabase_->getSystemDatabaseChunk(LockTableId); + LockHashNode *nodeList = (LockHashNode*) bucket->bucketList_; + LockHashNode *iter = nodeList, *prev = nodeList; + if (NULL == nodeList) + { + printError(ErrSysFatal, "Lock Bucket corrupted"); + return; + } + //If it is the first node, then make the bucket point to the next node + //in the list + if (nodeList == node) + { + bucket->bucketList_ = node->next_; + chunk->free(systemDatabase_, node); + return; + } + while(iter != node) + { + prev = iter; + iter = iter->next_; + } + //delete the node by making previous element point to the next element + //of the deleted element in the list + prev->next_ = iter->next_; + chunk->free(systemDatabase_, node); + return ; +} diff --git a/src/storage/Logger.cxx b/src/storage/Logger.cxx new file mode 100644 index 00000000..42f1d138 --- /dev/null +++ b/src/storage/Logger.cxx @@ -0,0 +1,112 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +int Logger::createLogRecord(LogLevel level, char* filename, + int lineNo, char* message, char **buffer) +{ + char tempBuffer[25]; + struct timeval timeStamp; + os::gettimeofday(&timeStamp); + struct tm* tempTm = os::localtime(&timeStamp.tv_sec); + strftime(tempBuffer, 25, "%d/%m/%Y %H:%M:%S.", tempTm); + snprintf(*buffer, MAX_TRACE_LOG_LENGTH, "%s::%s:%d::%s::%d::%d::%lu::%s\n", + levelNames[level], tempBuffer, timeStamp.tv_usec, + filename, lineNo, + os::getpid(), + os::getthrid(), + message); + return 0; +} + +//TODO::Multiple files: If it exceeeds some configured size, it rolls over to +//next with suffix like file.1, file.2, ... +int Logger::log(LogLevel level, char* filename, + int lineNo, char *format, ...) +{ + if (LogOff == configLevel) return 0; + if (level <= configLevel ) + { + va_list ap; + char mesgBuf[1024]; + va_start(ap, format); + + int err = ::vsnprintf(mesgBuf, sizeof(mesgBuf), format,ap); + if(err < 0) { + return err; + } + char *buffer = new char[MAX_TRACE_LOG_LENGTH]; + createLogRecord(level, filename, lineNo, mesgBuf, &buffer); + //TODO::There is some issue in locking. Need to look into this and then + //uncomment the below lines + //int ret = mutex_.tryLock(5, 100000); + int ret = 0; + if (ret != 0) + { + printError(ErrLockTimeOut,"Unable to acquire logger Mutex"); + delete[] buffer; + return -1; + } + os::write(fdLog, buffer, strlen(buffer)); + os::fsync(fdLog); + //mutex_.releaseLock(); + delete[] buffer; + } + return 0; +} + +DbRetVal Logger::startLogger(char *filename, bool isCreate) +{ + char file[256]; + int i =0; + if (isCreate) + { + while (true) + { + sprintf(file, "%s.%d", filename, i); + //check if file exists. If not create it + if (::access(file, F_OK) != 0 ) break; + i++; + } + fdLog = os::openFile(file, fileOpenCreat,0); + } + else + { + int newlyCreatedID =0; + while (true) + { + sprintf(file, "%s.%d", filename, i); + //check if file exists. If not create it + if (::access(file, F_OK) != 0 ) break; + newlyCreatedID = i; + i++; + } + sprintf(file, "%s.%d", filename, newlyCreatedID ); + fdLog = os::openFile(file, fileOpenAppend,0); + } + if (fdLog == -1) + { + printError(ErrSysInit,"Unable to create log file. Check whether server started\n"); + return ErrSysInit; + } + //TODO::get this value from configuration file + configLevel= LogFinest; + return OK; +} + +void Logger::stopLogger() +{ + os::closeFile(fdLog); +} diff --git a/src/server/Makefile.am b/src/storage/Makefile.am similarity index 77% rename from src/server/Makefile.am rename to src/storage/Makefile.am index 2ef1d092..e7070aed 100644 --- a/src/server/Makefile.am +++ b/src/storage/Makefile.am @@ -7,7 +7,3 @@ libcsql_la_SOURCES = BucketIter.cxx BucketList.cxx CatalogTables.cxx Chunk.cxx \ Debug.cxx FieldList.cxx Index.cxx LockListIter.cxx LockManager.cxx Logger.cxx Mutex.cxx os.cxx \ PageInfo.cxx PredicateImpl.cxx SessionImpl.cxx TableDef.cxx TableImpl.cxx Transaction.cxx \ TransactionManager.cxx TupleIterator.cxx UserManagerImpl.cxx HashIndex.cxx Config.cxx Process.cxx AggTableImpl.cxx JoinTableImpl.cxx -#bin_PROGRAMS = csqlserver -#csqlserver_SOURCES = Server.cxx -#csqlserver_LDADD = $(top_builddir)/src/cache/libcacheload.la \ -# $(top_builddir)/src/server/.libs/libcsql -lrt -lpthread -lcrypt diff --git a/src/server/Makefile.in b/src/storage/Makefile.in similarity index 97% rename from src/server/Makefile.in rename to src/storage/Makefile.in index 9c4857dc..6a5e08a0 100644 --- a/src/server/Makefile.in +++ b/src/storage/Makefile.in @@ -36,7 +36,7 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -subdir = src/server +subdir = src/storage DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in @@ -209,9 +209,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/server/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/storage/Makefile'; \ cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/server/Makefile + $(AUTOMAKE) --foreign src/storage/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -498,10 +498,4 @@ uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES tags uninstall uninstall-am uninstall-info-am \ uninstall-libLTLIBRARIES -#bin_PROGRAMS = csqlserver -#csqlserver_SOURCES = Server.cxx -#csqlserver_LDADD = $(top_builddir)/src/cache/libcacheload.la \ -# $(top_builddir)/src/server/.libs/libcsql -lrt -lpthread -lcrypt -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/src/storage/Mutex.cxx b/src/storage/Mutex.cxx new file mode 100644 index 00000000..4d51b846 --- /dev/null +++ b/src/storage/Mutex.cxx @@ -0,0 +1,212 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +Mutex::Mutex() +{ +#if defined(sparc) || defined(i686) + lock =0; +#else + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); + pthread_mutex_init(&mutex_, &attr); +#endif +} + +int Mutex::init() +{ +#if defined(sparc) || defined(i686) + lock = 0; +#else + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + int ret = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); + printf("pthread_mutexattr_setpshared Returned %d\n", ret); + pthread_mutex_init(&mutex_, &attr); + pthread_mutexattr_destroy(&attr); +#endif + return 0; +} +int Mutex::init(char *mname) +{ + if (strlen(mname) > 19 ) return 0; + init(); + strcpy(name, mname); + return 0; + +} + +#if defined(sparc) || defined(i686) +int TSL(Lock *lock) +{ +/* + if (lock == 0) { + __asm("mov $1, %eax"); + __asm("mov 20(%ebp), %edx"); + __asm("xchg %eax, (%edx)"); + __asm("test %eax %eax"); + __asm("jnz .L1000"); + return 0; + } else + { + __asm(".L1000:"); + return 1; + } +*/ +/*Was Working in linux + char oldval; + __asm__ __volatile__( + "xchgb %b0,%1" + :"=q" (oldval), "=m" (lock) + :"0" (0) : "memory"); + + return oldval > 0; +*/ +#if defined(i686) + int* lw; + int res; + lw = (int*)lock; + if (*lock == 1) return 1; + /* In assembly we use the so-called AT & T syntax where + the order of operands is inverted compared to the ordinary Intel + syntax. The 'l' after the mnemonics denotes a 32-bit operation. + The line after the code tells which values come out of the asm + code, and the second line tells the input to the asm code. */ + + /* This assembly compiles only with -O2 option, and not with -g option. Version1 + __asm__ __volatile__( + "movl $1, %%eax; xchgl (%%ecx), %%eax" + : "=eax" (res), "=m" (*lw) + : "ecx" (lw)); + */ + + /* This assembly takes lot of time for test/performance/DMLTest. Version2 + __asm__ __volatile__( + "movl %1, %0; xchgl %0, %2" + : "=r" (res), "=r" (lock) + : "r" (lock)); + */ + + + // This assembly is Version3. Working fine for now + __asm__ __volatile__( + "xchgl %0, %1 \n\t" + : "=r"(res), "=m"(*lock) + : "0"(1), "m"(*lock) + : "memory"); + + //fprintf(stderr,"after asm %d ret %d\n", *lock, res); + + return(res); + +#elif defined (sparc) + Lock res; + __asm__ __volatile__("ldstub [%2], %0 \n" + "=r"(res), "+m"(*lock) + "r"(lock) + "memory"); + return (int) res; +#endif +} +#endif + +int Mutex::tryLock(int tryTimes, int waitmsecs) +{ + int tries = 0; + int ret = 0; + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = waitmsecs; + if (tryTimes == 0 && waitmsecs == 0) + { + timeout.tv_sec = Conf::config.getMutexSecs(); + timeout.tv_usec = Conf::config.getMutexUSecs(); + tryTimes = Conf::config.getMutexRetries(); + } + while (tries < tryTimes) + { +#if defined(sparc) || defined(i686) + if (TSL(&lock) == 0) + { + return 0; + } +#else + ret = pthread_mutex_trylock(&mutex_); + if (EBUSY != ret) return 0; + +#endif + os::select(0, 0, 0, 0, &timeout); + tries++; + } + printError(ErrLockTimeOut, "Unable to get the mutex , tried %d times", tries); + return 1; +} + + +int Mutex::getLock(int procSlot, bool procAccount) +{ + int ret=0; +#if defined(sparc) || defined(i686) + ret = tryLock(); + //add it to the has_ of the ThreadInfo + if (ret ==0 && procAccount) ProcessManager::addMutex(this, procSlot); + + return ret; +#else + ret = pthread_mutex_lock(&mutex_); +#endif + if (ret == 0) return 0; + else + return 1; +} + +int Mutex::releaseLock(int procSlot, bool procAccount) +{ + int ret=0; +#if defined(sparc) || defined(i686) + /*int *lw = &lock; + if (*lw == 0) return 0; + __asm__ __volatile__("movl $0, %%eax; xchgl (%%ecx), %%eax" : + "=m" (*lw) : + "ecx" (lw) : + "eax"); + */ + lock = 0; +#else + ret = pthread_mutex_unlock(&mutex_); +#endif + if (ret == 0 && procAccount) + { + ProcessManager::removeMutex(this, procSlot); + return ret; + } + else + return 1; +} + +int Mutex::destroy() +{ +#if defined(sparc) || defined(i686) +#else + return pthread_mutex_destroy(&mutex_); +#endif + return 0; +} diff --git a/src/storage/PageInfo.cxx b/src/storage/PageInfo.cxx new file mode 100644 index 00000000..88447634 --- /dev/null +++ b/src/storage/PageInfo.cxx @@ -0,0 +1,36 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include + +void PageInfo::setPageAsUsed(size_t offset) +{ + isUsed_ = 1; + hasFreeSpace_ = 1; + nextPage_ = NULL; + if (PAGE_SIZE > offset) + nextPageAfterMerge_ = NULL; + else + nextPageAfterMerge_ = ((char*)this)+ offset; +} +void PageInfo::setFirstPageAsUsed() +{ + isUsed_ = 1; + hasFreeSpace_ = 1; + nextPageAfterMerge_ = NULL; + nextPage_ = NULL; +} diff --git a/src/storage/PredicateImpl.cxx b/src/storage/PredicateImpl.cxx new file mode 100644 index 00000000..94fe3983 --- /dev/null +++ b/src/storage/PredicateImpl.cxx @@ -0,0 +1,286 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +void PredicateImpl::print() +{ + printf("FieldName1 %s, FieldName2 %s", fldName1, fldName2); + printf("CompOp %d, operand %x operandPtr%x", compOp, operand); + printf("lhs %x, rhs %x", lhs, rhs); + +} + +void PredicateImpl::setTerm(const char* fName1, ComparisionOp op, + const char *fName2) +{ + strcpy(fldName1, fName1); + strcpy(fldName2, fName2); + compOp = op; + operand = NULL; + operandPtr = NULL; + lhs = rhs = NULL; + logicalOp = OpInvalidLogicalOp; +} + +//Operand should be of the same type of the field.This is must +void PredicateImpl::setTerm(const char* fName1, ComparisionOp op, void *opnd) +{ + strcpy(fldName1, fName1); + if (op == OpLike) { + char *c = (char *) opnd; + while (*c != '\0') { + if (*c == '_') *c = '?'; + else if(*c == '%') *c = '*'; + c++; + } + } + compOp = op; + operand = opnd; + operandPtr = NULL; + lhs = rhs = NULL; + logicalOp = OpInvalidLogicalOp; +} + +void PredicateImpl::setTerm(const char* fName1, ComparisionOp op, void **opnd) +{ + strcpy(fldName1, fName1); + compOp = op; + operand = NULL; + operandPtr = opnd; + lhs = rhs = NULL; + logicalOp = OpInvalidLogicalOp; +} + + +void PredicateImpl::setTerm(Predicate *p1, LogicalOp op, Predicate *p2 ) +{ + if (p2 == NULL && op != OpNot || op == OpNot && p2 != NULL) + { + //TODO::printError + return; + } + lhs = (PredicateImpl*)p1; + rhs = (PredicateImpl*)p2; + logicalOp = op; + compOp = OpInvalidComparisionOp; +} + +void PredicateImpl::setTable(Table *tbl) +{ + if (NULL != lhs) + lhs->setTable((TableImpl*)tbl); + if (NULL != rhs) + rhs->setTable((TableImpl*)tbl); + table = (TableImpl*)tbl; +} + +void PredicateImpl::setTuple(void *tpl) +{ + if (NULL != lhs) + lhs->setTuple(tpl); + if (NULL != rhs) + rhs->setTuple(tpl); + tuple = tpl; +} +bool PredicateImpl::isSingleTerm() +{ + if (NULL == lhs && NULL == rhs) return true; else false; +} + + +bool PredicateImpl::isNotOrInvolved() +{ + bool lhsResult = true, rhsResult = true; + if (NULL != lhs) + { + lhsResult = lhs->isNotOrInvolved(); + } + if (NULL != rhs) + { + rhsResult = rhs->isNotOrInvolved(); + } + if (NULL != lhs) + { + //Means it involves only Logical operator + switch(logicalOp) + { + case OpAnd: + if (lhsResult || rhsResult) return true; else return false; + break; + case OpOr: + return true; + break; + case OpNot: + default: + return true; + break; + } + } + return false; +} + +DbRetVal PredicateImpl::evaluate(bool &result) +{ + bool rhsResult = false, lhsResult=false; + printDebug(DM_Predicate, "Evaluate start logical:%d compOp:%d", logicalOp, compOp); + DbRetVal retCode =OK; + result = false; + if (NULL != lhs) + { + retCode = lhs->evaluate(lhsResult); + printDebug(DM_Predicate, "LHS result %d retcode: %d", lhsResult, retCode); + if (retCode != OK) return ErrInvalidExpr; + } + if (NULL != rhs) + { + retCode = rhs->evaluate(rhsResult); + printDebug(DM_Predicate, "RHS result %d retcode:%d", rhsResult, retCode); + if (retCode != OK) return ErrInvalidExpr; + } + if (NULL != lhs) + { + //Means it involves only Logical operator + printDebug(DM_Predicate,"Evalute operator %d lhsResult %d : rhsResult %d", logicalOp, lhsResult, rhsResult ); + switch(logicalOp) + { + case OpAnd: + if (lhsResult && rhsResult) result = true; + break; + case OpOr: + if (lhsResult || rhsResult) result = true; + break; + case OpNot: + if (lhsResult) result = false; else result = true; + break; + default: + return ErrInvalidExpr; + + } + printDebug(DM_Predicate, "result is %d", result); + return OK; + } + printDebug(DM_Predicate, "Evaluating comparision predicate op:%d", compOp); + //Means it is relational expression + //first operand is always field identifier + //get the value in the tuple + int offset1, offset2; + offset1 = table->getFieldOffset(fldName1); + //TODO::do not call getFieldXXX many times, instead get it using getFieldInfo + char *val1, *val2 ; + //Assumes that fldName2 data type is also same for expr f1 getFieldType(fldName1); + val1 = ((char*) tuple) + offset1; + if (operand == NULL && operandPtr == NULL) + { + if (fldName2) { + offset2 = table->getFieldOffset(fldName2); + val2 = ((char*)tuple) + offset2; + } + } + else if(operand != NULL && operandPtr == NULL) + { + val2 = (char*) operand; + } + else if(operand == NULL && operandPtr != NULL) + { + val2 = *(char**)operandPtr; + } + int ret = 0; + printDebug(DM_Predicate, " fldname :%s ", fldName1); + if (compOp == OpLike) result = ! fnmatch(val2, val1, 0); + else result = AllDataType::compareVal(val1, val2, compOp, srcType, + table->getFieldLength(fldName1)); + return OK; +} + +bool PredicateImpl::pointLookupInvolved(const char *fname) +{ + bool rhsResult, lhsResult; + if (NULL != lhs) + { + lhsResult = lhs->pointLookupInvolved(fname); + } + if (NULL != rhs) + { + rhsResult = rhs->pointLookupInvolved(fname); + } + if (NULL != lhs) + { + //Means it involves only Logical operator + switch(logicalOp) + { + case OpAnd: + //return lhsResult; + if (lhsResult || rhsResult) return true; else return false; + break; + case OpOr: + return false; + break; + case OpNot: + default: + return false; + break; + } + } + //Means it is relational expression + //first operand is always field identifier + if (OpEquals == compOp) + { + //for expressions f1 == f2 use full scan, so return false + if(NULL == operand && NULL == operandPtr) return false; + if(0 == strcmp(fldName1, fname)) + { + return true; + } + } + return false; +} + +void* PredicateImpl::valPtrForIndexField(const char *fname) +{ + void *lhsRet, *rhsRet; + if (NULL != lhs) + { + lhsRet = lhs->valPtrForIndexField(fname); + } + if (NULL != rhs) + { + rhsRet = rhs->valPtrForIndexField(fname); + } + if (NULL != lhs) + { + //Means it involves only Logical operator + if ( lhsRet != NULL) return lhsRet; + if ( rhsRet != NULL) return rhsRet; + } + //Means it is relational expression + //first operand is always field identifier + if (OpEquals == compOp) + { + if(0 == strcmp(fldName1, fname)) + { + if (operand) return operand; else return *(void**)operandPtr; + } + } + return NULL; +} diff --git a/src/storage/Process.cxx b/src/storage/Process.cxx new file mode 100644 index 00000000..2cbc6999 --- /dev/null +++ b/src/storage/Process.cxx @@ -0,0 +1,366 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include + +int ProcessManager::noThreads=0; +Mutex ProcessManager::mutex; +caddr_t ProcessManager::sysAddr=0; +caddr_t ProcessManager::usrAddr=0; +Database* ProcessManager::systemDatabase=NULL; +List ProcessManager::hasLockList; + +void ThreadInfo::init() +{ + pid_ = 0; + thrid_ =0; + want_ = NULL; + for (int i =0; i \n"); + printf(" %d \n", pid_); + printf(" %lu \n", thrid_); + printf(" %x \n"); + printf("\n"); +} +void ThreadInfo::print() +{ + printf("\n"); + printf(" %d \n", pid_); + printf(" %lu \n", thrid_); + printf(" %x \n", want_); + printf(" \n"); + for (int i =0; i %x \n", has_[i]); + printf(" \n"); + printf(" \n"); + for (int i =0; i \n"); + printf("\n"); + +} + +//It does not check for re registering as well as deregistering unregistered threads. +//as it is handled in the connection class open and close methods. +DbRetVal ProcessManager::registerThread() +{ + mutex.getLock(false); + noThreads++; + mutex.releaseLock(false); + DbRetVal rv = systemDatabase->getProcessTableMutex(false); + if (OK != rv) + { + printError(rv,"Unable to get process table mutex"); + return rv; + } + pid_t pid; + pid = os::getpid(); + pthread_t thrid = os::getthrid(); + ThreadInfo* pInfo = systemDatabase->getThreadInfo(0); + int i=0; + ThreadInfo* freeSlot = NULL; + int freeSlotPos =0; + bool freeSlotSelected = false; + for (; i < Conf::config.getMaxProcs(); i++) + { + if (pInfo->pid_ == 0 ) break; + pInfo++; + } + if ( i == Conf::config.getMaxProcs()) + { + systemDatabase->releaseProcessTableMutex(false); + printError(ErrNoResource, "No free thread slot. Limit reached"); + return ErrNoResource; + } + //printf("Process slot used %d %x\n", i, pInfo); + //TODO::make the above debug message + //TODO:print it to the trace file + pInfo->init(); + pInfo->pid_ = pid; + pInfo->thrid_ = thrid; + procSlot = i; + printDebug(DM_Process, "Process %d %lu registered with slot %d\n", pid, thrid, procSlot); + systemDatabase->releaseProcessTableMutex(false); + return OK; +} +DbRetVal ProcessManager::deregisterThread(int procSlot) +{ + mutex.getLock(false); + noThreads--; + mutex.releaseLock(false); + DbRetVal rv = systemDatabase->getProcessTableMutex(false); + if (OK != rv) + { + printError(rv,"Unable to get process table mutex"); + return rv; + }/* + pid_t pid = os::getpid(); + pthread_t thrid = os::getthrid(); + + ThreadInfo* pInfo = systemDatabase->getThreadInfo(0); + int i=0; + for (; i < Conf::config.getMaxProcs(); i++) + { + if (pInfo->pid_ == pid && pInfo->thrid_ == thrid) break; + pInfo++; + } + + systemDatabase->releaseProcessTableMutex(false); + if (i == Conf::config.getMaxProcs()) + { + printError(ErrSysFatal, "Degistering process %d is not registered with csql", pid); + return ErrNoResource; + }*/ + ThreadInfo* pInfo = systemDatabase->getThreadInfo(procSlot); + Transaction *trans = ProcessManager::getThreadTransaction(procSlot); + if (NULL != trans) + { + if (trans->status_ == TransRunning) + { + printError(ErrWarning, "Transaction is still running\n"); + } + } + if (pInfo->want_ != NULL) + { + printError(ErrSysFatal, "Probable data corruption.wants_ is not null\n"); + return ErrSysFatal; + } + for (int muti = 0 ;muti < MAX_MUTEX_PER_THREAD; muti++) + { + if (pInfo->has_[muti] != NULL) + { + printError(ErrSysFatal, "Probable data corruption.some mutexes are not freed %x %s\n", pInfo->has_[muti], pInfo->has_[muti]->name); + pInfo->has_[muti]->releaseLock(procSlot); + return ErrSysFatal; + } + } + printDebug(DM_Process, "Process %d %lu deregistered slot %d\n", pInfo->pid_, pInfo->thrid_, procSlot); + + //printf("Slot freed %d %x %d %lu\n", i, pInfo, pid, thrid); + pInfo->init(); + systemDatabase->releaseProcessTableMutex(false); + return OK; +} + +DbRetVal ProcessManager::addMutex(Mutex *mut, int pslot) +{ + //pid_t pid = os::getpid(); + //pthread_t thrid = os::getthrid(); + if (systemDatabase == NULL) + { + return OK; + } + ThreadInfo* pInfo = systemDatabase->getThreadInfo(pslot); + int i=0; + /*for (; i < Conf::config.getMaxProcs(); i++) + { + if (pInfo->pid_ == pid && pInfo->thrid_ == thrid) break; + pInfo++; + } + if (i == Conf::config.getMaxProcs()) + { + printError(ErrSysFatal, "Logical Error pid %d thrid %lu not found in procTable while adding mutex %s", pid, thrid, mut->name); + return ErrSysFatal; + }*/ + for (int i = 0 ;i < MAX_MUTEX_PER_THREAD; i++) + { + if (pInfo->has_[i] == NULL) + { + pInfo->has_[i] = mut; + printDebug(DM_Process, "procSlot %d acquiring %d mutex %x %s\n", pslot, i, mut, mut->name); + return OK; + } + } + printError(ErrSysInternal, "All slots are full. Reached per thread mutex limit."); + return ErrSysInternal; +} + +DbRetVal ProcessManager::removeMutex(Mutex *mut, int pslot) +{ + //pid_t pid = os::getpid(); + //pthread_t thrid = os::getthrid(); + if (systemDatabase == NULL) + { + return OK; + } + + ThreadInfo* pInfo = systemDatabase->getThreadInfo(pslot); + int i=0; + /*for (; i < Conf::config.getMaxProcs(); i++) + { + if (pInfo->pid_ == pid && pInfo->thrid_ == thrid) break; + pInfo++; + } + if (i == Conf::config.getMaxProcs()) + { + printError(ErrSysFatal, "Logical Error pid %d thrid %lu not found in procTable", pid, thrid); + return ErrSysFatal; + }*/ + for (int i = 0 ;i < MAX_MUTEX_PER_THREAD; i++) + { + if (pInfo->has_[i] == mut) + { + pInfo->has_[i] = NULL; + printDebug(DM_Process, "procSlot %d releasing %d mutex %x %s\n", pslot, i, mut, mut->name); + return OK; + } + } + printError(ErrSysInternal, "Mutex could not be found in the list %s", mut->name); + return ErrSysInternal; +} + +DbRetVal ProcessManager::setThreadTransaction(Transaction *trans, int pslot) +{ + pid_t pid = os::getpid(); + pthread_t thrid = os::getthrid(); + if (systemDatabase == NULL) + { + return OK; + } + + ThreadInfo* pInfo = systemDatabase->getThreadInfo(pslot); + int i=0; + + for (int i = 0 ;i < MAX_THREADS_PER_PROCESS; i++) + { + if (pInfo->thrTrans_[i].pid_ != 0) continue; + } + if (i == MAX_THREADS_PER_PROCESS) + { + printError(ErrSysInternal, "Max thread limit reached."); + return ErrSysInternal; + } + pInfo->thrTrans_[i].pid_ = pid; + pInfo->thrTrans_[i].thrid_ = thrid; + pInfo->thrTrans_[i].trans_ = trans; + + printDebug(DM_Process, "procSlot %d: pid: %d thrid: %lu is set to use trans %x\n", pslot, + pid, thrid, trans); + //pInfo->trans_ = trans; + return OK; +} + +Transaction* ProcessManager::getThreadTransaction(int pslot) +{ + pid_t pid = os::getpid(); + pthread_t thrid = os::getthrid(); + if (systemDatabase == NULL) + { + return NULL; + } + + ThreadInfo* pInfo = systemDatabase->getThreadInfo(pslot); + int i=0; + + for (int i = 0 ;i < MAX_THREADS_PER_PROCESS; i++) + { + if (pInfo->thrTrans_[i].pid_ == pid && pInfo->thrTrans_[i].thrid_ == thrid) break; + } + if (i == MAX_THREADS_PER_PROCESS) + { + printDebug(DM_Process, "Thread specific trans could not be found in list"); + return NULL; + } + + printDebug(DM_Process, "procSlot %d: pid: %d thrid: %lu is returning trans %x\n", pslot, + pid, thrid, pInfo->thrTrans_[i].trans_); + //pInfo->trans_ = trans; + return pInfo->thrTrans_[i].trans_; +} + +Transaction** ProcessManager::getThreadTransAddr(int pslot) +{ + pid_t pid = os::getpid(); + pthread_t thrid = os::getthrid(); + if (systemDatabase == NULL) + { + return NULL; + } + + ThreadInfo* pInfo = systemDatabase->getThreadInfo(pslot); + int i=0; + + for (int i = 0 ;i < MAX_THREADS_PER_PROCESS; i++) + { + if (pInfo->thrTrans_[i].pid_ == pid && pInfo->thrTrans_[i].thrid_ == thrid) break; + } + if (i == MAX_THREADS_PER_PROCESS) + { + printDebug(DM_Process, "Thread specific trans could not be found in list"); + return NULL; + } + + printDebug(DM_Process, "procSlot %d: pid: %d thrid: %lu is returning trans %x\n", pslot, + pid, thrid, pInfo->thrTrans_[i].trans_); + return &pInfo->thrTrans_[i].trans_; +} + + + + +void ProcessManager::printUsageStatistics() +{ + ThreadInfo* pInfo = systemDatabase->getThreadInfo(0); + int i=0, usedCount =0 , freeCount =0; + for (; i < Conf::config.getMaxProcs(); i++) + { + if (pInfo->pid_ != 0 ) usedCount++; else freeCount++; + pInfo++; + } + printf("\n"); + printf(" %d \n", usedCount); + printf(" %d \n", freeCount); + printf("\n"); + +} + +void ProcessManager::printDebugInfo() +{ + printf("\n"); + ThreadInfo* pInfo = systemDatabase->getThreadInfo(0); + int i=0, usedCount =0 , freeCount =0; + for (; i < Conf::config.getMaxProcs(); i++) + { + if (pInfo->pid_ != 0 ) {pInfo->print(); usedCount++;} else freeCount++; + pInfo++; + } + printf(" %d \n", usedCount); + printf(" %d \n", freeCount); + printf("\n"); +} + + +bool ProcessManager::isAnyOneRegistered() +{ + //the process which calls this will have an entry in proc table. + //so checking for 1 + ThreadInfo* pInfo = systemDatabase->getThreadInfo(0); + int i=0, usedCount =0; + for (; i < Conf::config.getMaxProcs(); i++) + { + if (pInfo->pid_ != 0 ) usedCount++; + pInfo++; + } + if (usedCount == 1) return false; else return true; +} diff --git a/src/storage/SessionImpl.cxx b/src/storage/SessionImpl.cxx new file mode 100644 index 00000000..fe3d8d0d --- /dev/null +++ b/src/storage/SessionImpl.cxx @@ -0,0 +1,283 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//Before calling this method, application is required to call readConfigValues +DbRetVal SessionImpl::initSystemDatabase() + +{ + DbRetVal rv = OK; + rv = readConfigFile(); + if (rv != OK) + { + printError(ErrSysInit, "Configuration file read failed\n"); + return ErrSysInit; + } + + Conf::config.print(); + + dbMgr = new DatabaseManagerImpl(); + rv = dbMgr->createDatabase(SYSTEMDB, Conf::config.getMaxSysDbSize()); + if (OK != rv) return rv; + dbMgr->setSysDb(dbMgr->db()); + dbMgr->setDb(NULL); + + Database *db = dbMgr->sysDb(); + + rv = db->getDatabaseMutex(); + if (OK != rv) + { + printError(ErrLockTimeOut, "Unable to get Database Mutex"); + return rv; + } + + + db->createAllCatalogTables(); + + //create the default dba user + CatalogTableUSER cUser(db); + rv = cUser.insert(DBAUSER, DBAPASS); + if (OK != rv) + { + db->releaseDatabaseMutex(); + return rv; + } + void *ret = NULL; + //Allocate space for the lock hash bucket + ret = db->allocLockHashBuckets(); + if (NULL == ret) + { + db->releaseDatabaseMutex(); + printError(ErrSysInit, "Allocation of Lock buckets failed"); + return ErrSysInit; + } + + db->releaseDatabaseMutex(); + printf("sysdb size %ld dbsize %ld\n", Conf::config.getMaxSysDbSize(), Conf::config.getMaxDbSize()); + //create user database + rv = dbMgr->createDatabase("userdb", Conf::config.getMaxDbSize()); + if (OK != rv) return rv; + return OK; +} + +DbRetVal SessionImpl::destroySystemDatabase() +{ + DbRetVal rv = OK; + rv = dbMgr->deleteDatabase(SYSTEMDB); + if (OK != rv) return rv; + rv = dbMgr->deleteDatabase("userdb"); + if (OK != rv) return rv; + delete dbMgr; + dbMgr = NULL; + return OK; +} + +DbRetVal SessionImpl::open(const char *username, const char *password) +{ + DbRetVal rv = OK; + rv = readConfigFile(); + if (rv != OK) + { + printError(ErrSysFatal, "Configuration file read failed\n"); + return ErrSysFatal; + } + + if ( NULL == dbMgr) + { + dbMgr = new DatabaseManagerImpl(); + rv = dbMgr->openSystemDatabase(); + } + if (OK != rv) + { + printError(rv,"Unable to open the system database"); + return rv; + } + + rv = authenticate(username, password); + if (OK != rv) + { + dbMgr->closeSystemDatabase(); + delete dbMgr; dbMgr = NULL; + return rv; + } + + dbMgr->createTransactionManager(); + dbMgr->createLockManager(); + rv = dbMgr->registerThread(); + if (OK != rv) + { + printError(rv,"Unable to register to csql server"); + dbMgr->closeSystemDatabase(); + delete dbMgr; dbMgr = NULL; + return rv; + } + rv = dbMgr->openDatabase("userdb"); + if (OK != rv) { + dbMgr->closeSystemDatabase(); + delete dbMgr; dbMgr = NULL; + return rv; + } + ((DatabaseManagerImpl*)dbMgr)->setProcSlot(); + //ProcessManager::systemDatabase = dbMgr->sysDb(); + return OK; +} +DbRetVal SessionImpl::authenticate(const char *username, const char *password) +{ + DbRetVal rv = dbMgr->sysDb()->getDatabaseMutex(false); + if (OK != rv) + { + printError(rv,"Unable to get database mutex"); + return rv; + } + CatalogTableUSER cUser(dbMgr->sysDb()); + cUser.authenticate(username, password, isAuthenticated, isDba); + strcpy(userName, username); + dbMgr->sysDb()->releaseDatabaseMutex(false); + if (!isAuthenticated) + { + printError(ErrNoPrivilege,"User Authentication failed"); + return ErrNoPrivilege; + } + return OK; +} +DbRetVal SessionImpl::close() +{ + DbRetVal rv = OK; + if (dbMgr) + { + rv = dbMgr->closeDatabase(); + if (rv != OK) { return ErrBadCall; } + rv = dbMgr->deregisterThread(); + if (rv != OK) { return ErrBadCall; } + rv = dbMgr->closeSystemDatabase(); + if (rv != OK) { return ErrBadCall; } + delete dbMgr; + dbMgr = NULL; + } + if (uMgr) + { + delete uMgr; + uMgr = NULL; + } + return OK; +} + +DatabaseManager* SessionImpl::getDatabaseManager() +{ + if (isAuthenticated) return dbMgr; + printError(ErrNoPrivilege, "Not Authenticated: Returning NULL"); + return NULL; +} + +UserManager* SessionImpl::getUserManager() +{ + if (!isAuthenticated) + { + printError(ErrNoPrivilege, "Not Authenticated: Returning NULL"); + return NULL; + } + if (uMgr != NULL) return uMgr; + UserManagerImpl *userMgr = new UserManagerImpl(); + if(0 == strcmp(userName, DBAUSER)) + userMgr->setDba(true); + else + userMgr->setDba(false); + + userMgr->setSysDb(dbMgr->sysDb()); + + userMgr->setUserName(userName); + uMgr = userMgr; + return userMgr; +} + +DbRetVal SessionImpl::startTransaction(IsolationLevel level) +{ + if (NULL == dbMgr || NULL == dbMgr->txnMgr()) + { + printError(ErrSysFatal, "Database Manager or Txn Manager object is NULL"); + return ErrSysFatal; + } + DbRetVal rv = OK; + + rv = dbMgr->txnMgr()->startTransaction(dbMgr->lockMgr(), level); + return rv; +} + + +DbRetVal SessionImpl::commit() +{ + DbRetVal rv = OK; + if (NULL == dbMgr || NULL == dbMgr->txnMgr()) + { + printError(ErrSysFatal, "Database Manager or Txn Manager object is NULL"); + return ErrSysFatal; + } + rv = dbMgr->txnMgr()->commit(dbMgr->lockMgr()); + if (OK != rv) + { + printError(rv,"Transaction commit failed\n"); + return rv; + } + return OK; +} + + +DbRetVal SessionImpl::rollback() +{ + DbRetVal rv = OK; + if (NULL == dbMgr || NULL == dbMgr->txnMgr()) + { + printError(ErrSysFatal, "Database Manager or Txn Manager object is NULL"); + return ErrSysFatal; + } + rv = dbMgr->txnMgr()->rollback(dbMgr->lockMgr()); + if (OK != rv) + { + printError(rv, "Transaction rollback failed\n"); + return rv; + } + return OK; +} + +DbRetVal SessionImpl::readConfigFile() +{ + // Check if env variable is set or not + char *confFilename = os::getenv("CSQL_CONFIG_FILE"); + if (confFilename == NULL) + { + printError(ErrSysInit, "CSQL_CONFIG_FILE environment variable should be set."); + return ErrSysInit; + } + + int rv = Conf::config.readAllValues(confFilename); + if (rv != 0) return ErrSysInit; + return OK; +} +Database* SessionImpl::getSystemDatabase() +{ + return dbMgr->sysDb(); +} + diff --git a/src/storage/TableDef.cxx b/src/storage/TableDef.cxx new file mode 100644 index 00000000..f936140c --- /dev/null +++ b/src/storage/TableDef.cxx @@ -0,0 +1,107 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include + +TableDef::~TableDef() +{ + reset(); +} +void TableDef::reset() +{ + fldList.removeAll(); + fldCount = 0; +} +int TableDef::addField(const char *name, DataType type, size_t length, + const void *defaultValue, bool notNull) +{ + if (name == NULL) return (int)ErrBadArg; + // The following code checks for duplicates + FieldIterator iter = getFieldIterator(); + while (iter.hasElement()) + { + FieldDef def = iter.nextElement(); + if (! strcmp(def.fldName_, name)) { + printError(ErrAlready, "Field %s already Exists", name); + return (int) ErrAlready; + } + } + FieldDef fldDef; + strcpy(fldDef.fldName_, name); + fldDef.fldName_[IDENTIFIER_LENGTH] = '\0'; + fldDef.type_ = type; + fldDef.length_ = length; + fldDef.bindVal_=NULL; + if (defaultValue != NULL) + { + fldDef.isDefault_ = true; + if (typeBinary == type) { + const char *p = (const char *) defaultValue; + while (*p != '\0') { + if (! isxdigit((int)(*p++)) ) { + printError(ErrBadArg, "Invalid hexadecimal value"); + return (int) ErrBadArg; + } + } + } + os::memcpy(fldDef.defaultValueBuf_, defaultValue, DEFAULT_VALUE_BUF_LENGTH); + } + else + { + fldDef.isDefault_ = false; + os::memset(fldDef.defaultValueBuf_,0, DEFAULT_VALUE_BUF_LENGTH); + } + fldDef.isNull_ = notNull; + switch(type) + { + case typeString : + case typeBinary: + fldDef.length_ = length; + break; + default: + fldDef.length_ = AllDataType::size(type); + break; + } + int ret = fldList.append(fldDef); + if (0 == ret) fldCount++; + return ret; +} + +int TableDef::dropField(const char *name) +{ + int ret = fldList.remove(name); + if (0 == ret) fldCount--; + return ret; +} + +int TableDef::getFieldCount() +{ + return fldCount; +} + +size_t TableDef::getTupleSize() +{ + size_t length = 0; + FieldIterator iter = getFieldIterator(); + while (iter.hasElement()) + { + FieldDef def = iter.nextElement(); + length = length + os::align(def.length_); + } + return length; +} diff --git a/src/storage/TableImpl.cxx b/src/storage/TableImpl.cxx new file mode 100644 index 00000000..d8ed62e6 --- /dev/null +++ b/src/storage/TableImpl.cxx @@ -0,0 +1,815 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DbRetVal TableImpl::bindFld(const char *name, void *val) +{ + //set it in the field list + DbRetVal rv = fldList_.updateBindVal(name, val); + if (OK != rv) { + printError(ErrNotExists, "Field %s does not exist", name); + return rv; + } + return OK; +} + +bool TableImpl::isFldNull(const char *name){ + int colpos = fldList_.getFieldPosition(name); + if (-1 == colpos) + { + printError(ErrNotExists, "Field %s does not exist", name); + return false; + } + + return isFldNull(colpos); +} + +bool TableImpl::isFldNull(int colpos) +{ + if (!curTuple_) return false; + if (colpos <1 || colpos > numFlds_) return false; + char *nullOffset = (char*)curTuple_ - 4; + if (isIntUsedForNULL) { + int nullVal = *(int*)((char*)curTuple_ + (length_ - 4)); + if (BITSET(nullVal, colpos)) return true; + } + else { + char *nullOffset = (char*)curTuple_ - os::align(numFlds_); + if (nullOffset[colpos-1]) return true; + } + return false; +} +void TableImpl::markFldNull(char const* name) +{ + int colpos = fldList_.getFieldPosition(name); + if (-1 == colpos) + { + printError(ErrNotExists, "Field %s does not exist", name); + return; + } + markFldNull(colpos); +} + +void TableImpl::markFldNull(int fldpos) +{ + if (fldpos <1 || fldpos > numFlds_) return; + if (isIntUsedForNULL) { + if (!BITSET(iNotNullInfo, fldpos)) SETBIT(iNullInfo, fldpos); + } + else + if (!BITSET(iNotNullInfo, fldpos)) cNullInfo[fldpos-1] = 1; + return; +} + +void TableImpl::clearFldNull(const char *name) +{ + int colpos = fldList_.getFieldPosition(name); + if (-1 == colpos) + { + printError(ErrNotExists, "Field %s does not exist", name); + return; + } + + clearFldNull(colpos); +} + +void TableImpl::clearFldNull(int colpos) +{ + if (colpos <1 || colpos > numFlds_) return; + if (isIntUsedForNULL) { + CLEARBIT(iNullInfo, colpos); + } + else + cNullInfo[colpos-1] = 0; + return; +} + + +DbRetVal TableImpl::execute() +{ + if (NULL != iter) + { + printError(ErrAlready,"Scan already open:Close and re execute"); + return ErrAlready; + } + //table ptr is set in predicate because it needs to access the + //type and length to evaluate + if( NULL != pred_) + { + PredicateImpl *pred = (PredicateImpl*) pred_; + pred->setTable(this); + } + DbRetVal ret = OK; + + ret = createPlan(); + if (OK != ret) + { + printError(ErrSysInternal,"Unable to create the plan"); + return ErrSysInternal; + } + if (useIndex_ >= 0) + iter = new TupleIterator(pred_, scanType_, idxInfo[useIndex_], chunkPtr_, sysDB_->procSlot); + else if (scanType_ == fullTableScan) + iter = new TupleIterator(pred_, scanType_, NULL, chunkPtr_, sysDB_->procSlot); + else + { + printError(ErrSysFatal,"Unable to create tuple iterator");//should never happen + return ErrSysFatal; + } + ret = iter->open(); + if (OK != ret) + { + printError(ret,"Unable to open the iterator"); + return ret; + } + return OK; +} + + +DbRetVal TableImpl::createPlan() +{ + if (isPlanCreated) { + //will do early return here. plan is generated only when setPredicate is called. + if (scanType_ == unknownScan) return ErrSysFatal; //this should never happen + else return OK; + } + useIndex_ = -1; + //if there are no predicates then go for full scan + //if there are no indexes then go for full scan + if (NULL == pred_ || NULL == indexPtr_) + { + scanType_ = fullTableScan; + isPlanCreated = true; + return OK; + } + if (NULL != indexPtr_) + { + PredicateImpl *pred = (PredicateImpl*)pred_; + printDebug(DM_Predicate, "predicate does not involve NOT , OR operator"); + if (!pred->isNotOrInvolved()) + { + printDebug(DM_Predicate, "predicate does not involve NOT , OR operator"); + for (int i =0; i < numIndexes_; i++) + { + HashIndexInfo* info = (HashIndexInfo*) idxInfo[i]; + FieldIterator iter = info->idxFldList.getIterator(); + while(iter.hasElement()) + { + FieldDef def = iter.nextElement(); + if (pred->pointLookupInvolved(def.fldName_)) + { + printDebug(DM_Predicate, "point lookup involved for field %s",def.fldName_); + scanType_ = hashIndexScan; + isPlanCreated = true; + useIndex_ = i; + } + else + { + useIndex_ = -1; + break; + } + }//while iter.hasElement() + if (useIndex_ != -1) return OK; + }//for + } + } + scanType_ = fullTableScan; + isPlanCreated = true; + return OK; +} + +void* TableImpl::fetch() +{ + fetchNoBind(); + if (NULL == curTuple_) return curTuple_; + copyValuesToBindBuffer(curTuple_); + return curTuple_; +} +void* TableImpl::fetch(DbRetVal &rv) +{ + fetchNoBind(rv); + if (NULL == curTuple_) return curTuple_; + copyValuesToBindBuffer(curTuple_); + return curTuple_; +} + +void* TableImpl::fetchNoBind() +{ + if (NULL == iter) + { + printError(ErrNotOpen,"Scan not open or Scan is closed\n"); + return NULL; + } + void *prevTuple = curTuple_; + curTuple_ = iter->next(); + if (NULL == curTuple_) + { + return NULL; + } + DbRetVal lockRet = OK; + if ((*trans)->isoLevel_ == READ_REPEATABLE) { + lockRet = lMgr_->getSharedLock(curTuple_, trans); + if (OK != lockRet) + { + printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_); + curTuple_ = prevTuple; + return NULL; + } + + } + else if ((*trans)->isoLevel_ == READ_COMMITTED) + { + //if iso level is read committed, operation duration lock is sufficent + //so release it here itself. + int tries = 5; + struct timeval timeout; + timeout.tv_sec = Conf::config.getMutexSecs(); + timeout.tv_usec = Conf::config.getMutexUSecs(); + + bool status = false; + while(true) { + lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status); + if (OK != lockRet) + { + printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_); + curTuple_ = prevTuple; + return NULL; + } + if (!status) break; + tries--; + if (tries == 0) break; + os::select(0, 0, 0, 0, &timeout); + + } + if (tries == 0) + { + printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_); + curTuple_ = prevTuple; + return NULL; + } + } + return curTuple_; +} + +void* TableImpl::fetchNoBind(DbRetVal &rv) +{ + rv = OK; + if (NULL == iter) + { + printError(ErrNotOpen,"Scan not open or Scan is closed\n"); + rv = ErrNotOpen; + return NULL; + } + void *prevTuple = curTuple_; + curTuple_ = iter->next(); + if (NULL == curTuple_) + { + return NULL; + } + DbRetVal lockRet = OK; + if ((*trans)->isoLevel_ == READ_REPEATABLE) { + lockRet = lMgr_->getSharedLock(curTuple_, trans); + if (OK != lockRet) + { + printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_); + rv = ErrLockTimeOut; + curTuple_ = prevTuple; + return NULL; + } + + } + else if ((*trans)->isoLevel_ == READ_COMMITTED) + { + //if iso level is read committed, operation duration lock is sufficent + //so release it here itself. + int tries = 5; + struct timeval timeout; + timeout.tv_sec = Conf::config.getMutexSecs(); + timeout.tv_usec = Conf::config.getMutexUSecs(); + + bool status = false; + while(true) { + lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status); + if (OK != lockRet) + { + printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_); + curTuple_ = prevTuple; + rv = ErrLockTimeOut; + return NULL; + } + if (!status) break; + tries--; + if (tries == 0) break; + os::select(0, 0, 0, 0, &timeout); + + } + if (tries == 0) + { + printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_); + curTuple_ = prevTuple; + rv = ErrLockTimeOut; + return NULL; + } + } + return curTuple_; +} + +DbRetVal TableImpl::insertTuple() +{ + DbRetVal ret =OK; + void *tptr = ((Chunk*)chunkPtr_)->allocate(db_, &ret); + if (NULL == tptr) + { + printError(ret, "Unable to allocate record from chunk"); + return ret; + } + ret = lMgr_->getExclusiveLock(tptr, trans); + if (OK != ret) + { + ((Chunk*)chunkPtr_)->free(db_, tptr); + printError(ret, "Could not get lock for the insert tuple %x", tptr); + return ErrLockTimeOut; + } + + + ret = copyValuesFromBindBuffer(tptr); + if (ret != OK) + { + printError(ret, "Unable to copy values from bind buffer"); + (*trans)->removeFromHasList(db_, tptr); + lMgr_->releaseLock(tptr); + ((Chunk*)chunkPtr_)->free(db_, tptr); + return ret; + } + + int addSize = 0; + if (numFlds_ < 31) + { + addSize = 4; + *(int*)((char*)(tptr) + (length_-addSize)) = iNullInfo; + } + else + { + addSize = os::align(numFlds_); + os::memcpy(((char*)(tptr) + (length_-addSize)), cNullInfo, addSize); + + } + //int tupleSize = length_ + addSize; + if (NULL != indexPtr_) + { + int i; + //it has index + for (i = 0; i < numIndexes_ ; i++) + { + ret = insertIndexNode(*trans, indexPtr_[i], idxInfo[i], tptr); + if (ret != OK) { printError(ret, "Error in inserting to index"); break;} + } + if (i != numIndexes_ ) + { + for (int j = 0; j < i ; j++) { + printError(ErrWarning, "Deleting index node"); + deleteIndexNode(*trans, indexPtr_[j], idxInfo[j], tptr); + } + lMgr_->releaseLock(tptr); + (*trans)->removeFromHasList(db_, tptr); + ((Chunk*)chunkPtr_)->free(db_, tptr); + //PRABA::TEMP + //printError(ret, "Unable to insert index node for tuple %x ", tptr); + printError(ret, "Unable to insert index node for tuple %x %d", tptr, *(int*)tptr); + return ret; + } + } + if (undoFlag) + ret = (*trans)->appendUndoLog(sysDB_, InsertOperation, tptr, length_); + if (ret != OK) { + printError(ret, "Unable to create undo log for %x %d", tptr, *(int*)tptr); + for (int j = 0; j < numIndexes_ ; j++) { + printError(ErrWarning, "Deleting index node"); + deleteIndexNode(*trans, indexPtr_[j], idxInfo[j], tptr); + } + lMgr_->releaseLock(tptr); + (*trans)->removeFromHasList(db_, tptr); + ((Chunk*)chunkPtr_)->free(db_, tptr); + } + return ret; +} + +DbRetVal TableImpl::deleteTuple() +{ + if (NULL == curTuple_) + { + printError(ErrNotOpen, "Scan not open: No Current tuple"); + return ErrNotOpen; + } + DbRetVal ret = lMgr_->getExclusiveLock(curTuple_, trans); + if (OK != ret) + { + printError(ret, "Could not get lock for the delete tuple %x", curTuple_); + return ErrLockTimeOut; + } + + if (NULL != indexPtr_) + { + int i; + //it has index + for (i = 0; i < numIndexes_ ; i++) + { + ret = deleteIndexNode(*trans, indexPtr_[i], idxInfo[i], curTuple_); + if (ret != OK) break; + } + if (i != numIndexes_ ) + { + for (int j = 0; j < i ; j++) + insertIndexNode(*trans, indexPtr_[j], idxInfo[j], curTuple_); + lMgr_->releaseLock(curTuple_); + (*trans)->removeFromHasList(db_, curTuple_); + printError(ret, "Unable to insert index node for tuple %x", curTuple_); + return ret; + } + } + ((Chunk*)chunkPtr_)->free(db_, curTuple_); + if (undoFlag) + ret = (*trans)->appendUndoLog(sysDB_, DeleteOperation, curTuple_, length_); + return ret; +} + +int TableImpl::deleteWhere() +{ + int tuplesDeleted = 0; + DbRetVal rv = OK; + rv = execute(); + if (rv !=OK) return (int) rv; + while(true){ + fetchNoBind( rv); + if (rv != OK) { tuplesDeleted = (int)rv; break; } + if (NULL == curTuple_) break; + rv = deleteTuple(); + if (rv != OK) { + printError(rv, "Error: Could only delete %d tuples", tuplesDeleted); + close(); + return (int) rv; + } + tuplesDeleted++; + } + close(); + return tuplesDeleted; +} + +int TableImpl::truncate() +{ + //take exclusive lock on the table + //get the chunk ptr of the table + //traverse the tablechunks and free all the pages except the first one + //get the chunk ptr of all its indexes + //traverse the indexchunks and free all the pages except the first one + //release table lock + + //TEMPORARY FIX + DbRetVal rv = OK; + Predicate* tmpPred = pred_; + pred_ = NULL; + isPlanCreated = false; + int tuplesDeleted = deleteWhere(); + isPlanCreated = false; + pred_ = tmpPred; + return tuplesDeleted; +} + +DbRetVal TableImpl::updateTuple() +{ + if (NULL == curTuple_) + { + printError(ErrNotOpen, "Scan not open: No Current tuple"); + return ErrNotOpen; + } + DbRetVal ret = lMgr_->getExclusiveLock(curTuple_, trans); + if (OK != ret) + { + printError(ret, "Could not get lock for the update tuple %x", curTuple_); + return ErrLockTimeOut; + } + if (NULL != indexPtr_) + { + //it has index + //TODO::If it fails while updating index node, we have to undo all the updates + //on other indexes on the table.Currently it will leave the database in an + //inconsistent state. + for (int i = 0; i < numIndexes_ ; i++) + { + ret = updateIndexNode(*trans, indexPtr_[i], idxInfo[i], curTuple_); + if (ret != OK) + { + lMgr_->releaseLock(curTuple_); + (*trans)->removeFromHasList(db_, curTuple_); + printError(ret, "Unable to update index node for tuple %x", curTuple_); + return ret; + } + } + } + if (undoFlag) + ret = (*trans)->appendUndoLog(sysDB_, UpdateOperation, curTuple_, length_); + if (ret != OK) return ret; + int addSize = 0; + if (numFlds_ < 31) + { + addSize = 4; + *(int*)((char*)(curTuple_) + (length_-addSize)) |= iNullInfo; + } + else + { + addSize = os::align(numFlds_); + //TODO::Do not do blind memcpy. It should OR each and every char + //os::memcpy(((char*)(curTuple_) + (length_-addSize)), cNullInfo, addSize); + + } + + DbRetVal rv = copyValuesFromBindBuffer(curTuple_, false); + if (rv != OK) { + lMgr_->releaseLock(curTuple_); + (*trans)->removeFromHasList(db_, curTuple_); + return rv; + } + return OK; +} + +void TableImpl::printInfo() +{ + printf(" %s \n", tblName_); + printf(" %d \n", numTuples()); + printf(" %d \n", pagesUsed()); + printf(" %d \n", spaceUsed()); + printf(" %d \n", numIndexes_); + printf(" %d \n", length_); + printf(" %d \n", numFlds_); + printf(" \n"); + for (int i =0; i %s \n", CatalogTableINDEX::getName(indexPtr_[i])); + printf(" \n"); + +} + +DbRetVal TableImpl::copyValuesFromBindBuffer(void *tuplePtr, bool isInsert) +{ + //Iterate through the bind list and copy the value here + FieldIterator fIter = fldList_.getIterator(); + char *colPtr = (char*) tuplePtr; + int fldpos=1; + while (fIter.hasElement()) + { + FieldDef def = fIter.nextElement(); + if (def.isNull_ && !def.isDefault_ && NULL == def.bindVal_ && isInsert) + { + printError(ErrNullViolation, "NOT NULL constraint violation for field %s\n", def.fldName_); + return ErrNullViolation; + } + if (def.isDefault_ && NULL == def.bindVal_ && isInsert) + { + void *dest = AllDataType::alloc(def.type_, def.length_); + AllDataType::convert(typeString, def.defaultValueBuf_, def.type_, dest, def.length_); + AllDataType::copyVal(colPtr, dest, def.type_, def.length_); + colPtr = colPtr + os::align(AllDataType::size(def.type_, def.length_)); + fldpos++; + free (dest); + continue; + } + switch(def.type_) + { + case typeString: + if (NULL != def.bindVal_) + { + strcpy((char*)colPtr, (char*)def.bindVal_); + *(((char*)colPtr) + (def.length_-1)) = '\0'; + } + else if (!def.isNull_ && isInsert) setNullBit(fldpos); + colPtr = colPtr + os::align(def.length_); + break; + case typeBinary: + if (NULL != def.bindVal_ ) { + DbRetVal rv = AllDataType::strToValue(colPtr, (char *) def.bindVal_, def.type_, def.length_); + if (rv != OK) return ErrBadArg; + } + else if (!def.isNull_ && isInsert) setNullBit(fldpos); + colPtr = colPtr + os::align(def.length_); + break; + default: + if (NULL != def.bindVal_) + AllDataType::copyVal(colPtr, def.bindVal_, def.type_); + else { if (!def.isNull_ && isInsert) setNullBit(fldpos); } + colPtr = colPtr + os::align(AllDataType::size(def.type_)); + break; + } + fldpos++; + } + return OK; +} +void TableImpl::setNullBit(int fldpos) +{ + if (isIntUsedForNULL) + SETBIT(iNullInfo, fldpos); + else + cNullInfo[fldpos-1] = 1; +} +DbRetVal TableImpl::copyValuesToBindBuffer(void *tuplePtr) +{ + //Iterate through the bind list and copy the value here + FieldIterator fIter = fldList_.getIterator(); + char *colPtr = (char*) tuplePtr; + while (fIter.hasElement()) + { + FieldDef def = fIter.nextElement(); + if (NULL != def.bindVal_) + AllDataType::copyVal(def.bindVal_, colPtr, def.type_, def.length_); + colPtr = colPtr + os::align(AllDataType::size(def.type_, def.length_)); + } + return OK; +} + +//-1 index not supported +DbRetVal TableImpl::insertIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple) +{ + INDEX *iptr = (INDEX*)indexPtr; + DbRetVal ret = OK; + printDebug(DM_Table, "Inside insertIndexNode type %d", iptr->indexType_); + Index* idx = Index::getIndex(iptr->indexType_); + ret = idx->insert(this, tr, indexPtr, info, tuple,undoFlag); + return ret; +} + +DbRetVal TableImpl::deleteIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple) +{ + INDEX *iptr = (INDEX*)indexPtr; + DbRetVal ret = OK; + Index* idx = Index::getIndex(iptr->indexType_); + ret = idx->remove(this, tr, indexPtr, info, tuple, undoFlag); + return ret; +} +void TableImpl::printSQLIndexString() +{ + CatalogTableINDEXFIELD cIndexField(sysDB_); + char fName[IDENTIFIER_LENGTH]; + char *fldName = fName; + DataType type; + for (int i = 0; i < numIndexes_ ; i++) + { + INDEX *iptr = (INDEX*) indexPtr_[i]; + //cIndexField.getFieldNameAndType((void*)iptr, fldName, type); + //printf("CREATE INDEX %s on %s ( %s ) ", iptr->indName_, getName(), fldName); + printf("CREATE INDEX %s on %s ( ", iptr->indName_, getName()); + FieldList fldList; + cIndexField.getFieldInfo(iptr, fldList); + FieldIterator fIter = fldList.getIterator(); + bool firstFld = true; + while(fIter.hasElement()) + { + FieldDef def = fIter.nextElement(); + if (firstFld) { printf(" %s ", def.fldName_); firstFld = false; } + else printf(" ,%s ", def.fldName_); + } + printf(" ) "); + if (((HashIndexInfo*) idxInfo[i])->isUnique) printf(" UNIQUE;\n"); else printf(";\n"); + } +} + + +DbRetVal TableImpl::updateIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple) +{ + INDEX *iptr = (INDEX*)indexPtr; + DbRetVal ret = OK; + Index* idx = Index::getIndex(iptr->indexType_); + //TODO::currently it updates irrespective of whether the key changed or not + //because of this commenting the whole index update code. relook at it and uncomment + + ret = idx->update(this, tr, indexPtr, info, tuple, undoFlag); + + return ret; +} + + +void TableImpl::setTableInfo(char *name, int tblid, size_t length, + int numFld, int numIdx, void *chunk) +{ + strcpy(tblName_, name); + tblID_ = tblid; + length_ = length; + numFlds_ = numFld; + numIndexes_ = numIdx; + chunkPtr_ = chunk; +} + +long TableImpl::spaceUsed() +{ + Chunk *chk = (Chunk*)chunkPtr_; + long totSize = chk->getTotalDataNodes() * chk->getSize(); + totSize = totSize + (chk->totalPages() * sizeof (PageInfo)); + return totSize; +} + +int TableImpl::pagesUsed() +{ + Chunk *chk = (Chunk*)chunkPtr_; + return chk->totalPages(); +} + +long TableImpl::numTuples() +{ + return ((Chunk*)chunkPtr_)->getTotalDataNodes(); +} + +List TableImpl::getFieldNameList() +{ + List fldNameList; + FieldIterator fIter = fldList_.getIterator(); + while (fIter.hasElement()) + { + FieldDef def = fIter.nextElement(); + Identifier *elem = new Identifier(); + strcpy(elem->name, def.fldName_); + fldNameList.append(elem); + } + return fldNameList; +} +DbRetVal TableImpl::close() +{ + if (NULL == iter) + { + printError(ErrNotOpen,"Scan not open"); + return ErrNotOpen; + } + iter->close(); + delete iter; + iter = NULL; + return OK; +} +DbRetVal TableImpl::lock(bool shared) +{ + + DbRetVal ret = OK; +/* + if (shared) + ret = lMgr_->getSharedLock(chunkPtr_, NULL); + else + ret = lMgr_->getExclusiveLock(chunkPtr_, NULL); + if (OK != ret) + { + printError(ret, "Could not exclusive lock on the table %x", chunkPtr_); + }else { + //do not append for S to X upgrade + if (!ProcessManager::hasLockList.exists(chunkPtr_)) + ProcessManager::hasLockList.append(chunkPtr_); + } +*/ + return ret; +} +DbRetVal TableImpl::unlock() +{ +/* + if (!ProcessManager::hasLockList.exists(chunkPtr_)) return OK; + DbRetVal ret = lMgr_->releaseLock(chunkPtr_); + if (OK != ret) + { + printError(ret, "Could not release exclusive lock on the table %x", chunkPtr_); + }else + { + ProcessManager::hasLockList.remove(chunkPtr_); + } +*/ + return OK; +} + +TableImpl::~TableImpl() +{ + if (NULL != iter ) { delete iter; iter = NULL; } + if (NULL != indexPtr_) { delete[] indexPtr_; indexPtr_ = NULL; } + if (NULL != idxInfo) + { + for (int i = 0; i < numIndexes_; i++) delete idxInfo[i]; + delete[] idxInfo; + idxInfo = NULL; + } + if (numFlds_ > 31 && cNullInfo != NULL) { free(cNullInfo); cNullInfo = NULL; } + + fldList_.removeAll(); + +} diff --git a/src/storage/Transaction.cxx b/src/storage/Transaction.cxx new file mode 100644 index 00000000..d9ffe45e --- /dev/null +++ b/src/storage/Transaction.cxx @@ -0,0 +1,274 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include + +DbRetVal Transaction::insertIntoHasList(Database *sysdb, LockHashNode *node) +{ + //allocate lock node + Chunk *chunk = sysdb->getSystemDatabaseChunk(TransHasTableId); + DbRetVal rv = OK; + TransHasNode *hasNode = (TransHasNode*)chunk->allocate(sysdb, &rv); + if (NULL == hasNode) + { + printError(rv, "Could not allocate Lock node"); + return rv; + } + printDebug(DM_Transaction, "insertIntoHasList new TransHasNode created:%x", + hasNode); + hasNode->node_ = node; + hasNode->next_ = NULL; + if (NULL == hasLockList_) + { + printDebug(DM_Transaction, "hasLockList is null:It is now %x",hasNode); + hasLockList_ = hasNode; + return OK; + } + + TransHasNode *it = hasLockList_; + while (NULL != it->next_) { it = it->next_; } + it->next_ = hasNode; + printDebug(DM_Transaction, "Added to hasLockList at end:%x",it); + return OK; +} + +DbRetVal Transaction::removeFromHasList(Database *sysdb, void *tuple) +{ + Chunk *chunk = sysdb->getSystemDatabaseChunk(TransHasTableId); + TransHasNode *iter = hasLockList_, *prev = hasLockList_; + if (NULL == iter) + { + printError(ErrNotFound, "There are no tuple lock in has list."); + return ErrNotFound; + } + while (iter != NULL) + { + if (tuple == iter->node_->ptrToTuple_) + { + prev->next_ = iter->next_; + chunk->free(sysdb, iter); + if (iter == hasLockList_) hasLockList_ = NULL; + return OK; + } + prev = iter; + iter = iter->next_; + } + printError(ErrNotFound, "There are no tuple lock in has list."); + return ErrNotFound; +} + + +DbRetVal Transaction::releaseAllLocks(LockManager *lockManager_) +{ + Database *sysdb =lockManager_->systemDatabase_; + Chunk *chunk = sysdb->getSystemDatabaseChunk(TransHasTableId); + TransHasNode *iter = hasLockList_, *prev; + while (NULL != iter) + { + prev = iter; + iter = iter->next_; + printDebug(DM_Transaction, "Releasing lock %x",prev->node_->ptrToTuple_); + lockManager_->releaseLock(prev->node_->ptrToTuple_); + chunk->free(sysdb, prev); + } + hasLockList_ = NULL; + return OK; +} +bool Transaction::findInHasList(Database *sysdb, LockHashNode *node) +{ + TransHasNode *iter = hasLockList_; + while (NULL != iter) + { + if (iter->node_ == node) return true; + iter = iter->next_; + } + return false; +} + +DbRetVal Transaction::appendUndoLog(Database *sysdb, OperationType type, + void *data, size_t size) +{ + DbRetVal rv =OK; + UndoLogInfo *logInfo = createUndoLog(sysdb, type, data, size, &rv); + if (logInfo == NULL) return rv; + os::memcpy((char*)logInfo + sizeof(UndoLogInfo), data, size); + addAtBegin(logInfo); + printDebug(DM_Transaction, "creating undo log and append %x optype:%d", + logInfo, type); + return OK; +} + + + +DbRetVal Transaction::appendLogicalUndoLog(Database *sysdb, OperationType type, void *data, + size_t size, void* indexPtr) +{ + DbRetVal rv = OK; + UndoLogInfo *logInfo = createUndoLog(sysdb, type, data, size, &rv); + if (logInfo == NULL) return rv; + char **indPtr = (char**)((char*)logInfo + sizeof(UndoLogInfo)); + *indPtr = (char*) indexPtr; + addAtBegin(logInfo); + printDebug(DM_Transaction, "creating logical undo log and append %x optype:%d", + logInfo, type); + return rv; +} + +UndoLogInfo* Transaction::createUndoLog(Database *sysdb, OperationType type, void *data, + size_t size, DbRetVal *rv) +{ + Chunk *chunk = sysdb->getSystemDatabaseChunk(UndoLogTableID); + UndoLogInfo *logInfo = (UndoLogInfo*)chunk->allocate(sysdb, + size + sizeof(UndoLogInfo), rv); + if (logInfo == NULL) { + printError(*rv, "Unable to allocate undo log record\n"); + return NULL; + } + logInfo->opType_ = type; + logInfo->ptrToTuple_ = data; + logInfo->size_ = size; + logInfo->next_ = NULL; + return logInfo; +} + +void Transaction::addAtBegin(UndoLogInfo* logInfo) +{ + //add it to the begin of the log list + logInfo->next_ = firstUndoLog_; + firstUndoLog_ = logInfo; + return; +} + +UndoLogInfo* Transaction::popUndoLog() +{ + UndoLogInfo *iter = firstUndoLog_, *prev = firstUndoLog_; + if(NULL != iter) + { + prev = iter; + iter = iter->next_; + } + firstUndoLog_ = iter; + return prev; + +} + +int Transaction::noOfUndoLogs() +{ + UndoLogInfo *iter = firstUndoLog_; + int count =0; + while(NULL != iter) + { + count++; + iter = iter->next_; + } + return count; +} +void Transaction::printDebugInfo(Database *sysdb) +{ + printf("\n"); + if (waitLock_ != NULL) + { + printf(""); + waitLock_->print(); + printf(""); + + } + printf("\n"); + Chunk *chunk = sysdb->getSystemDatabaseChunk(UndoLogTableID); + printf(" %d \n", chunk->totalPages()); + UndoLogInfo *iter = firstUndoLog_; + int count =0; + while(NULL != iter) + { + iter->print(); + iter = iter->next_; + count++; + } + printf(" %d \n", count); + printf("\n"); + + printf("\n"); + chunk = sysdb->getSystemDatabaseChunk(TransHasTableId); + printf(" %d \n", chunk->totalPages()); + TransHasNode *hasIter = hasLockList_; + count =0; + while (NULL != hasIter) + { + hasIter->print(); + hasIter = hasIter->next_; + count++; + } + printf(" %d \n", count); + printf("\n"); + + printf("\n"); + return ; +} +DbRetVal Transaction::removeUndoLogs(Database *sysdb) +{ + Chunk *chunk = sysdb->getSystemDatabaseChunk(UndoLogTableID); + UndoLogInfo *logInfo = NULL; + while(NULL != (logInfo = popUndoLog())) + { + chunk->free(sysdb, logInfo); + } + return OK; +} + + +DbRetVal Transaction::applyUndoLogs(Database *sysdb) +{ + Chunk *chunk = sysdb->getSystemDatabaseChunk(UndoLogTableID); + UndoLogInfo *logInfo = NULL; + while(NULL != (logInfo = popUndoLog())) + { + switch(logInfo->opType_) + { + case InsertOperation: + *((int*)(logInfo->ptrToTuple_) - 1) = 0; + //May memcpy is not needed as no one will update this + //as lock is taken on this tuple + os::memcpy(logInfo->ptrToTuple_, (char*) logInfo + + sizeof(UndoLogInfo), logInfo->size_); + break; + case DeleteOperation: + *((int*)(logInfo->ptrToTuple_) - 1) = 1; + os::memcpy(logInfo->ptrToTuple_, (char*) logInfo + + sizeof(UndoLogInfo), logInfo->size_); + break; + case UpdateOperation: + os::memcpy(logInfo->ptrToTuple_, (char*) logInfo + + sizeof(UndoLogInfo), logInfo->size_); + break; + + case InsertHashIndexOperation: + //TODO + break; + case UpdateHashIndexOperation: + //TODO + break; + case DeleteHashIndexOperation: + //TODO + break; + } + chunk->free(sysdb, logInfo); + } + return OK; +} diff --git a/src/storage/TransactionManager.cxx b/src/storage/TransactionManager.cxx new file mode 100644 index 00000000..dd8415a7 --- /dev/null +++ b/src/storage/TransactionManager.cxx @@ -0,0 +1,229 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +void TransactionManager::printUsageStatistics() +{ + Transaction *iter = firstTrans; + int i=0, usedCount =0, freeCount =0, undoLogCount=0; + for (; i < Conf::config.getMaxProcs(); i++) + { + if (iter->status_ == TransNotUsed) freeCount++; + else + { + usedCount++; + undoLogCount += iter->noOfUndoLogs(); + } + iter++; + } + printf("\n"); + printf(" %d \n", usedCount); + printf(" %d \n", freeCount); + + printf(" \n"); + printf(" %d \n", undoLogCount); + printf(" \n"); + printf("\n"); + +} + +void TransactionManager::printDebugInfo(Database *sysdb) +{ + Transaction *iter = firstTrans; + int i=0, usedCount =0, freeCount =0, undoLogCount=0; + printf("\n"); + for (; i < Conf::config.getMaxProcs(); i++) + { + if (iter->status_ == TransNotUsed) freeCount++; + else + { + usedCount++; + undoLogCount += iter->noOfUndoLogs(); + iter->printDebugInfo(sysdb); + } + iter++; + } + + printf(" %d \n", usedCount); + printf(" %d \n", freeCount); + + Chunk *chunk = sysdb->getSystemDatabaseChunk(UndoLogTableID); + + printf(" \n"); + printf(" %d \n", undoLogCount); + printf(" %d \n", chunk->totalPages()); + printf(" \n"); + printf("\n"); +} + + +DbRetVal TransactionManager::startTransaction(LockManager *lMgr, IsolationLevel level) +{ + Database *sysdb = lMgr->systemDatabase_; + Transaction *trans = ProcessManager::getThreadTransaction(sysdb->procSlot); + if (NULL != trans) + { + if (trans->status_ != TransNotUsed) return ErrAlready; + else { + //the previous transaction shall be used again + trans->status_ = TransRunning; + trans->isoLevel_ = level; + printDebug(DM_Transaction, "Using the same transaction slot\n"); + return OK; + } + + } + + DbRetVal rv = sysdb->getTransTableMutex(); + if (OK != rv) + { + printError(rv, "Unable to acquire transtable mutex"); + return rv; + } + Transaction *iter = firstTrans; + int i; + for (i =0 ; i < Conf::config.getMaxProcs(); i++) + { + if (iter->status_ == TransNotUsed) break; + iter++; + } + // if Transaction table is full return error + if (i == Conf::config.getMaxProcs()) { + printError(ErrNoResource, "Transaction slots are full"); + sysdb->releaseTransTableMutex(); + return ErrNoResource; + } + printDebug(DM_Transaction, "Using transaction slot %d \n", i); + + //Make this free slot, as the current transaction and + //set the state + trans = iter; + trans->status_ = TransRunning; + trans->isoLevel_ = level; + sysdb->releaseTransTableMutex(); + ProcessManager::setThreadTransaction(trans, sysdb->procSlot); + return OK; +} + +void TransactionManager::setFirstTrans(Transaction *trans) +{ + firstTrans = trans; +} + + +DbRetVal TransactionManager::commit(LockManager *lockManager) +{ + Database *sysdb = lockManager->systemDatabase_; + Transaction *trans = ProcessManager::getThreadTransaction(sysdb->procSlot); + if (NULL == trans) + { + printError(ErrNotOpen, "No transaction started for this procSlot %d", sysdb->procSlot); + return ErrNotOpen; + } + DbRetVal rv = sysdb->getTransTableMutex(); + if (OK != rv) + { + printError(rv, "Unable to acquire transtable mutex"); + return rv; + } + + if (trans->status_ != TransRunning) + { + sysdb->releaseTransTableMutex(); + printError(ErrBadCall, "Transaction is not in running state %d\n", trans->status_); + return ErrBadCall; + } + trans->status_ = TransCommitting; + sysdb->releaseTransTableMutex(); + + trans->releaseAllLocks(lockManager); + if(NULL != trans->waitLock_) + { + printError(ErrSysInternal, "Trans WaitLock is not null\n"); + return ErrSysInternal; + } + //TODO::flush all redo logs to disk + //TODO::remove all the logs in memory + trans->removeUndoLogs(sysdb); + rv = sysdb->getTransTableMutex(); + if (OK != rv) + { + printError(rv, "Unable to acquire transtable mutex"); + return rv; + } + trans->status_ = TransNotUsed; + sysdb->releaseTransTableMutex(); + printDebug(DM_Transaction, "Committed transaction:%x",trans); + return OK; +} + +DbRetVal TransactionManager::rollback(LockManager *lockManager, Transaction *t) +{ + Database *sysdb = lockManager->systemDatabase_; + Transaction *trans; + if (t == NULL) + trans = ProcessManager::getThreadTransaction(sysdb->procSlot); + else + trans = t; + if (NULL == trans) + { + return OK; + } + DbRetVal rv= sysdb->getTransTableMutex(); + if (OK != rv) + { + printError(rv, "Unable to acquire transtable mutex"); + return rv; + } + + if (trans->status_ != TransRunning) + { + sysdb->releaseTransTableMutex(); + //will be called during connection disconnect without starting transaction. + return OK; + } + trans->status_ = TransAborting; + sysdb->releaseTransTableMutex(); + + trans->applyUndoLogs(sysdb); + //TODO::remove all the logs in memory + trans->releaseAllLocks(lockManager); + if(NULL != trans->waitLock_) + { + printError(ErrSysInternal, "Trans waitlock is not null"); + return ErrSysInternal; + } + + rv = sysdb->getTransTableMutex(); + if (OK != rv) + { + //nothing can be done.. go ahead and set it. + //no harm. parallel starttransaction will miss this slot. thats ok + //as it is not leak + } + trans->status_ = TransNotUsed; + sysdb->releaseTransTableMutex(); + printDebug(DM_Transaction, "Aborted transaction:%x",trans); + + return OK; +} diff --git a/src/storage/TupleIterator.cxx b/src/storage/TupleIterator.cxx new file mode 100644 index 00000000..2ef266d4 --- /dev/null +++ b/src/storage/TupleIterator.cxx @@ -0,0 +1,148 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +DbRetVal TupleIterator::open() +{ + + if (fullTableScan == scanType_) + { + cIter = new ChunkIterator(); + *cIter = ((Chunk*)chunkPtr_)->getIterator(); + }else if (hashIndexScan == scanType_) + { + HashIndexInfo *hIdxInfo = (HashIndexInfo*)info; + PredicateImpl *predImpl = (PredicateImpl*) pred_; + bool isPtr = false; + FieldIterator iter = hIdxInfo->idxFldList.getIterator(); + char *keyBuffer; + keyBuffer = (char*) malloc(hIdxInfo->compLength); + void *keyStartBuffer = (void*) keyBuffer, *keyPtr; + while(iter.hasElement()) + { + FieldDef def = iter.nextElement(); + keyPtr = (void*)predImpl->valPtrForIndexField(def.fldName_); + AllDataType::copyVal(keyBuffer, keyPtr, def.type_, def.length_); + keyBuffer = keyBuffer + AllDataType::size(def.type_, def.length_); + } + + int bucketNo = HashIndex::computeHashBucket(hIdxInfo->type, + keyStartBuffer, hIdxInfo->noOfBuckets, hIdxInfo->compLength); + free(keyStartBuffer); + Bucket *bucket = &(hIdxInfo->buckets[bucketNo]); + int ret = bucket->mutex_.getLock(procSlot); + if (ret != 0) + { + printError(ErrLockTimeOut,"Unable to acquire bucket Mutex for bucket %d",bucketNo); + return ErrLockTimeOut; + } + HashIndexNode *head = (HashIndexNode*) bucket->bucketList_; + if (!head) + { + bucket->mutex_.releaseLock(procSlot); + bIter = NULL ; + return OK; + } + printDebug(DM_HashIndex, "open:head for bucket %x is :%x", bucket, head); + bIter = new BucketIter(head); + bucket->mutex_.releaseLock(procSlot); + + } + return OK; +} + + +void* TupleIterator::next() +{ + PredicateImpl *predImpl = (PredicateImpl*) pred_; + void *tuple = NULL; + DbRetVal rv = OK; + if (fullTableScan == scanType_) + { + + if (NULL == pred_ ) + { + //no predicates + return cIter->nextElement(); + } + else + { + //evaluate till it succeeds + bool result = false; + while (!result) + { + tuple = cIter->nextElement(); + if(NULL == tuple) return NULL; + predImpl->setTuple(tuple); + printDebug(DM_Table, "Evaluating the predicate from fullTableScan"); + rv = predImpl->evaluate(result); + if (rv != OK) return NULL; + } + } + }else if (hashIndexScan == scanType_) + { + if (NULL == bIter) + { + //if there are no nodes in bucket bIter will be null + return NULL; + } + //evaluate till it succeeds + bool result = false; + while (!result) + { + HashIndexNode *node = bIter->next(); + if (node == NULL) return NULL; + printDebug(DM_HashIndex, "next: returned HashIndexNode: %x", node); + tuple = node->ptrToTuple_; + if(NULL == tuple) { + printDebug(DM_HashIndex, "next::tuple is null"); + return NULL; + } + + //if (!predImpl->isSingleTerm()) { + printDebug(DM_HashIndex, "next: predicate has more than single term"); + predImpl->setTuple(tuple); + printDebug(DM_Table, "Evaluating the predicate from hashIndexScan: has more than one term"); + rv = predImpl->evaluate(result); + if (rv != OK) return NULL; + //} + //else + // return tuple; + } + + } + return tuple; +} + +DbRetVal TupleIterator::close() +{ + if (scanType_ == fullTableScan) + { + delete cIter; + cIter = NULL; + } else if (scanType_ == hashIndexScan) + { + delete bIter; + bIter = NULL; + } + scanType_ = unknownScan; + return OK; +} diff --git a/src/storage/UserManagerImpl.cxx b/src/storage/UserManagerImpl.cxx new file mode 100644 index 00000000..1163d6aa --- /dev/null +++ b/src/storage/UserManagerImpl.cxx @@ -0,0 +1,93 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +int UserManagerImpl::createUser(const char *name, const char *password) +{ + if (!isDba) + { + printError(ErrNoPrivilege, + "Only DBA privileged schema can create users"); + return ErrNoPrivilege; + } + int ret = 0; + //add entry to USER table + CatalogTableUSER cUser(systemDatabase_); + cUser.insert(name, password); + if (0 != ret) + { + printError(ErrSysInternal, + "Catalog table insert failed for the user %s",name); + return ErrSysInternal; + } + return OK; +} + +int UserManagerImpl::deleteUser(const char *name) +{ + if (!isDba) + { + printError(ErrNoPrivilege, + "Only DBA privileged schema can delete users"); + return ErrNoPrivilege; + } + int ret = 0; + CatalogTableUSER cUser(systemDatabase_); + ret = cUser.remove(name); + if (0 != ret) + { + printError(ErrNotExists, + "User %s not exists",name); + return ErrNotExists; + } + return OK; +} + +int UserManagerImpl::changePassword(const char *usrName, const char* newPasswd) +{ + if (!isDba) + { + printError(ErrNoPrivilege, + "Only DBA privileged schema can change password for other users"); + return ErrNoPrivilege; + } + int ret = 0; + CatalogTableUSER cUser(systemDatabase_); + ret = cUser.changePass(usrName, newPasswd ); + if (0 != ret) + { + printError(ErrSysInternal, + "Catalog table updation failed for user %s",usrName); + return ErrSysInternal; + } + return OK; +} + + +int UserManagerImpl::changePassword(const char* newPasswd) +{ + int ret = 0; + CatalogTableUSER cUser(systemDatabase_); + ret = cUser.changePass(userName, newPasswd ); + if (0 != ret) + { + printError(ErrSysInternal, + "Catalog table updation failed"); + return ErrSysInternal; + } + return OK; +} diff --git a/src/storage/os.cxx b/src/storage/os.cxx new file mode 100644 index 00000000..8ad7333c --- /dev/null +++ b/src/storage/os.cxx @@ -0,0 +1,256 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include + +caddr_t os::mmap(caddr_t addr, size_t len, int prot, int flags, int fildes, off_t off) +{ + return ((caddr_t)::mmap(addr,len,prot,flags,fildes,off)); +} + +int os::munmap(caddr_t addr, size_t len) +{ + return ::munmap(addr, len); +} + + +shared_memory_id os::shm_create(shared_memory_key key, size_t size, int flag) +{ + return ::shmget(key, size, IPC_CREAT | IPC_EXCL | flag); + //return ::shmget(key, size, IPC_CREAT | flag); +} + +shared_memory_id os::shm_open(shared_memory_key key, size_t size, int flag) +{ + return ::shmget(key, size, flag); +} +int os::shmctl(int shmid, int cmd) +{ + return ::shmctl(shmid, cmd, NULL); +} + +void* os::shm_attach(shared_memory_id id, const void *ptr, int flag) +{ + return ::shmat(id, ptr, flag); +} + +int os::shm_detach (void* addr) +{ + return ::shmdt((char*)addr); +} + +double os::floor(double val) +{ + return ::floor(val); +} + +int os::gettimeofday(struct timeval *tp) +{ + int retval; + retval=::gettimeofday(tp, NULL); + return retval; +} + +struct tm* os::localtime(long *secs) +{ + return ::localtime(secs); +} + +pid_t os::getpid() +{ + return ::getpid(); +} +pthread_t os::getthrid() +{ + return ::pthread_self(); +} + + + + +int os::openFile(const char *name, FileOpenMode flags, size_t size) +{ + int retval = -1; + //mode_t mode = S_IRWXU | S_IRGRP | S_IWGRP ; + mode_t mode = (mode_t)0755 ; + retval=::open(name, flags, mode); + if (0 == size) + return retval; + os::lseek(retval, size-1, SEEK_SET); + char *buf = (char*)" "; + os::write(retval, buf, 1); + return retval; +} + +int os::closeFile(int fd) +{ + return ::close(fd); +} + +off_t os::lseek(int fildes, off_t offset, int whence) +{ + return ::lseek(fildes, offset, whence); +} + +size_t os::write(int fildes, char *buf, size_t size) +{ + return ::write(fildes, buf, size); +} + +int os::msync(caddr_t addr, size_t len, int flags) +{ + return ::msync(addr, len, flags); +} +int os::fsync(int fildes) +{ + return ::fsync(fildes); +} + +char* os::encrypt(const char *key, const char *salt) +{ + return ::crypt(key, salt); +} + +void* os::memset(void *src, int c, size_t size) +{ + return::memset(src, c, size); +} + +void* os::memcpy(void *src, const void *dest, size_t size) +{ + return ::memcpy(src, dest, size); +} + +int os::memcmp(const void *s1, const void *s2, size_t size) +{ + return ::memcmp(s1, s2, size); +} +sighandler_t os::signal(int signum, sighandler_t handler) +{ + return ::signal(signum, handler); +} + +size_t os::alignLong(size_t size) +{ + return ((size - 1) | (sizeof(long) - 1)) + 1; +} + +size_t os::align(size_t size) +{ + //Calls alignLong + return ((size - 1) | (sizeof(long) - 1)) + 1; +} + +int os::select(int nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, struct timeval * timeout) +{ + return ::select(nfds, readfds, writefds, exceptfds, timeout); +} +int os::sleep(int secs) +{ + return ::sleep(secs); +} +int os::usleep(int msecs) +{ + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = msecs; + os::select(0,0,0,0, &timeout); + return 0; +} + + + +char* os::getenv(const char *envVarName) +{ + char *retVal; + retVal = ::getenv(envVarName); + return retVal; +} + +int os::setenv(const char *envVarName, const char *value) +{ + return ::setenv(envVarName, value,1); +} + +int os::kill(pid_t pid, int sig) +{ + return ::kill(pid, sig); +} +bool os::atobool(char *value) +{ + if (strlen(value) ==3 && strncasecmp(value,"YES",3)==0) return true; + else if (strlen(value) ==2 && strncasecmp(value,"NO", 2)==0) return false; + else if (strlen(value) ==4 && strncasecmp(value,"true",4)==0) return true; + else if (strlen(value) ==5 && strncasecmp(value,"false",5)==0) return false; + return false; +} +pid_t os::createProcess(const char* cmdName, const char *arg0, ...) +{ + pid_t pid; + pid = ::vfork(); + if (pid == (pid_t) -1 ) + { + printf("Process creation failed\n"); + return -1; + } + if (pid >0) + { + //return for parent + return pid; + } + va_list ap; + va_start(ap,arg0); + + const char *argv[5]; + + argv[0]=cmdName; + argv[1]=arg0; + + argv[2]=NULL; + int i = 2; + while(argv[i++]=va_arg(ap,char *)); + switch(i){ + case 2: + pid=::execl(argv[0],argv[1]);break; + case 3: + pid=::execl(argv[0],argv[1],argv[2]);break; + case 4: + pid=::execl(argv[0],argv[1],argv[2],argv[3]);break; + case 5: + pid=::execl(argv[0],argv[1],argv[2],argv[3],argv[4]);break; + default: + printf("only three options allowed\n"); + pid=-1;break; + } + if (pid < 0) + printf("Exec failed\n"); + return pid; + +} +pid_t os::fork() +{ + return ::fork(); +} +size_t os::send(int fd, const void *buf, size_t len, int flags) +{ + return ::send(fd, buf, len, flags); +} +size_t os::recv(int fd, void *buf, size_t len, int flags) +{ + return ::recv(fd, buf, len, flags); +} diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am index 4ebbe3d3..542727f1 100644 --- a/src/tools/Makefile.am +++ b/src/tools/Makefile.am @@ -2,14 +2,14 @@ INCLUDES = -I$(top_srcdir)/include $(all_includes) -I$(top_srcdir)/src/sql METASOURCES = AUTO bin_PROGRAMS = csql catalog cachetable csqlserver csqlreplserver repltable csqlcacheserver csqldump cacheverify csql_SOURCES = isql.cxx -csql_LDADD = $(top_builddir)/src/server/.libs/libcsql $(top_builddir)/src/sql/.libs/libcsqlsql $(top_builddir)/src/sqllog/.libs/libcsqlsqllog $(top_builddir)/src/network/.libs/libcsqlnw $(top_builddir)/src/adapter/.libs/libcsqlodbcadapter $(top_builddir)/src/gateway/.libs/libcsqlgw -lrt -lpthread -lcrypt -lodbc +csql_LDADD = $(top_builddir)/src/storage/.libs/libcsql $(top_builddir)/src/sql/.libs/libcsqlsql $(top_builddir)/src/sqllog/.libs/libcsqlsqllog $(top_builddir)/src/network/.libs/libcsqlnw $(top_builddir)/src/adapter/.libs/libcsqlodbcadapter $(top_builddir)/src/gateway/.libs/libcsqlgw -lrt -lpthread -lcrypt -lodbc catalog_SOURCES = catalog.cxx -catalog_LDADD = $(top_builddir)/src/server/libcsql.la +catalog_LDADD = $(top_builddir)/src/storage/libcsql.la catalog_LDFLAGS = -lcrypt cachetable_LDADD = $(top_builddir)/src/cache/libcacheload.la \ - $(top_builddir)/src/server/libcsql.la $(top_builddir)/src/adapter/libcsqlodbcadapter.la + $(top_builddir)/src/storage/libcsql.la $(top_builddir)/src/adapter/libcsqlodbcadapter.la cachetable_LDFLAGS = -lcrypt -lodbc cachetable_SOURCES = cachetable.cxx @@ -18,20 +18,20 @@ cacheverify_LDADD = $(top_builddir)/src/sql/libcsqlsql.la \ $(top_builddir)/src/network/libcsqlnw.la \ $(top_builddir)/src/gateway/libcsqlgw.la \ $(top_builddir)/src/adapter/libcsqlodbcadapter.la \ - $(top_builddir)/src/server/libcsql.la -lrt -lpthread -lcrypt - $(top_builddir)/src/server/libcsql.la $(top_builddir)/src/adapter/libcsqlodbcadapter.la + $(top_builddir)/src/storage/libcsql.la -lrt -lpthread -lcrypt + $(top_builddir)/src/storage/libcsql.la $(top_builddir)/src/adapter/libcsqlodbcadapter.la cacheverify_LDFLAGS = -lcrypt -lodbc cacheverify_SOURCES = cacheverify.cxx repltable_LDADD = $(top_builddir)/src/cache/libcacheload.la \ - $(top_builddir)/src/server/libcsql.la \ + $(top_builddir)/src/storage/libcsql.la \ $(top_builddir)/src/adapter/libcsqlodbcadapter.la \ $(top_builddir)/src/gateway/libcsqlgw.la repltable_LDFLAGS = -lcrypt -lodbc repltable_SOURCES = repltable.cxx csqlserver_LDADD = $(top_builddir)/src/cache/libcacheload.la \ - $(top_builddir)/src/server/libcsql.la \ + $(top_builddir)/src/storage/libcsql.la \ $(top_builddir)/src/gateway/libcsqlgw.la -lrt -lpthread -lcrypt csqlserver_LDFLAGS = -lcrypt -lodbc csqlserver_SOURCES = csqlserver.cxx @@ -41,7 +41,7 @@ csqlreplserver_LDADD = $(top_builddir)/src/sql/libcsqlsql.la \ $(top_builddir)/src/network/libcsqlnw.la \ $(top_builddir)/src/gateway/libcsqlgw.la \ $(top_builddir)/src/adapter/libcsqlodbcadapter.la \ - $(top_builddir)/src/server/libcsql.la -lrt -lpthread -lcrypt + $(top_builddir)/src/storage/libcsql.la -lrt -lpthread -lcrypt csqlreplserver_LDFLAGS = -lcrypt -lodbc csqlreplserver_SOURCES = csqlreplserver.cxx @@ -50,7 +50,7 @@ csqldump_LDADD = $(top_builddir)/src/sql/libcsqlsql.la \ $(top_builddir)/src/network/libcsqlnw.la \ $(top_builddir)/src/gateway/libcsqlgw.la \ $(top_builddir)/src/adapter/libcsqlodbcadapter.la \ - $(top_builddir)/src/server/libcsql.la -lrt -lpthread -lcrypt + $(top_builddir)/src/storage/libcsql.la -lrt -lpthread -lcrypt csqldump_LDFLAGS = -lcrypt -lodbc csqldump_SOURCES = csqldump.cxx @@ -59,6 +59,6 @@ csqlcacheserver_LDADD = $(top_builddir)/src/sql/libcsqlsql.la \ $(top_builddir)/src/network/libcsqlnw.la \ $(top_builddir)/src/gateway/libcsqlgw.la \ $(top_builddir)/src/adapter/libcsqlodbcadapter.la \ - $(top_builddir)/src/server/libcsql.la -lrt -lpthread -lcrypt + $(top_builddir)/src/storage/libcsql.la -lrt -lpthread -lcrypt csqlcacheserver_LDFLAGS = -lcrypt -lodbc csqlcacheserver_SOURCES = csqlcacheserver.cxx diff --git a/src/tools/Makefile.in b/src/tools/Makefile.in index 0cd095a7..1b26dbef 100644 --- a/src/tools/Makefile.in +++ b/src/tools/Makefile.in @@ -55,7 +55,7 @@ PROGRAMS = $(bin_PROGRAMS) am_cachetable_OBJECTS = cachetable.$(OBJEXT) cachetable_OBJECTS = $(am_cachetable_OBJECTS) cachetable_DEPENDENCIES = $(top_builddir)/src/cache/libcacheload.la \ - $(top_builddir)/src/server/libcsql.la \ + $(top_builddir)/src/storage/libcsql.la \ $(top_builddir)/src/adapter/libcsqlodbcadapter.la am_cacheverify_OBJECTS = cacheverify.$(OBJEXT) cacheverify_OBJECTS = $(am_cacheverify_OBJECTS) @@ -64,13 +64,13 @@ cacheverify_DEPENDENCIES = $(top_builddir)/src/sql/libcsqlsql.la \ $(top_builddir)/src/network/libcsqlnw.la \ $(top_builddir)/src/gateway/libcsqlgw.la \ $(top_builddir)/src/adapter/libcsqlodbcadapter.la \ - $(top_builddir)/src/server/libcsql.la + $(top_builddir)/src/storage/libcsql.la am_catalog_OBJECTS = catalog.$(OBJEXT) catalog_OBJECTS = $(am_catalog_OBJECTS) -catalog_DEPENDENCIES = $(top_builddir)/src/server/libcsql.la +catalog_DEPENDENCIES = $(top_builddir)/src/storage/libcsql.la am_csql_OBJECTS = isql.$(OBJEXT) csql_OBJECTS = $(am_csql_OBJECTS) -csql_DEPENDENCIES = $(top_builddir)/src/server/.libs/libcsql \ +csql_DEPENDENCIES = $(top_builddir)/src/storage/.libs/libcsql \ $(top_builddir)/src/sql/.libs/libcsqlsql \ $(top_builddir)/src/sqllog/.libs/libcsqlsqllog \ $(top_builddir)/src/network/.libs/libcsqlnw \ @@ -83,7 +83,7 @@ csqlcacheserver_DEPENDENCIES = $(top_builddir)/src/sql/libcsqlsql.la \ $(top_builddir)/src/network/libcsqlnw.la \ $(top_builddir)/src/gateway/libcsqlgw.la \ $(top_builddir)/src/adapter/libcsqlodbcadapter.la \ - $(top_builddir)/src/server/libcsql.la + $(top_builddir)/src/storage/libcsql.la am_csqldump_OBJECTS = csqldump.$(OBJEXT) csqldump_OBJECTS = $(am_csqldump_OBJECTS) csqldump_DEPENDENCIES = $(top_builddir)/src/sql/libcsqlsql.la \ @@ -91,7 +91,7 @@ csqldump_DEPENDENCIES = $(top_builddir)/src/sql/libcsqlsql.la \ $(top_builddir)/src/network/libcsqlnw.la \ $(top_builddir)/src/gateway/libcsqlgw.la \ $(top_builddir)/src/adapter/libcsqlodbcadapter.la \ - $(top_builddir)/src/server/libcsql.la + $(top_builddir)/src/storage/libcsql.la am_csqlreplserver_OBJECTS = csqlreplserver.$(OBJEXT) csqlreplserver_OBJECTS = $(am_csqlreplserver_OBJECTS) csqlreplserver_DEPENDENCIES = $(top_builddir)/src/sql/libcsqlsql.la \ @@ -99,16 +99,16 @@ csqlreplserver_DEPENDENCIES = $(top_builddir)/src/sql/libcsqlsql.la \ $(top_builddir)/src/network/libcsqlnw.la \ $(top_builddir)/src/gateway/libcsqlgw.la \ $(top_builddir)/src/adapter/libcsqlodbcadapter.la \ - $(top_builddir)/src/server/libcsql.la + $(top_builddir)/src/storage/libcsql.la am_csqlserver_OBJECTS = csqlserver.$(OBJEXT) csqlserver_OBJECTS = $(am_csqlserver_OBJECTS) csqlserver_DEPENDENCIES = $(top_builddir)/src/cache/libcacheload.la \ - $(top_builddir)/src/server/libcsql.la \ + $(top_builddir)/src/storage/libcsql.la \ $(top_builddir)/src/gateway/libcsqlgw.la am_repltable_OBJECTS = repltable.$(OBJEXT) repltable_OBJECTS = $(am_repltable_OBJECTS) repltable_DEPENDENCIES = $(top_builddir)/src/cache/libcacheload.la \ - $(top_builddir)/src/server/libcsql.la \ + $(top_builddir)/src/storage/libcsql.la \ $(top_builddir)/src/adapter/libcsqlodbcadapter.la \ $(top_builddir)/src/gateway/libcsqlgw.la DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) @@ -242,12 +242,12 @@ target_alias = @target_alias@ INCLUDES = -I$(top_srcdir)/include $(all_includes) -I$(top_srcdir)/src/sql METASOURCES = AUTO csql_SOURCES = isql.cxx -csql_LDADD = $(top_builddir)/src/server/.libs/libcsql $(top_builddir)/src/sql/.libs/libcsqlsql $(top_builddir)/src/sqllog/.libs/libcsqlsqllog $(top_builddir)/src/network/.libs/libcsqlnw $(top_builddir)/src/adapter/.libs/libcsqlodbcadapter $(top_builddir)/src/gateway/.libs/libcsqlgw -lrt -lpthread -lcrypt -lodbc +csql_LDADD = $(top_builddir)/src/storage/.libs/libcsql $(top_builddir)/src/sql/.libs/libcsqlsql $(top_builddir)/src/sqllog/.libs/libcsqlsqllog $(top_builddir)/src/network/.libs/libcsqlnw $(top_builddir)/src/adapter/.libs/libcsqlodbcadapter $(top_builddir)/src/gateway/.libs/libcsqlgw -lrt -lpthread -lcrypt -lodbc catalog_SOURCES = catalog.cxx -catalog_LDADD = $(top_builddir)/src/server/libcsql.la +catalog_LDADD = $(top_builddir)/src/storage/libcsql.la catalog_LDFLAGS = -lcrypt cachetable_LDADD = $(top_builddir)/src/cache/libcacheload.la \ - $(top_builddir)/src/server/libcsql.la $(top_builddir)/src/adapter/libcsqlodbcadapter.la + $(top_builddir)/src/storage/libcsql.la $(top_builddir)/src/adapter/libcsqlodbcadapter.la cachetable_LDFLAGS = -lcrypt -lodbc cachetable_SOURCES = cachetable.cxx @@ -256,19 +256,19 @@ cacheverify_LDADD = $(top_builddir)/src/sql/libcsqlsql.la \ $(top_builddir)/src/network/libcsqlnw.la \ $(top_builddir)/src/gateway/libcsqlgw.la \ $(top_builddir)/src/adapter/libcsqlodbcadapter.la \ - $(top_builddir)/src/server/libcsql.la -lrt -lpthread -lcrypt + $(top_builddir)/src/storage/libcsql.la -lrt -lpthread -lcrypt cacheverify_LDFLAGS = -lcrypt -lodbc cacheverify_SOURCES = cacheverify.cxx repltable_LDADD = $(top_builddir)/src/cache/libcacheload.la \ - $(top_builddir)/src/server/libcsql.la \ + $(top_builddir)/src/storage/libcsql.la \ $(top_builddir)/src/adapter/libcsqlodbcadapter.la \ $(top_builddir)/src/gateway/libcsqlgw.la repltable_LDFLAGS = -lcrypt -lodbc repltable_SOURCES = repltable.cxx csqlserver_LDADD = $(top_builddir)/src/cache/libcacheload.la \ - $(top_builddir)/src/server/libcsql.la \ + $(top_builddir)/src/storage/libcsql.la \ $(top_builddir)/src/gateway/libcsqlgw.la -lrt -lpthread -lcrypt csqlserver_LDFLAGS = -lcrypt -lodbc @@ -278,7 +278,7 @@ csqlreplserver_LDADD = $(top_builddir)/src/sql/libcsqlsql.la \ $(top_builddir)/src/network/libcsqlnw.la \ $(top_builddir)/src/gateway/libcsqlgw.la \ $(top_builddir)/src/adapter/libcsqlodbcadapter.la \ - $(top_builddir)/src/server/libcsql.la -lrt -lpthread -lcrypt + $(top_builddir)/src/storage/libcsql.la -lrt -lpthread -lcrypt csqlreplserver_LDFLAGS = -lcrypt -lodbc csqlreplserver_SOURCES = csqlreplserver.cxx @@ -287,7 +287,7 @@ csqldump_LDADD = $(top_builddir)/src/sql/libcsqlsql.la \ $(top_builddir)/src/network/libcsqlnw.la \ $(top_builddir)/src/gateway/libcsqlgw.la \ $(top_builddir)/src/adapter/libcsqlodbcadapter.la \ - $(top_builddir)/src/server/libcsql.la -lrt -lpthread -lcrypt + $(top_builddir)/src/storage/libcsql.la -lrt -lpthread -lcrypt csqldump_LDFLAGS = -lcrypt -lodbc csqldump_SOURCES = csqldump.cxx @@ -296,7 +296,7 @@ csqlcacheserver_LDADD = $(top_builddir)/src/sql/libcsqlsql.la \ $(top_builddir)/src/network/libcsqlnw.la \ $(top_builddir)/src/gateway/libcsqlgw.la \ $(top_builddir)/src/adapter/libcsqlodbcadapter.la \ - $(top_builddir)/src/server/libcsql.la -lrt -lpthread -lcrypt + $(top_builddir)/src/storage/libcsql.la -lrt -lpthread -lcrypt csqlcacheserver_LDFLAGS = -lcrypt -lodbc csqlcacheserver_SOURCES = csqlcacheserver.cxx @@ -604,7 +604,7 @@ uninstall-am: uninstall-binPROGRAMS uninstall-info-am pdf pdf-am ps ps-am tags uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-info-am - $(top_builddir)/src/server/libcsql.la $(top_builddir)/src/adapter/libcsqlodbcadapter.la + $(top_builddir)/src/storage/libcsql.la $(top_builddir)/src/adapter/libcsqlodbcadapter.la # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: -- 2.11.4.GIT