From: amayank Date: Wed, 6 Mar 2013 20:54:55 +0000 (-0800) Subject: Make db_stress Not purge redundant keys on some opens X-Git-Tag: v1.5.8~9 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=3b6653b1f8ca82771e41d61be2d472399676b455;p=rocksdb.git Make db_stress Not purge redundant keys on some opens Summary: In light of the new option introduced by commit 806e26435037f5e2eb3b8c2d1e5f278a86fdb2ba where the database has an option to compact before flushing to disk, we want the stress test to test both sides of the option. Have made it to 'deterministically' and configurably change that option for reopens. Test Plan: make db_stress; ./db_stress with some differnet options Reviewers: dhruba, vamsi Reviewed By: dhruba CC: leveldb, sheki Differential Revision: https://reviews.facebook.net/D9165 --- 3b6653b1f8ca82771e41d61be2d472399676b455 diff --git a/.arcconfig b/.arcconfig new file mode 100644 index 00000000..82d17715 --- /dev/null +++ b/.arcconfig @@ -0,0 +1,10 @@ +{ + "project_id" : "leveldb", + "conduit_uri" : "https://reviews.facebook.net/", + "copyright_holder" : "", + "load" : [ + "linters/src/" + ], + "lint.engine" : "FacebookFbcodeLintEngine", + "lint.engine.single.linter" : "FbcodeCppLinter" +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..d287d7e8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +build_config.mk +*.a +*.o +*.dylib* +*.so +*.so.* +*_test +*.arc +*.d +db_bench +db_stress +ldb +leveldb_server +leveldb_shell +manifest_dump +sst_dump +util/build_version.cc +db_repl_stress diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..8e80208c --- /dev/null +++ b/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2011 The LevelDB Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..5128559d --- /dev/null +++ b/Makefile @@ -0,0 +1,290 @@ +# Copyright (c) 2011 The LevelDB Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. See the AUTHORS file for names of contributors. + +# Inherit some settings from environment variables, if available +INSTALL_PATH ?= $(CURDIR) + +#----------------------------------------------- +# Uncomment exactly one of the lines labelled (A), (B), and (C) below +# to switch between compilation modes. + +# OPT ?= -DNDEBUG # (A) Production use (optimized mode) +OPT += -O2 -fno-omit-frame-pointer -momit-leaf-frame-pointer +#----------------------------------------------- + +# detect what platform we're building on +$(shell ./build_detect_platform build_config.mk) +# this file is generated by the previous line to set build flags and sources +include build_config.mk + +WARNING_FLAGS = -Wall -Werror -Wno-unused-parameter -Wno-sign-compare +CFLAGS += -g $(WARNING_FLAGS) -I. -I./include $(PLATFORM_CCFLAGS) $(OPT) +CXXFLAGS += -g $(WARNING_FLAGS) -I. -I./include $(PLATFORM_CXXFLAGS) $(OPT) + +LDFLAGS += $(PLATFORM_LDFLAGS) + +LIBOBJECTS = $(SOURCES:.cc=.o) +LIBOBJECTS += $(SOURCESCPP:.cpp=.o) +MEMENVOBJECTS = $(MEMENV_SOURCES:.cc=.o) + +TESTUTIL = ./util/testutil.o +TESTHARNESS = ./util/testharness.o $(TESTUTIL) +VALGRIND_ERROR = 2 +VALGRIND_DIR = VALGRIND_LOGS +VALGRIND_VER = /mnt/gvfs/third-party/3748fabb2c5e033009597bae1f9ef8bf4b218581/gcc-4.7.1-glibc-2.14.1/valgrind/valgrind-3.8.1/91ddd43/bin/valgrind +VALGRIND_OPTS = --error-exitcode=$(VALGRIND_ERROR) --leak-check=full + +TESTS = \ + arena_test \ + bloom_test \ + c_test \ + cache_test \ + coding_test \ + histogram_test \ + corruption_test \ + crc32c_test \ + db_test \ + dbformat_test \ + env_test \ + filename_test \ + filter_block_test \ + log_test \ + memenv_test \ + skiplist_test \ + table_test \ + block_test \ + version_edit_test \ + version_set_test \ + reduce_levels_test \ + write_batch_test \ + auto_roll_logger_test \ + filelock_test + + +TOOLS = \ + manifest_dump \ + sst_dump \ + db_stress \ + ldb \ + db_repl_stress + +PROGRAMS = db_bench $(TESTS) $(TOOLS) +BENCHMARKS = db_bench_sqlite3 db_bench_tree_db + +LIBRARY = libleveldb.a +MEMENVLIBRARY = libmemenv.a + +default: all + +# Should we build shared libraries? +ifneq ($(PLATFORM_SHARED_EXT),) + +ifneq ($(PLATFORM_SHARED_VERSIONED),true) +SHARED1 = libleveldb.$(PLATFORM_SHARED_EXT) +SHARED2 = $(SHARED1) +SHARED3 = $(SHARED1) +SHARED = $(SHARED1) +else +# Update db.h if you change these. +SHARED_MAJOR = 1 +SHARED_MINOR = 5 +SHARED1 = libleveldb.$(PLATFORM_SHARED_EXT) +SHARED2 = $(SHARED1).$(SHARED_MAJOR) +SHARED3 = $(SHARED1).$(SHARED_MAJOR).$(SHARED_MINOR) +SHARED = $(SHARED1) $(SHARED2) $(SHARED3) +$(SHARED1): $(SHARED3) + ln -fs $(SHARED3) $(SHARED1) +$(SHARED2): $(SHARED3) + ln -fs $(SHARED3) $(SHARED2) +endif + +$(SHARED3): + $(CXX) $(LDFLAGS) $(PLATFORM_SHARED_LDFLAGS)$(SHARED2) $(CXXFLAGS) $(PLATFORM_SHARED_CFLAGS) $(SOURCES) -o $(SHARED3) + +endif # PLATFORM_SHARED_EXT + +all: $(SHARED) $(LIBRARY) $(PROGRAMS) + +release: + make clean + OPT=-DNDEBUG make -j32 + +check: all $(PROGRAMS) $(TESTS) $(TOOLS) ldb_tests + for t in $(TESTS); do echo "***** Running $$t"; ./$$t || exit 1; done + +ldb_tests: all $(PROGRAMS) $(TOOLS) + python tools/ldb_test.py + +valgrind_check: all $(PROGRAMS) $(TESTS) + echo TESTS THAT HAVE VALGRIND ERRORS > $(VALGRIND_DIR)/valgrind_failed_tests; \ + echo TIMES in seconds TAKEN BY TESTS ON VALGRIND > $(VALGRIND_DIR)/valgrind_tests_times; \ + for t in $(filter-out skiplist_test,$(TESTS)); do \ + stime=`date '+%s'`; \ + $(VALGRIND_VER) $(VALGRIND_OPTS) ./$$t; \ + if [ $$? -eq $(VALGRIND_ERROR) ] ; then \ + echo $$t >> $(VALGRIND_DIR)/valgrind_failed_tests; \ + fi; \ + etime=`date '+%s'`; \ + echo $$t $$((etime - stime)) >> $(VALGRIND_DIR)/valgrind_tests_times; \ + done + +clean: + -rm -f $(PROGRAMS) $(BENCHMARKS) $(LIBRARY) $(SHARED) $(MEMENVLIBRARY) $(THRIFTSERVER) */*.o */*/*.o ios-x86/*/*.o ios-arm/*/*.o build_config.mk + -rm -rf ios-x86/* ios-arm/* + +$(LIBRARY): $(LIBOBJECTS) + rm -f $@ + $(AR) -rs $@ $(LIBOBJECTS) + + +db_bench: db/db_bench.o $(LIBOBJECTS) $(TESTUTIL) + $(CXX) db/db_bench.o $(LIBOBJECTS) $(TESTUTIL) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +db_stress: tools/db_stress.o $(LIBOBJECTS) $(TESTUTIL) + $(CXX) tools/db_stress.o $(LIBOBJECTS) $(TESTUTIL) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +db_repl_stress: tools/db_repl_stress.o $(LIBOBJECTS) $(TESTUTIL) + $(CXX) tools/db_repl_stress.o $(LIBOBJECTS) $(TESTUTIL) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +db_bench_sqlite3: doc/bench/db_bench_sqlite3.o $(LIBOBJECTS) $(TESTUTIL) + $(CXX) doc/bench/db_bench_sqlite3.o $(LIBOBJECTS) $(TESTUTIL) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) -lsqlite3 + +db_bench_tree_db: doc/bench/db_bench_tree_db.o $(LIBOBJECTS) $(TESTUTIL) + $(CXX) doc/bench/db_bench_tree_db.o $(LIBOBJECTS) $(TESTUTIL) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) -lkyotocabinet + +arena_test: util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +bloom_test: util/bloom_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) util/bloom_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +c_test: db/c_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) db/c_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +cache_test: util/cache_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) util/cache_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +coding_test: util/coding_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) util/coding_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +histogram_test: util/histogram_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) util/histogram_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o$@ $(LDFLAGS) + +corruption_test: db/corruption_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) db/corruption_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +crc32c_test: util/crc32c_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) util/crc32c_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +db_test: db/db_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) db/db_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +dbformat_test: db/dbformat_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) db/dbformat_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +env_test: util/env_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) util/env_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +filename_test: db/filename_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) db/filename_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +filter_block_test: table/filter_block_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) table/filter_block_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +log_test: db/log_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) db/log_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +table_test: table/table_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) table/table_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +block_test: table/block_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) table/block_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +skiplist_test: db/skiplist_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) db/skiplist_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +version_edit_test: db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +version_set_test: db/version_set_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) db/version_set_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +reduce_levels_test: tools/reduce_levels_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) tools/reduce_levels_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +write_batch_test: db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +$(MEMENVLIBRARY) : $(MEMENVOBJECTS) + rm -f $@ + $(AR) -rs $@ $(MEMENVOBJECTS) + +memenv_test : helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) + $(CXX) helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +leveldb_shell: tools/shell/ShellContext.o tools/shell/ShellState.o tools/shell/LeveldbShell.o tools/shell/DBClientProxy.o tools/shell/ShellContext.h tools/shell/ShellState.h tools/shell/DBClientProxy.h $(LIBOBJECTS) + $(CXX) tools/shell/ShellContext.o tools/shell/ShellState.o tools/shell/LeveldbShell.o tools/shell/DBClientProxy.o $(LIBOBJECTS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +DBClientProxy_test: tools/shell/test/DBClientProxyTest.o tools/shell/DBClientProxy.o $(LIBRARY) + $(CXX) tools/shell/test/DBClientProxyTest.o tools/shell/DBClientProxy.o $(LIBRARY) $(EXEC_LDFLAGS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +manifest_dump: tools/manifest_dump.o $(LIBOBJECTS) + $(CXX) tools/manifest_dump.o $(LIBOBJECTS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +filelock_test: util/filelock_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) util/filelock_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +auto_roll_logger_test: util/auto_roll_logger_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) util/auto_roll_logger_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +sst_dump: tools/sst_dump.o $(LIBOBJECTS) + $(CXX) tools/sst_dump.o $(LIBOBJECTS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +ldb: tools/ldb.o $(LIBOBJECTS) + $(CXX) tools/ldb.o $(LIBOBJECTS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) + +ifeq ($(PLATFORM), IOS) +# For iOS, create universal object files to be used on both the simulator and +# a device. +PLATFORMSROOT=/Applications/Xcode.app/Contents/Developer/Platforms +SIMULATORROOT=$(PLATFORMSROOT)/iPhoneSimulator.platform/Developer +DEVICEROOT=$(PLATFORMSROOT)/iPhoneOS.platform/Developer +IOSVERSION=$(shell defaults read $(PLATFORMSROOT)/iPhoneOS.platform/versionCFBundleShortVersionString) + +.cc.o: + mkdir -p ios-x86/$(dir $@) + $(SIMULATORROOT)/usr/bin/$(CXX) $(CXXFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -c $< -o ios-x86/$@ + mkdir -p ios-arm/$(dir $@) + $(DEVICEROOT)/usr/bin/$(CXX) $(CXXFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 -c $< -o ios-arm/$@ + lipo ios-x86/$@ ios-arm/$@ -create -output $@ + +.c.o: + mkdir -p ios-x86/$(dir $@) + $(SIMULATORROOT)/usr/bin/$(CC) $(CFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -c $< -o ios-x86/$@ + mkdir -p ios-arm/$(dir $@) + $(DEVICEROOT)/usr/bin/$(CC) $(CFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 -c $< -o ios-arm/$@ + lipo ios-x86/$@ ios-arm/$@ -create -output $@ + +else +.cc.o: + $(CXX) $(CXXFLAGS) $(PLATFORM_SHARED_CFLAGS) -c $< -o $@ + +.c.o: + $(CC) $(CFLAGS) $(PLATFORM_SHARED_CFLAGS) -c $< -o $@ +endif + +%.d: %.cc + $(CXX) $(CXXFLAGS) $(PLATFORM_SHARED_CFLAGS) -MM $< -o $*.d + @cp -f $*.d $*.d.tmp + @sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d + @rm -f $*.d.tmp + +DEPFILES = $(filter-out util/build_version.d,$(SOURCES:.cc=.d)) + +depend: $(DEPFILES) + +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPFILES) +endif + diff --git a/README b/README new file mode 100644 index 00000000..783332c4 --- /dev/null +++ b/README @@ -0,0 +1,61 @@ +rocksdb: A persistent key-value store for flash storage +Authors: The Facebook Database Engineering Team + +This code is a library that forms the core building block for a fast +key value server, especially suited for storing data on flash drives. +It has an Log-Stuctured-Merge-Database (LSM) design with flexible tradeoffs +between Write-Amplification-Factor(WAF), Read-Amplification-Factor (RAF) +and Space-Amplification-Factor(SAF). It has multi-threaded compactions, +making it specially suitable for storing multiple terabytes of data in a +single database. + +The core of this code has been derived from open-source leveldb. + +The code under this directory implements a system for maintaining a +persistent key/value store. + +See doc/index.html for more explanation. +See doc/impl.html for a brief overview of the implementation. + +The public interface is in include/*.h. Callers should not include or +rely on the details of any other header files in this package. Those +internal APIs may be changed without warning. + +Guide to header files: + +include/db.h + Main interface to the DB: Start here + +include/options.h + Control over the behavior of an entire database, and also + control over the behavior of individual reads and writes. + +include/comparator.h + Abstraction for user-specified comparison function. If you want + just bytewise comparison of keys, you can use the default comparator, + but clients can write their own comparator implementations if they + want custom ordering (e.g. to handle different character + encodings, etc.) + +include/iterator.h + Interface for iterating over data. You can get an iterator + from a DB object. + +include/write_batch.h + Interface for atomically applying multiple updates to a database. + +include/slice.h + A simple module for maintaining a pointer and a length into some + other byte array. + +include/status.h + Status is returned from many of the public interfaces and is used + to report success and various kinds of errors. + +include/env.h + Abstraction of the OS environment. A posix implementation of + this interface is in util/env_posix.cc + +include/table.h +include/table_builder.h + Lower-level modules that most clients probably won't use directly diff --git a/README.fb b/README.fb new file mode 100644 index 00000000..1f0d71cf --- /dev/null +++ b/README.fb @@ -0,0 +1,3 @@ +* Detailed instructions on how to compile using fbcode and jemalloc + +* Latest release is 1.5.7.fb diff --git a/VALGRIND_LOGS/README b/VALGRIND_LOGS/README new file mode 100644 index 00000000..57d7cb96 --- /dev/null +++ b/VALGRIND_LOGS/README @@ -0,0 +1,4 @@ +This directory stores the tests that failed valgrind and the times associated +with the failed runs. +"make valgrind_check" can be invoked to call valgrind on the rocksdb tests and +generate files in this directory diff --git a/build_detect_platform b/build_detect_platform new file mode 100755 index 00000000..7318f947 --- /dev/null +++ b/build_detect_platform @@ -0,0 +1,252 @@ +#!/bin/sh +# +# Detects OS we're compiling on and outputs a file specified by the first +# argument, which in turn gets read while processing Makefile. +# +# The output will set the following variables: +# CC C Compiler path +# CXX C++ Compiler path +# PLATFORM_LDFLAGS Linker flags +# PLATFORM_SHARED_EXT Extension for shared libraries +# PLATFORM_SHARED_LDFLAGS Flags for building shared library +# PLATFORM_SHARED_CFLAGS Flags for compiling objects for shared library +# PLATFORM_CCFLAGS C compiler flags +# PLATFORM_CXXFLAGS C++ compiler flags. Will contain: +# PLATFORM_SHARED_VERSIONED Set to 'true' if platform supports versioned +# shared libraries, empty otherwise. +# +# The PLATFORM_CCFLAGS and PLATFORM_CXXFLAGS might include the following: +# +# -DLEVELDB_PLATFORM_POSIX if cstdatomic is present +# -DLEVELDB_PLATFORM_NOATOMIC if it is not +# -DSNAPPY if the Snappy library is present +# + +OUTPUT=$1 +if test -z "$OUTPUT"; then + echo "usage: $0 " >&2 + exit 1 +fi + +# Default to fbcode gcc on internal fb machines +if [ -d /mnt/gvfs/third-party -a -z "$CXX" ]; then + if [ -z "$USE_CLANG" ]; then + source fbcode.gcc471.sh + else + source fbcode.clang31.sh + fi +fi + +# Delete existing output, if it exists +rm -f $OUTPUT +touch $OUTPUT + +if test -z "$CC"; then + CC=cc +fi + +if test -z "$CXX"; then + CXX=g++ +fi + +# Detect OS +if test -z "$TARGET_OS"; then + TARGET_OS=`uname -s` +fi + +COMMON_FLAGS="${CFLAGS}" +CROSS_COMPILE= +PLATFORM_CCFLAGS= +PLATFORM_CXXFLAGS="${CXXFLAGS}" +PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS" +PLATFORM_SHARED_EXT="so" +PLATFORM_SHARED_LDFLAGS="${EXEC_LDFLAGS_SHARED} -shared -Wl,-soname -Wl," +PLATFORM_SHARED_CFLAGS="-fPIC" +PLATFORM_SHARED_VERSIONED=true + +# On GCC, we pick libc's memcmp over GCC's memcmp via -fno-builtin-memcmp +case "$TARGET_OS" in + Darwin) + PLATFORM=OS_MACOSX + COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp -DOS_MACOSX" + PLATFORM_SHARED_EXT=dylib + PLATFORM_SHARED_LDFLAGS="-dynamiclib -install_name " + PORT_FILE=port/port_posix.cc + ;; + Linux) + PLATFORM=OS_LINUX + COMMON_FLAGS="$COMMON_FLAGS -DOS_LINUX -fPIC" + if [ -z "$USE_CLANG" ]; then + COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp" + fi + PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lpthread" + PORT_FILE=port/port_posix.cc + ;; + SunOS) + PLATFORM=OS_SOLARIS + COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp -D_REENTRANT -DOS_SOLARIS" + PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lpthread -lrt" + PORT_FILE=port/port_posix.cc + ;; + FreeBSD) + PLATFORM=OS_FREEBSD + COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp -D_REENTRANT -DOS_FREEBSD" + PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lpthread" + PORT_FILE=port/port_posix.cc + ;; + NetBSD) + PLATFORM=OS_NETBSD + COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp -D_REENTRANT -DOS_NETBSD" + PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lpthread -lgcc_s" + PORT_FILE=port/port_posix.cc + ;; + OpenBSD) + PLATFORM=OS_OPENBSD + COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp -D_REENTRANT -DOS_OPENBSD" + PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -pthread" + PORT_FILE=port/port_posix.cc + ;; + DragonFly) + PLATFORM=OS_DRAGONFLYBSD + COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp -D_REENTRANT -DOS_DRAGONFLYBSD" + PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lpthread" + PORT_FILE=port/port_posix.cc + ;; + OS_ANDROID_CROSSCOMPILE) + PLATFORM=OS_ANDROID + COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp -D_REENTRANT -DOS_ANDROID -DLEVELDB_PLATFORM_POSIX" + PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS " # All pthread features are in the Android C library + PORT_FILE=port/port_posix.cc + CROSS_COMPILE=true + ;; + *) + echo "Unknown platform!" >&2 + exit 1 +esac + +./build_detect_version + +# We want to make a list of all cc files within util, db, table, and helpers +# except for the test and benchmark files. By default, find will output a list +# of all files matching either rule, so we need to append -print to make the +# prune take effect. +DIRS="util db table" +if test "$USE_THRIFT"; then + DIRS="$DIRS thrift/server_utils.cpp thrift/gen-cpp " + THRIFTSERVER=leveldb_server +fi + +if test "$USE_SCRIBE"; then + DIRS="$DIRS scribe " +fi + +set -f # temporarily disable globbing so that our patterns arent expanded +PRUNE_TEST="-name *test*.cc -prune" +PRUNE_BENCH="-name *_bench.cc -prune" +PORTABLE_FILES=`find $DIRS $PRUNE_TEST -o $PRUNE_BENCH -o -name '*.cc' -print | sort | tr "\n" " "` +PORTABLE_CPP=`find $DIRS $PRUNE_TEST -o $PRUNE_BENCH -o -name '*.cpp' -print | sort | tr "\n" " "` +set +f # re-enable globbing + +# The sources consist of the portable files, plus the platform-specific port +# file. +echo "SOURCES=$PORTABLE_FILES $PORT_FILE" >> $OUTPUT +echo "SOURCESCPP=$PORTABLE_CPP" >> $OUTPUT +echo "MEMENV_SOURCES=helpers/memenv/memenv.cc" >> $OUTPUT + +if [ "$CROSS_COMPILE" = "true" ]; then + # Cross-compiling; do not try any compilation tests. + true +else + # If -std=c++0x works, use . Otherwise use port_posix.h. + $CXX $CFLAGS -std=c++0x -x c++ - -o /dev/null 2>/dev/null < + int main() {} +EOF + if [ "$?" = 0 ]; then + COMMON_FLAGS="$COMMON_FLAGS -DLEVELDB_PLATFORM_POSIX -DLEVELDB_CSTDATOMIC_PRESENT" + PLATFORM_CXXFLAGS="-std=c++0x" + else + COMMON_FLAGS="$COMMON_FLAGS -DLEVELDB_PLATFORM_POSIX" + fi + + # Test whether Snappy library is installed + # http://code.google.com/p/snappy/ + $CXX $CFLAGS -x c++ - -o /dev/null 2>/dev/null < + int main() {} +EOF + if [ "$?" = 0 ]; then + COMMON_FLAGS="$COMMON_FLAGS -DSNAPPY" + PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS ${SNAPPY_LDFLAGS:-./snappy/libs/libsnappy.a}" + fi + + # Test whether zlib library is installed + $CXX $CFLAGS $COMMON_FLAGS -x c++ - -o /dev/null 2>/dev/null < + int main() {} +EOF + if [ "$?" = 0 ]; then + COMMON_FLAGS="$COMMON_FLAGS -DZLIB" + PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lz" + fi + + # Test whether bzip library is installed + $CXX $CFLAGS $COMMON_FLAGS -x c++ - -o /dev/null 2>/dev/null < + int main() {} +EOF + if [ "$?" = 0 ]; then + COMMON_FLAGS="$COMMON_FLAGS -DBZIP2" + PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lbz2" + fi + + # Test whether tcmalloc is available + $CXX $CFLAGS -x c++ - -o /dev/null -ltcmalloc 2>/dev/null <> $OUTPUT +echo "CXX=$CXX" >> $OUTPUT +echo "PLATFORM=$PLATFORM" >> $OUTPUT +echo "PLATFORM_LDFLAGS=$PLATFORM_LDFLAGS" >> $OUTPUT +echo "PLATFORM_CCFLAGS=$PLATFORM_CCFLAGS" >> $OUTPUT +echo "PLATFORM_CXXFLAGS=$PLATFORM_CXXFLAGS" >> $OUTPUT +echo "PLATFORM_SHARED_CFLAGS=$PLATFORM_SHARED_CFLAGS" >> $OUTPUT +echo "PLATFORM_SHARED_EXT=$PLATFORM_SHARED_EXT" >> $OUTPUT +echo "PLATFORM_SHARED_LDFLAGS=$PLATFORM_SHARED_LDFLAGS" >> $OUTPUT +echo "PLATFORM_SHARED_VERSIONED=$PLATFORM_SHARED_VERSIONED" >> $OUTPUT +echo "THRIFTSERVER=$THRIFTSERVER" >> $OUTPUT +echo "EXEC_LDFLAGS=$EXEC_LDFLAGS" >> $OUTPUT diff --git a/build_detect_version b/build_detect_version new file mode 100755 index 00000000..73dbf62a --- /dev/null +++ b/build_detect_version @@ -0,0 +1,29 @@ +#!/bin/sh +# +# Record the version of the source that we are compiling. +# We keep a record of the git revision in util/version.cc. This source file +# is then built as a regular source file as part of the compilation process. +# One can run "strings executable_filename | grep _build_" to find the version of +# the source that we used to build the executable file. +# + +# create git version file +VFILE=$(mktemp) +trap "rm $VFILE" EXIT + +# check to see if git is in the path +which git > /dev/null + +if [ "$?" = 0 ]; then + env -i git rev-parse HEAD | awk ' BEGIN {print "#include \"build_version.h\""} {print "const char * leveldb_build_git_sha = \"leveldb_build_git_sha:" $0"\";"} END {}' > ${VFILE} +else + echo "git not found"| awk ' BEGIN {print "#include \"build_version.h\""} {print "const char * leveldb_build_git_sha = \"leveldb_build_git_sha:git not found\";"} END {}' > ${VFILE} +fi + +echo "const char * leveldb_build_compile_date = __DATE__;" >> ${VFILE} +echo "const char * leveldb_build_compile_time = __TIME__;" >> ${VFILE} + +OUTFILE=util/build_version.cc +if [ ! -e $OUTFILE ] || ! cmp -s $VFILE $OUTFILE; then + cp $VFILE $OUTFILE +fi diff --git a/build_java.sh b/build_java.sh new file mode 100755 index 00000000..b0e1442f --- /dev/null +++ b/build_java.sh @@ -0,0 +1,86 @@ +#!/bin/bash -e +function print_usage { + echo "Usage: $0 [build | release | bump_version version ]" +} + +function check_env { + if [ -z $LEVELDB_HOME ] ; then + echo "Expect LEVELDB_HOME to be SET" + exit 1 + fi + if [ -z $JAVA_HOME ] ; then + export JAVA_HOME=/usr/local/jdk-6u14-64/ + echo "JAVA_HOME not set. Assuming JAVA_HOME=$JAVA_HOME" + fi + if [ -z $LEVELDBJNI_HOME ] ; then + export LEVELDBJNI_HOME=$LEVELDB_HOME/java/leveldbjni/ + echo "LEVELDBJNI_HOME not set. Assuming LEVELDBJNI_HOME=$LEVELDBJNI_HOME" + fi + if [ -z $SNAPPY_HOME ] ; then + export SNAPPY_HOME="/home/dhruba/snappy-1.0.5" + echo "SNAPPY_HOME not set. Assuming SNAPPY_HOME=$SNAPPY_HOME" + fi + if [ -z $LEVELDB_PATCH ] ; then + LEVELDB_PATCH=$LEVELDB_HOME/java/leveldbjni/db.h.patch + echo "LEVELDB_PATCH not set. Assuming LEVELDB_PATCH=$LEVELDB_PATCH" + fi +} + +function build { + cd $LEVELDB_HOME + git apply $LEVELDB_PATCH + make clean libleveldb.a + cd $LEVELDB_HOME/java/leveldb/leveldb-api + mvn clean package + cd $LEVELDBJNI_HOME + mvn clean install -P linux64 + cd $LEVELDB_HOME + git checkout $LEVELDB_HOME/include/leveldb/db.h +} + +function release { + cd $LEVELDB_HOME + git apply $LEVELDB_PATCH + make clean libleveldb.a + cd $LEVELDB_HOME/java/leveldb/leveldb-api + mvn clean package + cd $LEVELDBJNI_HOME + mvn deploy -P linux64 -DskipTests + cd $LEVELDB_HOME + git checkout $LEVELDB_HOME/include/leveldb/db.h +} + +CMD=$1 +if [ -z $CMD ]; then + print_usage + exit 1 +fi + +case "$CMD" in + build) + check_env + build + ;; + bump_version) + if [ -z $2 ] ; then + echo "bump_version requires a version.no parameter at the end" + exit 1 + fi + check_env + VERSION=$2 + pushd $LEVELDBJNI_HOME + mvn versions:set -DnewVersion="$VERSION" + popd + echo "VERSION SET TO $VERSION" + ;; + release) + check_env + pushd $LEVELDBJNI_HOME + release + popd + ;; + *) + print_usage + exit 1 + ;; +esac diff --git a/db/builder.cc b/db/builder.cc new file mode 100644 index 00000000..1de062e5 --- /dev/null +++ b/db/builder.cc @@ -0,0 +1,141 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/builder.h" + +#include "db/filename.h" +#include "db/dbformat.h" +#include "db/table_cache.h" +#include "db/version_edit.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" + +namespace leveldb { + +Status BuildTable(const std::string& dbname, + Env* env, + const Options& options, + TableCache* table_cache, + Iterator* iter, + FileMetaData* meta, + const Comparator* user_comparator, + const SequenceNumber newest_snapshot, + const SequenceNumber earliest_seqno_in_memtable) { + Status s; + meta->file_size = 0; + iter->SeekToFirst(); + + // If the sequence number of the smallest entry in the memtable is + // smaller than the most recent snapshot, then we do not trigger + // removal of duplicate/deleted keys as part of this builder. + bool purge = options.purge_redundant_kvs_while_flush; + if (earliest_seqno_in_memtable <= newest_snapshot) { + purge = false; + } + + std::string fname = TableFileName(dbname, meta->number); + if (iter->Valid()) { + unique_ptr file; + s = env->NewWritableFile(fname, &file); + if (!s.ok()) { + return s; + } + TableBuilder* builder = new TableBuilder(options, file.get(), 0); + + // the first key is the smallest key + Slice key = iter->key(); + meta->smallest.DecodeFrom(key); + + if (purge) { + ParsedInternalKey prev_ikey; + std::string prev_value; + std::string prev_key; + + // store first key-value + prev_key.assign(key.data(), key.size()); + prev_value.assign(iter->value().data(), iter->value().size()); + ParseInternalKey(Slice(prev_key), &prev_ikey); + assert(prev_ikey.sequence >= earliest_seqno_in_memtable); + + for (iter->Next(); iter->Valid(); iter->Next()) { + ParsedInternalKey this_ikey; + Slice key = iter->key(); + ParseInternalKey(key, &this_ikey); + assert(this_ikey.sequence >= earliest_seqno_in_memtable); + + if (user_comparator->Compare(prev_ikey.user_key, this_ikey.user_key)) { + // This key is different from previous key. + // Output prev key and remember current key + builder->Add(Slice(prev_key), Slice(prev_value)); + prev_key.assign(key.data(), key.size()); + prev_value.assign(iter->value().data(), iter->value().size()); + ParseInternalKey(Slice(prev_key), &prev_ikey); + } else { + // seqno within the same key are in decreasing order + assert(this_ikey.sequence < prev_ikey.sequence); + // This key is an earlier version of the same key in prev_key. + // Skip current key. + } + } + // output last key + builder->Add(Slice(prev_key), Slice(prev_value)); + meta->largest.DecodeFrom(Slice(prev_key)); + + } else { + for (; iter->Valid(); iter->Next()) { + Slice key = iter->key(); + meta->largest.DecodeFrom(key); + builder->Add(key, iter->value()); + } + } + + // Finish and check for builder errors + if (s.ok()) { + s = builder->Finish(); + if (s.ok()) { + meta->file_size = builder->FileSize(); + assert(meta->file_size > 0); + } + } else { + builder->Abandon(); + } + delete builder; + + // Finish and check for file errors + if (s.ok() && !options.disableDataSync) { + if (options.use_fsync) { + s = file->Fsync(); + } else { + s = file->Sync(); + } + } + if (s.ok()) { + s = file->Close(); + } + + if (s.ok()) { + // Verify that the table is usable + Iterator* it = table_cache->NewIterator(ReadOptions(), + meta->number, + meta->file_size); + s = it->status(); + delete it; + } + } + + // Check for input iterator errors + if (!iter->status().ok()) { + s = iter->status(); + } + + if (s.ok() && meta->file_size > 0) { + // Keep it + } else { + env->DeleteFile(fname); + } + return s; +} + +} // namespace leveldb diff --git a/db/builder.h b/db/builder.h new file mode 100644 index 00000000..e4abc7ea --- /dev/null +++ b/db/builder.h @@ -0,0 +1,39 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_BUILDER_H_ +#define STORAGE_LEVELDB_DB_BUILDER_H_ + +#include "leveldb/comparator.h" +#include "leveldb/status.h" +#include "leveldb/types.h" + +namespace leveldb { + +struct Options; +struct FileMetaData; + +class Env; +class Iterator; +class TableCache; +class VersionEdit; + +// Build a Table file from the contents of *iter. The generated file +// will be named according to meta->number. On success, the rest of +// *meta will be filled with metadata about the generated table. +// If no data is present in *iter, meta->file_size will be set to +// zero, and no Table file will be produced. +extern Status BuildTable(const std::string& dbname, + Env* env, + const Options& options, + TableCache* table_cache, + Iterator* iter, + FileMetaData* meta, + const Comparator* user_comparator, + const SequenceNumber newest_snapshot, + const SequenceNumber earliest_seqno_in_memtable); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_BUILDER_H_ diff --git a/db/c.cc b/db/c.cc new file mode 100644 index 00000000..7614e7ed --- /dev/null +++ b/db/c.cc @@ -0,0 +1,681 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/c.h" + +#include +#include +#include "leveldb/cache.h" +#include "leveldb/comparator.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/filter_policy.h" +#include "leveldb/iterator.h" +#include "leveldb/options.h" +#include "leveldb/status.h" +#include "leveldb/write_batch.h" + +using leveldb::Cache; +using leveldb::Comparator; +using leveldb::CompressionType; +using leveldb::DB; +using leveldb::Env; +using leveldb::FileLock; +using leveldb::FilterPolicy; +using leveldb::Iterator; +using leveldb::Logger; +using leveldb::NewBloomFilterPolicy; +using leveldb::NewLRUCache; +using leveldb::Options; +using leveldb::RandomAccessFile; +using leveldb::Range; +using leveldb::ReadOptions; +using leveldb::SequentialFile; +using leveldb::Slice; +using leveldb::Snapshot; +using leveldb::Status; +using leveldb::WritableFile; +using leveldb::WriteBatch; +using leveldb::WriteOptions; + +using std::shared_ptr; + +extern "C" { + +struct leveldb_t { DB* rep; }; +struct leveldb_iterator_t { Iterator* rep; }; +struct leveldb_writebatch_t { WriteBatch rep; }; +struct leveldb_snapshot_t { const Snapshot* rep; }; +struct leveldb_readoptions_t { ReadOptions rep; }; +struct leveldb_writeoptions_t { WriteOptions rep; }; +struct leveldb_options_t { Options rep; }; +struct leveldb_seqfile_t { SequentialFile* rep; }; +struct leveldb_randomfile_t { RandomAccessFile* rep; }; +struct leveldb_writablefile_t { WritableFile* rep; }; +struct leveldb_filelock_t { FileLock* rep; }; +struct leveldb_logger_t { shared_ptr rep; }; +struct leveldb_cache_t { shared_ptr rep; }; + +struct leveldb_comparator_t : public Comparator { + void* state_; + void (*destructor_)(void*); + int (*compare_)( + void*, + const char* a, size_t alen, + const char* b, size_t blen); + const char* (*name_)(void*); + + virtual ~leveldb_comparator_t() { + (*destructor_)(state_); + } + + virtual int Compare(const Slice& a, const Slice& b) const { + return (*compare_)(state_, a.data(), a.size(), b.data(), b.size()); + } + + virtual const char* Name() const { + return (*name_)(state_); + } + + // No-ops since the C binding does not support key shortening methods. + virtual void FindShortestSeparator(std::string*, const Slice&) const { } + virtual void FindShortSuccessor(std::string* key) const { } +}; + +struct leveldb_filterpolicy_t : public FilterPolicy { + void* state_; + void (*destructor_)(void*); + const char* (*name_)(void*); + char* (*create_)( + void*, + const char* const* key_array, const size_t* key_length_array, + int num_keys, + size_t* filter_length); + unsigned char (*key_match_)( + void*, + const char* key, size_t length, + const char* filter, size_t filter_length); + + virtual ~leveldb_filterpolicy_t() { + (*destructor_)(state_); + } + + virtual const char* Name() const { + return (*name_)(state_); + } + + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const { + std::vector key_pointers(n); + std::vector key_sizes(n); + for (int i = 0; i < n; i++) { + key_pointers[i] = keys[i].data(); + key_sizes[i] = keys[i].size(); + } + size_t len; + char* filter = (*create_)(state_, &key_pointers[0], &key_sizes[0], n, &len); + dst->append(filter, len); + free(filter); + } + + virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const { + return (*key_match_)(state_, key.data(), key.size(), + filter.data(), filter.size()); + } +}; + +struct leveldb_env_t { + Env* rep; + bool is_default; +}; + +static bool SaveError(char** errptr, const Status& s) { + assert(errptr != NULL); + if (s.ok()) { + return false; + } else if (*errptr == NULL) { + *errptr = strdup(s.ToString().c_str()); + } else { + // TODO(sanjay): Merge with existing error? + free(*errptr); + *errptr = strdup(s.ToString().c_str()); + } + return true; +} + +static char* CopyString(const std::string& str) { + char* result = reinterpret_cast(malloc(sizeof(char) * str.size())); + memcpy(result, str.data(), sizeof(char) * str.size()); + return result; +} + +leveldb_t* leveldb_open( + const leveldb_options_t* options, + const char* name, + char** errptr) { + DB* db; + if (SaveError(errptr, DB::Open(options->rep, std::string(name), &db))) { + return NULL; + } + leveldb_t* result = new leveldb_t; + result->rep = db; + return result; +} + +void leveldb_close(leveldb_t* db) { + delete db->rep; + delete db; +} + +void leveldb_put( + leveldb_t* db, + const leveldb_writeoptions_t* options, + const char* key, size_t keylen, + const char* val, size_t vallen, + char** errptr) { + SaveError(errptr, + db->rep->Put(options->rep, Slice(key, keylen), Slice(val, vallen))); +} + +void leveldb_delete( + leveldb_t* db, + const leveldb_writeoptions_t* options, + const char* key, size_t keylen, + char** errptr) { + SaveError(errptr, db->rep->Delete(options->rep, Slice(key, keylen))); +} + + +void leveldb_write( + leveldb_t* db, + const leveldb_writeoptions_t* options, + leveldb_writebatch_t* batch, + char** errptr) { + SaveError(errptr, db->rep->Write(options->rep, &batch->rep)); +} + +char* leveldb_get( + leveldb_t* db, + const leveldb_readoptions_t* options, + const char* key, size_t keylen, + size_t* vallen, + char** errptr) { + char* result = NULL; + std::string tmp; + Status s = db->rep->Get(options->rep, Slice(key, keylen), &tmp); + if (s.ok()) { + *vallen = tmp.size(); + result = CopyString(tmp); + } else { + *vallen = 0; + if (!s.IsNotFound()) { + SaveError(errptr, s); + } + } + return result; +} + +leveldb_iterator_t* leveldb_create_iterator( + leveldb_t* db, + const leveldb_readoptions_t* options) { + leveldb_iterator_t* result = new leveldb_iterator_t; + result->rep = db->rep->NewIterator(options->rep); + return result; +} + +const leveldb_snapshot_t* leveldb_create_snapshot( + leveldb_t* db) { + leveldb_snapshot_t* result = new leveldb_snapshot_t; + result->rep = db->rep->GetSnapshot(); + return result; +} + +void leveldb_release_snapshot( + leveldb_t* db, + const leveldb_snapshot_t* snapshot) { + db->rep->ReleaseSnapshot(snapshot->rep); + delete snapshot; +} + +char* leveldb_property_value( + leveldb_t* db, + const char* propname) { + std::string tmp; + if (db->rep->GetProperty(Slice(propname), &tmp)) { + // We use strdup() since we expect human readable output. + return strdup(tmp.c_str()); + } else { + return NULL; + } +} + +void leveldb_approximate_sizes( + leveldb_t* db, + int num_ranges, + const char* const* range_start_key, const size_t* range_start_key_len, + const char* const* range_limit_key, const size_t* range_limit_key_len, + uint64_t* sizes) { + Range* ranges = new Range[num_ranges]; + for (int i = 0; i < num_ranges; i++) { + ranges[i].start = Slice(range_start_key[i], range_start_key_len[i]); + ranges[i].limit = Slice(range_limit_key[i], range_limit_key_len[i]); + } + db->rep->GetApproximateSizes(ranges, num_ranges, sizes); + delete[] ranges; +} + +void leveldb_compact_range( + leveldb_t* db, + const char* start_key, size_t start_key_len, + const char* limit_key, size_t limit_key_len) { + Slice a, b; + db->rep->CompactRange( + // Pass NULL Slice if corresponding "const char*" is NULL + (start_key ? (a = Slice(start_key, start_key_len), &a) : NULL), + (limit_key ? (b = Slice(limit_key, limit_key_len), &b) : NULL)); +} + +void leveldb_destroy_db( + const leveldb_options_t* options, + const char* name, + char** errptr) { + SaveError(errptr, DestroyDB(name, options->rep)); +} + +void leveldb_repair_db( + const leveldb_options_t* options, + const char* name, + char** errptr) { + SaveError(errptr, RepairDB(name, options->rep)); +} + +void leveldb_iter_destroy(leveldb_iterator_t* iter) { + delete iter->rep; + delete iter; +} + +unsigned char leveldb_iter_valid(const leveldb_iterator_t* iter) { + return iter->rep->Valid(); +} + +void leveldb_iter_seek_to_first(leveldb_iterator_t* iter) { + iter->rep->SeekToFirst(); +} + +void leveldb_iter_seek_to_last(leveldb_iterator_t* iter) { + iter->rep->SeekToLast(); +} + +void leveldb_iter_seek(leveldb_iterator_t* iter, const char* k, size_t klen) { + iter->rep->Seek(Slice(k, klen)); +} + +void leveldb_iter_next(leveldb_iterator_t* iter) { + iter->rep->Next(); +} + +void leveldb_iter_prev(leveldb_iterator_t* iter) { + iter->rep->Prev(); +} + +const char* leveldb_iter_key(const leveldb_iterator_t* iter, size_t* klen) { + Slice s = iter->rep->key(); + *klen = s.size(); + return s.data(); +} + +const char* leveldb_iter_value(const leveldb_iterator_t* iter, size_t* vlen) { + Slice s = iter->rep->value(); + *vlen = s.size(); + return s.data(); +} + +void leveldb_iter_get_error(const leveldb_iterator_t* iter, char** errptr) { + SaveError(errptr, iter->rep->status()); +} + +leveldb_writebatch_t* leveldb_writebatch_create() { + return new leveldb_writebatch_t; +} + +void leveldb_writebatch_destroy(leveldb_writebatch_t* b) { + delete b; +} + +void leveldb_writebatch_clear(leveldb_writebatch_t* b) { + b->rep.Clear(); +} + +void leveldb_writebatch_put( + leveldb_writebatch_t* b, + const char* key, size_t klen, + const char* val, size_t vlen) { + b->rep.Put(Slice(key, klen), Slice(val, vlen)); +} + +void leveldb_writebatch_delete( + leveldb_writebatch_t* b, + const char* key, size_t klen) { + b->rep.Delete(Slice(key, klen)); +} + +void leveldb_writebatch_iterate( + leveldb_writebatch_t* b, + void* state, + void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen), + void (*deleted)(void*, const char* k, size_t klen)) { + class H : public WriteBatch::Handler { + public: + void* state_; + void (*put_)(void*, const char* k, size_t klen, const char* v, size_t vlen); + void (*deleted_)(void*, const char* k, size_t klen); + virtual void Put(const Slice& key, const Slice& value) { + (*put_)(state_, key.data(), key.size(), value.data(), value.size()); + } + virtual void Delete(const Slice& key) { + (*deleted_)(state_, key.data(), key.size()); + } + }; + H handler; + handler.state_ = state; + handler.put_ = put; + handler.deleted_ = deleted; + b->rep.Iterate(&handler); +} + +leveldb_options_t* leveldb_options_create() { + return new leveldb_options_t; +} + +void leveldb_options_destroy(leveldb_options_t* options) { + delete options; +} + +void leveldb_options_set_comparator( + leveldb_options_t* opt, + leveldb_comparator_t* cmp) { + opt->rep.comparator = cmp; +} + +void leveldb_options_set_filter_policy( + leveldb_options_t* opt, + leveldb_filterpolicy_t* policy) { + opt->rep.filter_policy = policy; +} + +void leveldb_options_set_create_if_missing( + leveldb_options_t* opt, unsigned char v) { + opt->rep.create_if_missing = v; +} + +void leveldb_options_set_error_if_exists( + leveldb_options_t* opt, unsigned char v) { + opt->rep.error_if_exists = v; +} + +void leveldb_options_set_paranoid_checks( + leveldb_options_t* opt, unsigned char v) { + opt->rep.paranoid_checks = v; +} + +void leveldb_options_set_env(leveldb_options_t* opt, leveldb_env_t* env) { + opt->rep.env = (env ? env->rep : NULL); +} + +void leveldb_options_set_info_log(leveldb_options_t* opt, leveldb_logger_t* l) { + if (l) { + opt->rep.info_log = l->rep; + } +} + +void leveldb_options_set_write_buffer_size(leveldb_options_t* opt, size_t s) { + opt->rep.write_buffer_size = s; +} + +void leveldb_options_set_max_open_files(leveldb_options_t* opt, int n) { + opt->rep.max_open_files = n; +} + +void leveldb_options_set_cache(leveldb_options_t* opt, leveldb_cache_t* c) { + if (c) { + opt->rep.block_cache = c->rep; + } +} + +void leveldb_options_set_block_size(leveldb_options_t* opt, size_t s) { + opt->rep.block_size = s; +} + +void leveldb_options_set_block_restart_interval(leveldb_options_t* opt, int n) { + opt->rep.block_restart_interval = n; +} + +void leveldb_options_set_target_file_size_base( + leveldb_options_t* opt, uint64_t n) { + opt->rep.target_file_size_base = n; +} + +void leveldb_options_set_target_file_size_multiplier( + leveldb_options_t* opt, int n) { + opt->rep.target_file_size_multiplier = n; +} + +void leveldb_options_set_max_bytes_for_level_base( + leveldb_options_t* opt, uint64_t n) { + opt->rep.max_bytes_for_level_base = n; +} + +void leveldb_options_set_max_bytes_for_level_multiplier( + leveldb_options_t* opt, int n) { + opt->rep.max_bytes_for_level_multiplier = n; +} + +void leveldb_options_set_expanded_compaction_factor( + leveldb_options_t* opt, int n) { + opt->rep.expanded_compaction_factor = n; +} + +void leveldb_options_set_max_grandparent_overlap_factor( + leveldb_options_t* opt, int n) { + opt->rep.max_grandparent_overlap_factor = n; +} + +void leveldb_options_set_num_levels(leveldb_options_t* opt, int n) { + opt->rep.num_levels = n; +} + +void leveldb_options_set_level0_file_num_compaction_trigger( + leveldb_options_t* opt, int n) { + opt->rep.level0_file_num_compaction_trigger = n; +} + +void leveldb_options_set_level0_slowdown_writes_trigger( + leveldb_options_t* opt, int n) { + opt->rep.level0_slowdown_writes_trigger = n; +} + +void leveldb_options_set_level0_stop_writes_trigger( + leveldb_options_t* opt, int n) { + opt->rep.level0_stop_writes_trigger = n; +} + +void leveldb_options_set_max_mem_compaction_level( + leveldb_options_t* opt, int n) { + opt->rep.max_mem_compaction_level = n; +} + +void leveldb_options_set_compression(leveldb_options_t* opt, int t) { + opt->rep.compression = static_cast(t); +} + +void leveldb_options_set_compression_per_level(leveldb_options_t* opt, + int* level_values, + size_t num_levels) { + opt->rep.compression_per_level.resize(num_levels); + for (size_t i = 0; i < num_levels; ++i) { + opt->rep.compression_per_level[i] = + static_cast(level_values[i]); + } +} + +void leveldb_options_set_compression_options( + leveldb_options_t* opt, int w_bits, int level, int strategy) { + opt->rep.compression_opts.window_bits = w_bits; + opt->rep.compression_opts.level = level; + opt->rep.compression_opts.strategy = strategy; +} + +void leveldb_options_set_disable_data_sync( + leveldb_options_t* opt, bool disable_data_sync) { + opt->rep.disableDataSync = disable_data_sync; +} + +void leveldb_options_set_use_fsync( + leveldb_options_t* opt, bool use_fsync) { + opt->rep.use_fsync = use_fsync; +} + +void leveldb_options_set_db_stats_log_interval( + leveldb_options_t* opt, int db_stats_log_interval) { + opt->rep.db_stats_log_interval = db_stats_log_interval; +} + +void leveldb_options_set_db_log_dir( + leveldb_options_t* opt, const char* db_log_dir) { + opt->rep.db_log_dir = db_log_dir; +} + +void leveldb_options_set_WAL_ttl_seconds(leveldb_options_t* opt, uint64_t ttl) { + opt->rep.WAL_ttl_seconds = ttl; +} + +leveldb_comparator_t* leveldb_comparator_create( + void* state, + void (*destructor)(void*), + int (*compare)( + void*, + const char* a, size_t alen, + const char* b, size_t blen), + const char* (*name)(void*)) { + leveldb_comparator_t* result = new leveldb_comparator_t; + result->state_ = state; + result->destructor_ = destructor; + result->compare_ = compare; + result->name_ = name; + return result; +} + +void leveldb_comparator_destroy(leveldb_comparator_t* cmp) { + delete cmp; +} + +leveldb_filterpolicy_t* leveldb_filterpolicy_create( + void* state, + void (*destructor)(void*), + char* (*create_filter)( + void*, + const char* const* key_array, const size_t* key_length_array, + int num_keys, + size_t* filter_length), + unsigned char (*key_may_match)( + void*, + const char* key, size_t length, + const char* filter, size_t filter_length), + const char* (*name)(void*)) { + leveldb_filterpolicy_t* result = new leveldb_filterpolicy_t; + result->state_ = state; + result->destructor_ = destructor; + result->create_ = create_filter; + result->key_match_ = key_may_match; + result->name_ = name; + return result; +} + +void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t* filter) { + delete filter; +} + +leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom(int bits_per_key) { + // Make a leveldb_filterpolicy_t, but override all of its methods so + // they delegate to a NewBloomFilterPolicy() instead of user + // supplied C functions. + struct Wrapper : public leveldb_filterpolicy_t { + const FilterPolicy* rep_; + ~Wrapper() { delete rep_; } + const char* Name() const { return rep_->Name(); } + void CreateFilter(const Slice* keys, int n, std::string* dst) const { + return rep_->CreateFilter(keys, n, dst); + } + bool KeyMayMatch(const Slice& key, const Slice& filter) const { + return rep_->KeyMayMatch(key, filter); + } + static void DoNothing(void*) { } + }; + Wrapper* wrapper = new Wrapper; + wrapper->rep_ = NewBloomFilterPolicy(bits_per_key); + wrapper->state_ = NULL; + wrapper->destructor_ = &Wrapper::DoNothing; + return wrapper; +} + +leveldb_readoptions_t* leveldb_readoptions_create() { + return new leveldb_readoptions_t; +} + +void leveldb_readoptions_destroy(leveldb_readoptions_t* opt) { + delete opt; +} + +void leveldb_readoptions_set_verify_checksums( + leveldb_readoptions_t* opt, + unsigned char v) { + opt->rep.verify_checksums = v; +} + +void leveldb_readoptions_set_fill_cache( + leveldb_readoptions_t* opt, unsigned char v) { + opt->rep.fill_cache = v; +} + +void leveldb_readoptions_set_snapshot( + leveldb_readoptions_t* opt, + const leveldb_snapshot_t* snap) { + opt->rep.snapshot = (snap ? snap->rep : NULL); +} + +leveldb_writeoptions_t* leveldb_writeoptions_create() { + return new leveldb_writeoptions_t; +} + +void leveldb_writeoptions_destroy(leveldb_writeoptions_t* opt) { + delete opt; +} + +void leveldb_writeoptions_set_sync( + leveldb_writeoptions_t* opt, unsigned char v) { + opt->rep.sync = v; +} + +leveldb_cache_t* leveldb_cache_create_lru(size_t capacity) { + leveldb_cache_t* c = new leveldb_cache_t; + c->rep = NewLRUCache(capacity); + return c; +} + +void leveldb_cache_destroy(leveldb_cache_t* cache) { + delete cache; +} + +leveldb_env_t* leveldb_create_default_env() { + leveldb_env_t* result = new leveldb_env_t; + result->rep = Env::Default(); + result->is_default = true; + return result; +} + +void leveldb_env_destroy(leveldb_env_t* env) { + if (!env->is_default) delete env->rep; + delete env; +} + +} // end extern "C" diff --git a/db/c_test.c b/db/c_test.c new file mode 100644 index 00000000..1d71b650 --- /dev/null +++ b/db/c_test.c @@ -0,0 +1,390 @@ +/* Copyright (c) 2011 The LevelDB Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. See the AUTHORS file for names of contributors. */ + +#include "leveldb/c.h" + +#include +#include +#include +#include +#include +#include + +const char* phase = ""; +static char dbname[200]; + +static void StartPhase(const char* name) { + fprintf(stderr, "=== Test %s\n", name); + phase = name; +} + +static const char* GetTempDir(void) { + const char* ret = getenv("TEST_TMPDIR"); + if (ret == NULL || ret[0] == '\0') + ret = "/tmp"; + return ret; +} + +#define CheckNoError(err) \ + if ((err) != NULL) { \ + fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, (err)); \ + abort(); \ + } + +#define CheckCondition(cond) \ + if (!(cond)) { \ + fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, #cond); \ + abort(); \ + } + +static void CheckEqual(const char* expected, const char* v, size_t n) { + if (expected == NULL && v == NULL) { + // ok + } else if (expected != NULL && v != NULL && n == strlen(expected) && + memcmp(expected, v, n) == 0) { + // ok + return; + } else { + fprintf(stderr, "%s: expected '%s', got '%s'\n", + phase, + (expected ? expected : "(null)"), + (v ? v : "(null")); + abort(); + } +} + +static void Free(char** ptr) { + if (*ptr) { + free(*ptr); + *ptr = NULL; + } +} + +static void CheckGet( + leveldb_t* db, + const leveldb_readoptions_t* options, + const char* key, + const char* expected) { + char* err = NULL; + size_t val_len; + char* val; + val = leveldb_get(db, options, key, strlen(key), &val_len, &err); + CheckNoError(err); + CheckEqual(expected, val, val_len); + Free(&val); +} + +static void CheckIter(leveldb_iterator_t* iter, + const char* key, const char* val) { + size_t len; + const char* str; + str = leveldb_iter_key(iter, &len); + CheckEqual(key, str, len); + str = leveldb_iter_value(iter, &len); + CheckEqual(val, str, len); +} + +// Callback from leveldb_writebatch_iterate() +static void CheckPut(void* ptr, + const char* k, size_t klen, + const char* v, size_t vlen) { + int* state = (int*) ptr; + CheckCondition(*state < 2); + switch (*state) { + case 0: + CheckEqual("bar", k, klen); + CheckEqual("b", v, vlen); + break; + case 1: + CheckEqual("box", k, klen); + CheckEqual("c", v, vlen); + break; + } + (*state)++; +} + +// Callback from leveldb_writebatch_iterate() +static void CheckDel(void* ptr, const char* k, size_t klen) { + int* state = (int*) ptr; + CheckCondition(*state == 2); + CheckEqual("bar", k, klen); + (*state)++; +} + +static void CmpDestroy(void* arg) { } + +static int CmpCompare(void* arg, const char* a, size_t alen, + const char* b, size_t blen) { + int n = (alen < blen) ? alen : blen; + int r = memcmp(a, b, n); + if (r == 0) { + if (alen < blen) r = -1; + else if (alen > blen) r = +1; + } + return r; +} + +static const char* CmpName(void* arg) { + return "foo"; +} + +// Custom filter policy +static unsigned char fake_filter_result = 1; +static void FilterDestroy(void* arg) { } +static const char* FilterName(void* arg) { + return "TestFilter"; +} +static char* FilterCreate( + void* arg, + const char* const* key_array, const size_t* key_length_array, + int num_keys, + size_t* filter_length) { + *filter_length = 4; + char* result = malloc(4); + memcpy(result, "fake", 4); + return result; +} +unsigned char FilterKeyMatch( + void* arg, + const char* key, size_t length, + const char* filter, size_t filter_length) { + CheckCondition(filter_length == 4); + CheckCondition(memcmp(filter, "fake", 4) == 0); + return fake_filter_result; +} + +int main(int argc, char** argv) { + leveldb_t* db; + leveldb_comparator_t* cmp; + leveldb_cache_t* cache; + leveldb_env_t* env; + leveldb_options_t* options; + leveldb_readoptions_t* roptions; + leveldb_writeoptions_t* woptions; + char* err = NULL; + int run = -1; + + snprintf(dbname, sizeof(dbname), + "%s/leveldb_c_test-%d", + GetTempDir(), + ((int) geteuid())); + + StartPhase("create_objects"); + cmp = leveldb_comparator_create(NULL, CmpDestroy, CmpCompare, CmpName); + env = leveldb_create_default_env(); + cache = leveldb_cache_create_lru(100000); + + options = leveldb_options_create(); + leveldb_options_set_comparator(options, cmp); + leveldb_options_set_error_if_exists(options, 1); + leveldb_options_set_cache(options, cache); + leveldb_options_set_env(options, env); + leveldb_options_set_info_log(options, NULL); + leveldb_options_set_write_buffer_size(options, 100000); + leveldb_options_set_paranoid_checks(options, 1); + leveldb_options_set_max_open_files(options, 10); + leveldb_options_set_block_size(options, 1024); + leveldb_options_set_block_restart_interval(options, 8); + leveldb_options_set_compression(options, leveldb_no_compression); + leveldb_options_set_compression_options(options, -14, -1, 0); + int compression_levels[] = {leveldb_no_compression, leveldb_no_compression, + leveldb_no_compression, leveldb_no_compression}; + leveldb_options_set_compression_per_level(options, compression_levels, 4); + + roptions = leveldb_readoptions_create(); + leveldb_readoptions_set_verify_checksums(roptions, 1); + leveldb_readoptions_set_fill_cache(roptions, 0); + + woptions = leveldb_writeoptions_create(); + leveldb_writeoptions_set_sync(woptions, 1); + + StartPhase("destroy"); + leveldb_destroy_db(options, dbname, &err); + Free(&err); + + StartPhase("open_error"); + db = leveldb_open(options, dbname, &err); + CheckCondition(err != NULL); + Free(&err); + + StartPhase("open"); + leveldb_options_set_create_if_missing(options, 1); + db = leveldb_open(options, dbname, &err); + CheckNoError(err); + CheckGet(db, roptions, "foo", NULL); + + StartPhase("put"); + leveldb_put(db, woptions, "foo", 3, "hello", 5, &err); + CheckNoError(err); + CheckGet(db, roptions, "foo", "hello"); + + StartPhase("compactall"); + leveldb_compact_range(db, NULL, 0, NULL, 0); + CheckGet(db, roptions, "foo", "hello"); + + StartPhase("compactrange"); + leveldb_compact_range(db, "a", 1, "z", 1); + CheckGet(db, roptions, "foo", "hello"); + + StartPhase("writebatch"); + { + leveldb_writebatch_t* wb = leveldb_writebatch_create(); + leveldb_writebatch_put(wb, "foo", 3, "a", 1); + leveldb_writebatch_clear(wb); + leveldb_writebatch_put(wb, "bar", 3, "b", 1); + leveldb_writebatch_put(wb, "box", 3, "c", 1); + leveldb_writebatch_delete(wb, "bar", 3); + leveldb_write(db, woptions, wb, &err); + CheckNoError(err); + CheckGet(db, roptions, "foo", "hello"); + CheckGet(db, roptions, "bar", NULL); + CheckGet(db, roptions, "box", "c"); + int pos = 0; + leveldb_writebatch_iterate(wb, &pos, CheckPut, CheckDel); + CheckCondition(pos == 3); + leveldb_writebatch_destroy(wb); + } + + StartPhase("iter"); + { + leveldb_iterator_t* iter = leveldb_create_iterator(db, roptions); + CheckCondition(!leveldb_iter_valid(iter)); + leveldb_iter_seek_to_first(iter); + CheckCondition(leveldb_iter_valid(iter)); + CheckIter(iter, "box", "c"); + leveldb_iter_next(iter); + CheckIter(iter, "foo", "hello"); + leveldb_iter_prev(iter); + CheckIter(iter, "box", "c"); + leveldb_iter_prev(iter); + CheckCondition(!leveldb_iter_valid(iter)); + leveldb_iter_seek_to_last(iter); + CheckIter(iter, "foo", "hello"); + leveldb_iter_seek(iter, "b", 1); + CheckIter(iter, "box", "c"); + leveldb_iter_get_error(iter, &err); + CheckNoError(err); + leveldb_iter_destroy(iter); + } + + StartPhase("approximate_sizes"); + { + int i; + int n = 20000; + char keybuf[100]; + char valbuf[100]; + uint64_t sizes[2]; + const char* start[2] = { "a", "k00000000000000010000" }; + size_t start_len[2] = { 1, 21 }; + const char* limit[2] = { "k00000000000000010000", "z" }; + size_t limit_len[2] = { 21, 1 }; + leveldb_writeoptions_set_sync(woptions, 0); + for (i = 0; i < n; i++) { + snprintf(keybuf, sizeof(keybuf), "k%020d", i); + snprintf(valbuf, sizeof(valbuf), "v%020d", i); + leveldb_put(db, woptions, keybuf, strlen(keybuf), valbuf, strlen(valbuf), + &err); + CheckNoError(err); + } + leveldb_approximate_sizes(db, 2, start, start_len, limit, limit_len, sizes); + CheckCondition(sizes[0] > 0); + CheckCondition(sizes[1] > 0); + } + + StartPhase("property"); + { + char* prop = leveldb_property_value(db, "nosuchprop"); + CheckCondition(prop == NULL); + prop = leveldb_property_value(db, "leveldb.stats"); + CheckCondition(prop != NULL); + Free(&prop); + } + + StartPhase("snapshot"); + { + const leveldb_snapshot_t* snap; + snap = leveldb_create_snapshot(db); + leveldb_delete(db, woptions, "foo", 3, &err); + CheckNoError(err); + leveldb_readoptions_set_snapshot(roptions, snap); + CheckGet(db, roptions, "foo", "hello"); + leveldb_readoptions_set_snapshot(roptions, NULL); + CheckGet(db, roptions, "foo", NULL); + leveldb_release_snapshot(db, snap); + } + + StartPhase("repair"); + { + // If we do not compact here, then the lazy deletion of + // files (https://reviews.facebook.net/D6123) would leave + // around deleted files and the repair process will find + // those files and put them back into the database. + leveldb_compact_range(db, NULL, 0, NULL, 0); + leveldb_close(db); + leveldb_options_set_create_if_missing(options, 0); + leveldb_options_set_error_if_exists(options, 0); + leveldb_repair_db(options, dbname, &err); + CheckNoError(err); + db = leveldb_open(options, dbname, &err); + CheckNoError(err); + CheckGet(db, roptions, "foo", NULL); + CheckGet(db, roptions, "bar", NULL); + CheckGet(db, roptions, "box", "c"); + leveldb_options_set_create_if_missing(options, 1); + leveldb_options_set_error_if_exists(options, 1); + } + + StartPhase("filter"); + for (run = 0; run < 2; run++) { + // First run uses custom filter, second run uses bloom filter + CheckNoError(err); + leveldb_filterpolicy_t* policy; + if (run == 0) { + policy = leveldb_filterpolicy_create( + NULL, FilterDestroy, FilterCreate, FilterKeyMatch, FilterName); + } else { + policy = leveldb_filterpolicy_create_bloom(10); + } + + // Create new database + leveldb_close(db); + leveldb_destroy_db(options, dbname, &err); + leveldb_options_set_filter_policy(options, policy); + db = leveldb_open(options, dbname, &err); + CheckNoError(err); + leveldb_put(db, woptions, "foo", 3, "foovalue", 8, &err); + CheckNoError(err); + leveldb_put(db, woptions, "bar", 3, "barvalue", 8, &err); + CheckNoError(err); + leveldb_compact_range(db, NULL, 0, NULL, 0); + + fake_filter_result = 1; + CheckGet(db, roptions, "foo", "foovalue"); + CheckGet(db, roptions, "bar", "barvalue"); + if (phase == 0) { + // Must not find value when custom filter returns false + fake_filter_result = 0; + CheckGet(db, roptions, "foo", NULL); + CheckGet(db, roptions, "bar", NULL); + fake_filter_result = 1; + + CheckGet(db, roptions, "foo", "foovalue"); + CheckGet(db, roptions, "bar", "barvalue"); + } + leveldb_options_set_filter_policy(options, NULL); + leveldb_filterpolicy_destroy(policy); + } + + StartPhase("cleanup"); + leveldb_close(db); + leveldb_options_destroy(options); + leveldb_readoptions_destroy(roptions); + leveldb_writeoptions_destroy(woptions); + leveldb_cache_destroy(cache); + leveldb_comparator_destroy(cmp); + leveldb_env_destroy(env); + + fprintf(stderr, "PASS\n"); + return 0; +} diff --git a/db/corruption_test.cc b/db/corruption_test.cc new file mode 100644 index 00000000..e3ee98fd --- /dev/null +++ b/db/corruption_test.cc @@ -0,0 +1,358 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/db.h" + +#include +#include +#include +#include +#include "leveldb/cache.h" +#include "leveldb/env.h" +#include "leveldb/table.h" +#include "leveldb/write_batch.h" +#include "db/db_impl.h" +#include "db/filename.h" +#include "db/log_format.h" +#include "db/version_set.h" +#include "util/logging.h" +#include "util/testharness.h" +#include "util/testutil.h" + +namespace leveldb { + +static const int kValueSize = 1000; + +class CorruptionTest { + public: + test::ErrorEnv env_; + std::string dbname_; + shared_ptr tiny_cache_; + Options options_; + DB* db_; + + CorruptionTest() { + tiny_cache_ = NewLRUCache(100); + options_.env = &env_; + dbname_ = test::TmpDir() + "/db_test"; + DestroyDB(dbname_, options_); + + db_ = nullptr; + options_.create_if_missing = true; + Reopen(); + options_.create_if_missing = false; + } + + ~CorruptionTest() { + delete db_; + DestroyDB(dbname_, Options()); + } + + Status TryReopen(Options* options = nullptr) { + delete db_; + db_ = nullptr; + Options opt = (options ? *options : options_); + opt.env = &env_; + opt.block_cache = tiny_cache_; + return DB::Open(opt, dbname_, &db_); + } + + void Reopen(Options* options = nullptr) { + ASSERT_OK(TryReopen(options)); + } + + void RepairDB() { + delete db_; + db_ = nullptr; + ASSERT_OK(::leveldb::RepairDB(dbname_, options_)); + } + + void Build(int n) { + std::string key_space, value_space; + WriteBatch batch; + for (int i = 0; i < n; i++) { + //if ((i % 100) == 0) fprintf(stderr, "@ %d of %d\n", i, n); + Slice key = Key(i, &key_space); + batch.Clear(); + batch.Put(key, Value(i, &value_space)); + ASSERT_OK(db_->Write(WriteOptions(), &batch)); + } + } + + void Check(int min_expected, int max_expected) { + unsigned int next_expected = 0; + int missed = 0; + int bad_keys = 0; + int bad_values = 0; + int correct = 0; + std::string value_space; + Iterator* iter = db_->NewIterator(ReadOptions()); + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + uint64_t key; + Slice in(iter->key()); + if (!ConsumeDecimalNumber(&in, &key) || + !in.empty() || + key < next_expected) { + bad_keys++; + continue; + } + missed += (key - next_expected); + next_expected = key + 1; + if (iter->value() != Value(key, &value_space)) { + bad_values++; + } else { + correct++; + } + } + delete iter; + + fprintf(stderr, + "expected=%d..%d; got=%d; bad_keys=%d; bad_values=%d; missed=%d\n", + min_expected, max_expected, correct, bad_keys, bad_values, missed); + ASSERT_LE(min_expected, correct); + ASSERT_GE(max_expected, correct); + } + + void Corrupt(FileType filetype, int offset, int bytes_to_corrupt) { + // Pick file to corrupt + std::vector filenames; + ASSERT_OK(env_.GetChildren(dbname_, &filenames)); + uint64_t number; + FileType type; + std::string fname; + int picked_number = -1; + for (unsigned int i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type) && + type == filetype && + int(number) > picked_number) { // Pick latest file + fname = dbname_ + "/" + filenames[i]; + picked_number = number; + } + } + ASSERT_TRUE(!fname.empty()) << filetype; + + struct stat sbuf; + if (stat(fname.c_str(), &sbuf) != 0) { + const char* msg = strerror(errno); + ASSERT_TRUE(false) << fname << ": " << msg; + } + + if (offset < 0) { + // Relative to end of file; make it absolute + if (-offset > sbuf.st_size) { + offset = 0; + } else { + offset = sbuf.st_size + offset; + } + } + if (offset > sbuf.st_size) { + offset = sbuf.st_size; + } + if (offset + bytes_to_corrupt > sbuf.st_size) { + bytes_to_corrupt = sbuf.st_size - offset; + } + + // Do it + std::string contents; + Status s = ReadFileToString(Env::Default(), fname, &contents); + ASSERT_TRUE(s.ok()) << s.ToString(); + for (int i = 0; i < bytes_to_corrupt; i++) { + contents[i + offset] ^= 0x80; + } + s = WriteStringToFile(Env::Default(), contents, fname); + ASSERT_TRUE(s.ok()) << s.ToString(); + } + + int Property(const std::string& name) { + std::string property; + int result; + if (db_->GetProperty(name, &property) && + sscanf(property.c_str(), "%d", &result) == 1) { + return result; + } else { + return -1; + } + } + + // Return the ith key + Slice Key(int i, std::string* storage) { + char buf[100]; + snprintf(buf, sizeof(buf), "%016d", i); + storage->assign(buf, strlen(buf)); + return Slice(*storage); + } + + // Return the value to associate with the specified key + Slice Value(int k, std::string* storage) { + Random r(k); + return test::RandomString(&r, kValueSize, storage); + } +}; + +TEST(CorruptionTest, Recovery) { + Build(100); + Check(100, 100); + Corrupt(kLogFile, 19, 1); // WriteBatch tag for first record + Corrupt(kLogFile, log::kBlockSize + 1000, 1); // Somewhere in second block + Reopen(); + + // The 64 records in the first two log blocks are completely lost. + Check(36, 36); +} + +TEST(CorruptionTest, RecoverWriteError) { + env_.writable_file_error_ = true; + Status s = TryReopen(); + ASSERT_TRUE(!s.ok()); +} + +TEST(CorruptionTest, NewFileErrorDuringWrite) { + // Do enough writing to force minor compaction + env_.writable_file_error_ = true; + const int num = 3 + (Options().write_buffer_size / kValueSize); + std::string value_storage; + Status s; + for (int i = 0; s.ok() && i < num; i++) { + WriteBatch batch; + batch.Put("a", Value(100, &value_storage)); + s = db_->Write(WriteOptions(), &batch); + } + ASSERT_TRUE(!s.ok()); + ASSERT_GE(env_.num_writable_file_errors_, 1); + env_.writable_file_error_ = false; + Reopen(); +} + +TEST(CorruptionTest, TableFile) { + Build(100); + DBImpl* dbi = reinterpret_cast(db_); + dbi->TEST_CompactMemTable(); + dbi->TEST_CompactRange(0, nullptr, nullptr); + dbi->TEST_CompactRange(1, nullptr, nullptr); + + Corrupt(kTableFile, 100, 1); + Check(99, 99); +} + +TEST(CorruptionTest, TableFileIndexData) { + Build(10000); // Enough to build multiple Tables + DBImpl* dbi = reinterpret_cast(db_); + dbi->TEST_CompactMemTable(); + + Corrupt(kTableFile, -2000, 500); + Reopen(); + Check(5000, 9999); +} + +TEST(CorruptionTest, MissingDescriptor) { + Build(1000); + RepairDB(); + Reopen(); + Check(1000, 1000); +} + +TEST(CorruptionTest, SequenceNumberRecovery) { + ASSERT_OK(db_->Put(WriteOptions(), "foo", "v1")); + ASSERT_OK(db_->Put(WriteOptions(), "foo", "v2")); + ASSERT_OK(db_->Put(WriteOptions(), "foo", "v3")); + ASSERT_OK(db_->Put(WriteOptions(), "foo", "v4")); + ASSERT_OK(db_->Put(WriteOptions(), "foo", "v5")); + RepairDB(); + Reopen(); + std::string v; + ASSERT_OK(db_->Get(ReadOptions(), "foo", &v)); + ASSERT_EQ("v5", v); + // Write something. If sequence number was not recovered properly, + // it will be hidden by an earlier write. + ASSERT_OK(db_->Put(WriteOptions(), "foo", "v6")); + ASSERT_OK(db_->Get(ReadOptions(), "foo", &v)); + ASSERT_EQ("v6", v); + Reopen(); + ASSERT_OK(db_->Get(ReadOptions(), "foo", &v)); + ASSERT_EQ("v6", v); +} + +TEST(CorruptionTest, CorruptedDescriptor) { + ASSERT_OK(db_->Put(WriteOptions(), "foo", "hello")); + DBImpl* dbi = reinterpret_cast(db_); + dbi->TEST_CompactMemTable(); + dbi->TEST_CompactRange(0, nullptr, nullptr); + + Corrupt(kDescriptorFile, 0, 1000); + Status s = TryReopen(); + ASSERT_TRUE(!s.ok()); + + RepairDB(); + Reopen(); + std::string v; + ASSERT_OK(db_->Get(ReadOptions(), "foo", &v)); + ASSERT_EQ("hello", v); +} + +TEST(CorruptionTest, CompactionInputError) { + Build(10); + DBImpl* dbi = reinterpret_cast(db_); + dbi->TEST_CompactMemTable(); + const int last = dbi->MaxMemCompactionLevel(); + ASSERT_EQ(1, Property("leveldb.num-files-at-level" + NumberToString(last))); + + Corrupt(kTableFile, 100, 1); + Check(9, 9); + + // Force compactions by writing lots of values + Build(10000); + Check(10000, 10000); +} + +TEST(CorruptionTest, CompactionInputErrorParanoid) { + Options options; + options.paranoid_checks = true; + options.write_buffer_size = 1048576; + Reopen(&options); + DBImpl* dbi = reinterpret_cast(db_); + + // Fill levels >= 1 so memtable compaction outputs to level 1 + for (int level = 1; level < dbi->NumberLevels(); level++) { + dbi->Put(WriteOptions(), "", "begin"); + dbi->Put(WriteOptions(), "~", "end"); + dbi->TEST_CompactMemTable(); + } + + Build(10); + dbi->TEST_CompactMemTable(); + ASSERT_EQ(1, Property("leveldb.num-files-at-level0")); + + Corrupt(kTableFile, 100, 1); + Check(9, 9); + + // Write must eventually fail because of corrupted table + Status s; + std::string tmp1, tmp2; + for (int i = 0; i < 10000 && s.ok(); i++) { + s = db_->Put(WriteOptions(), Key(i, &tmp1), Value(i, &tmp2)); + } + ASSERT_TRUE(!s.ok()) << "write did not fail in corrupted paranoid db"; +} + +TEST(CorruptionTest, UnrelatedKeys) { + Build(10); + DBImpl* dbi = reinterpret_cast(db_); + dbi->TEST_CompactMemTable(); + Corrupt(kTableFile, 100, 1); + + std::string tmp1, tmp2; + ASSERT_OK(db_->Put(WriteOptions(), Key(1000, &tmp1), Value(1000, &tmp2))); + std::string v; + ASSERT_OK(db_->Get(ReadOptions(), Key(1000, &tmp1), &v)); + ASSERT_EQ(Value(1000, &tmp2).ToString(), v); + dbi->TEST_CompactMemTable(); + ASSERT_OK(db_->Get(ReadOptions(), Key(1000, &tmp1), &v)); + ASSERT_EQ(Value(1000, &tmp2).ToString(), v); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/db/db_bench.cc b/db/db_bench.cc new file mode 100644 index 00000000..ce1ff7ab --- /dev/null +++ b/db/db_bench.cc @@ -0,0 +1,1697 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include +#include +#include "db/db_impl.h" +#include "db/version_set.h" +#include "db/db_statistics.h" +#include "leveldb/cache.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/write_batch.h" +#include "leveldb/statistics.h" +#include "port/port.h" +#include "util/crc32c.h" +#include "util/histogram.h" +#include "util/mutexlock.h" +#include "util/random.h" +#include "util/testutil.h" +#include "hdfs/env_hdfs.h" + +// Comma-separated list of operations to run in the specified order +// Actual benchmarks: +// fillseq -- write N values in sequential key order in async mode +// fillrandom -- write N values in random key order in async mode +// overwrite -- overwrite N values in random key order in async mode +// fillsync -- write N/100 values in random key order in sync mode +// fill100K -- write N/1000 100K values in random order in async mode +// deleteseq -- delete N keys in sequential order +// deleterandom -- delete N keys in random order +// readseq -- read N times sequentially +// readreverse -- read N times in reverse order +// readrandom -- read N times in random order +// readmissing -- read N missing keys in random order +// readhot -- read N times in random order from 1% section of DB +// seekrandom -- N random seeks +// crc32c -- repeated crc32c of 4K of data +// acquireload -- load N*1000 times +// Meta operations: +// compact -- Compact the entire DB +// stats -- Print DB stats +// sstables -- Print sstable info +// heapprofile -- Dump a heap profile (if supported by this port) +static const char* FLAGS_benchmarks = + "fillseq," + "fillsync," + "fillrandom," + "overwrite," + "readrandom," + "readrandom," // Extra run to allow previous compactions to quiesce + "readseq," + "readreverse," + "compact," + "readrandom," + "readseq," + "readreverse," + "readrandomwriterandom," // mix reads and writes based on FLAGS_readwritepercent + "randomwithverify," // random reads and writes with some verification + "fill100K," + "crc32c," + "snappycomp," + "snappyuncomp," + "acquireload," + ; +// the maximum size of key in bytes +static const int MAX_KEY_SIZE = 128; +// Number of key/values to place in database +static long FLAGS_num = 1000000; + +// Number of distinct keys to use. Used in RandomWithVerify to read/write +// on fewer keys so that gets are more likely to find the key and puts +// are more likely to update the same key +static long FLAGS_numdistinct = 1000; + +// Number of read operations to do. If negative, do FLAGS_num reads. +static long FLAGS_reads = -1; + +// When ==1 reads use ::Get, when >1 reads use an iterator +static long FLAGS_read_range = 1; + +// Seed base for random number generators. When 0 it is deterministic. +static long FLAGS_seed = 0; + +// Number of concurrent threads to run. +static int FLAGS_threads = 1; + +// Size of each value +static int FLAGS_value_size = 100; + +//size of each key +static int FLAGS_key_size = 16; + +// Arrange to generate values that shrink to this fraction of +// their original size after compression +static double FLAGS_compression_ratio = 0.5; + +// Print histogram of operation timings +static bool FLAGS_histogram = false; + +// Number of bytes to buffer in memtable before compacting +// (initialized to default value by "main") +static int FLAGS_write_buffer_size = 0; + +// The number of in-memory memtables. +// Each memtable is of size FLAGS_write_buffer_size. +// This is initialized to default value of 2 in "main" function. +static int FLAGS_max_write_buffer_number = 0; + +// The maximum number of concurrent background compactions +// that can occur in parallel. +// This is initialized to default value of 1 in "main" function. +static int FLAGS_max_background_compactions = 0; + +// Number of bytes to use as a cache of uncompressed data. +// Negative means use default settings. +static long FLAGS_cache_size = -1; + +// Number of bytes in a block. +static int FLAGS_block_size = 0; + +// Maximum number of files to keep open at the same time (use default if == 0) +static int FLAGS_open_files = 0; + +// Bloom filter bits per key. +// Negative means use default settings. +static int FLAGS_bloom_bits = -1; + +// If true, do not destroy the existing database. If you set this +// flag and also specify a benchmark that wants a fresh database, that +// benchmark will fail. +static bool FLAGS_use_existing_db = false; + +// Use the db with the following name. +static const char* FLAGS_db = nullptr; + +// Number of shards for the block cache is 2 ** FLAGS_cache_numshardbits. +// Negative means use default settings. This is applied only +// if FLAGS_cache_size is non-negative. +static int FLAGS_cache_numshardbits = -1; + +// Verify checksum for every block read from storage +static bool FLAGS_verify_checksum = false; + +// Database statistics +static bool FLAGS_statistics = false; +static class leveldb::DBStatistics* dbstats = nullptr; + +// Number of write operations to do. If negative, do FLAGS_num reads. +static long FLAGS_writes = -1; + +// These default values might change if the hardcoded + +// Sync all writes to disk +static bool FLAGS_sync = false; + +// If true, do not wait until data is synced to disk. +static bool FLAGS_disable_data_sync = false; + +// If true, issue fsync instead of fdatasync +static bool FLAGS_use_fsync = false; + +// If true, do not write WAL for write. +static bool FLAGS_disable_wal = false; + +// The total number of levels +static unsigned int FLAGS_num_levels = 7; + +// Target level-0 file size for compaction +static int FLAGS_target_file_size_base = 2 * 1048576; + +// A multiplier to compute targe level-N file size +static int FLAGS_target_file_size_multiplier = 1; + +// Max bytes for level-1 +static uint64_t FLAGS_max_bytes_for_level_base = 10 * 1048576; + +// A multiplier to compute max bytes for level-N +static int FLAGS_max_bytes_for_level_multiplier = 10; + +// Number of files in level-0 that will trigger put stop. +static int FLAGS_level0_stop_writes_trigger = 12; + +// Number of files in level-0 that will slow down writes. +static int FLAGS_level0_slowdown_writes_trigger = 8; + +// Number of files in level-0 when compactions start +static int FLAGS_level0_file_num_compaction_trigger = 4; + +// Ratio of reads to writes (expressed as a percentage) +// for the ReadRandomWriteRandom workload. The default +// setting is 9 gets for every 1 put. +static int FLAGS_readwritepercent = 90; + +// This percent of deletes are done (used in RandomWithVerify only) +// Must be smaller than total writepercent (i.e 100 - FLAGS_readwritepercent) +static int FLAGS_deletepercent = 2; + +// Option to disable compation triggered by read. +static int FLAGS_disable_seek_compaction = false; + +// Option to delete obsolete files periodically +// Default: 0 which means that obsolete files are +// deleted after every compaction run. +static uint64_t FLAGS_delete_obsolete_files_period_micros = 0; + +// Algorithm to use to compress the database +static enum leveldb::CompressionType FLAGS_compression_type = + leveldb::kSnappyCompression; + +// Allows compression for levels 0 and 1 to be disabled when +// other levels are compressed +static int FLAGS_min_level_to_compress = -1; + +static int FLAGS_table_cache_numshardbits = 4; + +// posix or hdfs environment +static leveldb::Env* FLAGS_env = leveldb::Env::Default(); + +// Stats are reported every N operations when this is greater +// than zero. When 0 the interval grows over time. +static int FLAGS_stats_interval = 0; + +// Reports additional stats per interval when this is greater +// than 0. +static int FLAGS_stats_per_interval = 0; + +// When not equal to 0 this make threads sleep at each stats +// reporting interval until the compaction score for all levels is +// less than or equal to this value. +static double FLAGS_rate_limit = 0; + +// When FLAGS_rate_limit is set then this is the max time a put will be stalled. +static int FLAGS_rate_limit_delay_milliseconds = 1000; + +// Control maximum bytes of overlaps in grandparent (i.e., level+2) before we +// stop building a single file in a level->level+1 compaction. +static int FLAGS_max_grandparent_overlap_factor = 10; + +// Run read only benchmarks. +static bool FLAGS_read_only = false; + +// Do not auto trigger compactions +static bool FLAGS_disable_auto_compactions = false; + +// Cap the size of data in levelK for a compaction run +// that compacts Levelk with LevelK+1 +static int FLAGS_source_compaction_factor = 1; + +// Set the TTL for the WAL Files. +static uint64_t FLAGS_WAL_ttl_seconds = 0; + +extern bool useOsBuffer; +extern bool useFsReadAhead; +extern bool useMmapRead; +extern bool useMmapWrite; + +namespace leveldb { + +// Helper for quickly generating random data. +class RandomGenerator { + private: + std::string data_; + unsigned int pos_; + + public: + RandomGenerator() { + // We use a limited amount of data over and over again and ensure + // that it is larger than the compression window (32KB), and also + // large enough to serve all typical value sizes we want to write. + Random rnd(301); + std::string piece; + while (data_.size() < 1048576) { + // Add a short fragment that is as compressible as specified + // by FLAGS_compression_ratio. + test::CompressibleString(&rnd, FLAGS_compression_ratio, 100, &piece); + data_.append(piece); + } + pos_ = 0; + } + + Slice Generate(int len) { + if (pos_ + len > data_.size()) { + pos_ = 0; + assert(len < data_.size()); + } + pos_ += len; + return Slice(data_.data() + pos_ - len, len); + } +}; +static Slice TrimSpace(Slice s) { + unsigned int start = 0; + while (start < s.size() && isspace(s[start])) { + start++; + } + unsigned int limit = s.size(); + while (limit > start && isspace(s[limit-1])) { + limit--; + } + return Slice(s.data() + start, limit - start); +} + +static void AppendWithSpace(std::string* str, Slice msg) { + if (msg.empty()) return; + if (!str->empty()) { + str->push_back(' '); + } + str->append(msg.data(), msg.size()); +} + +class Stats { + private: + int id_; + double start_; + double finish_; + double seconds_; + long done_; + long last_report_done_; + int next_report_; + int64_t bytes_; + double last_op_finish_; + double last_report_finish_; + HistogramImpl hist_; + std::string message_; + + public: + Stats() { Start(-1); } + + void Start(int id) { + id_ = id; + next_report_ = FLAGS_stats_interval ? FLAGS_stats_interval : 100; + last_op_finish_ = start_; + hist_.Clear(); + done_ = 0; + last_report_done_ = 0; + bytes_ = 0; + seconds_ = 0; + start_ = FLAGS_env->NowMicros(); + finish_ = start_; + last_report_finish_ = start_; + message_.clear(); + } + + void Merge(const Stats& other) { + hist_.Merge(other.hist_); + done_ += other.done_; + bytes_ += other.bytes_; + seconds_ += other.seconds_; + if (other.start_ < start_) start_ = other.start_; + if (other.finish_ > finish_) finish_ = other.finish_; + + // Just keep the messages from one thread + if (message_.empty()) message_ = other.message_; + } + + void Stop() { + finish_ = FLAGS_env->NowMicros(); + seconds_ = (finish_ - start_) * 1e-6; + } + + void AddMessage(Slice msg) { + AppendWithSpace(&message_, msg); + } + + void SetId(int id) { id_ = id; } + + void FinishedSingleOp(DB* db) { + if (FLAGS_histogram) { + double now = FLAGS_env->NowMicros(); + double micros = now - last_op_finish_; + hist_.Add(micros); + if (micros > 20000 && !FLAGS_stats_interval) { + fprintf(stderr, "long op: %.1f micros%30s\r", micros, ""); + fflush(stderr); + } + last_op_finish_ = now; + } + + done_++; + if (done_ >= next_report_) { + if (!FLAGS_stats_interval) { + if (next_report_ < 1000) next_report_ += 100; + else if (next_report_ < 5000) next_report_ += 500; + else if (next_report_ < 10000) next_report_ += 1000; + else if (next_report_ < 50000) next_report_ += 5000; + else if (next_report_ < 100000) next_report_ += 10000; + else if (next_report_ < 500000) next_report_ += 50000; + else next_report_ += 100000; + fprintf(stderr, "... finished %ld ops%30s\r", done_, ""); + fflush(stderr); + } else { + double now = FLAGS_env->NowMicros(); + fprintf(stderr, + "%s ... thread %d: (%ld,%ld) ops and (%.1f,%.1f) ops/second in (%.6f,%.6f) seconds\n", + FLAGS_env->TimeToString((uint64_t) now/1000000).c_str(), + id_, + done_ - last_report_done_, done_, + (done_ - last_report_done_) / + ((now - last_report_finish_) / 1000000.0), + done_ / ((now - start_) / 1000000.0), + (now - last_report_finish_) / 1000000.0, + (now - start_) / 1000000.0); + + if (FLAGS_stats_per_interval) { + std::string stats; + if (db && db->GetProperty("leveldb.stats", &stats)) + fprintf(stderr, "%s\n", stats.c_str()); + } + + fflush(stderr); + next_report_ += FLAGS_stats_interval; + last_report_finish_ = now; + last_report_done_ = done_; + } + } + } + + void AddBytes(int64_t n) { + bytes_ += n; + } + + void Report(const Slice& name) { + // Pretend at least one op was done in case we are running a benchmark + // that does not call FinishedSingleOp(). + if (done_ < 1) done_ = 1; + + std::string extra; + if (bytes_ > 0) { + // Rate is computed on actual elapsed time, not the sum of per-thread + // elapsed times. + double elapsed = (finish_ - start_) * 1e-6; + char rate[100]; + snprintf(rate, sizeof(rate), "%6.1f MB/s", + (bytes_ / 1048576.0) / elapsed); + extra = rate; + } + AppendWithSpace(&extra, message_); + double elapsed = (finish_ - start_) * 1e-6; + double throughput = (double)done_/elapsed; + + fprintf(stdout, "%-12s : %11.3f micros/op %ld ops/sec;%s%s\n", + name.ToString().c_str(), + seconds_ * 1e6 / done_, + (long)throughput, + (extra.empty() ? "" : " "), + extra.c_str()); + if (FLAGS_histogram) { + fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str()); + } + fflush(stdout); + } +}; + +// State shared by all concurrent executions of the same benchmark. +struct SharedState { + port::Mutex mu; + port::CondVar cv; + int total; + + // Each thread goes through the following states: + // (1) initializing + // (2) waiting for others to be initialized + // (3) running + // (4) done + + long num_initialized; + long num_done; + bool start; + + SharedState() : cv(&mu) { } +}; + +// Per-thread state for concurrent executions of the same benchmark. +struct ThreadState { + int tid; // 0..n-1 when running in n threads + Random rand; // Has different seeds for different threads + Stats stats; + SharedState* shared; + + /* implicit */ ThreadState(int index) + : tid(index), + rand((FLAGS_seed ? FLAGS_seed : 1000) + index) { + } +}; + +class Benchmark { + private: + shared_ptr cache_; + const FilterPolicy* filter_policy_; + DB* db_; + long num_; + int value_size_; + int key_size_; + int entries_per_batch_; + WriteOptions write_options_; + long reads_; + long writes_; + long readwrites_; + int heap_counter_; + char keyFormat_[100]; // this string will contain the format of key. e.g "%016d" + void PrintHeader() { + PrintEnvironment(); + fprintf(stdout, "Keys: %d bytes each\n", FLAGS_key_size); + fprintf(stdout, "Values: %d bytes each (%d bytes after compression)\n", + FLAGS_value_size, + static_cast(FLAGS_value_size * FLAGS_compression_ratio + 0.5)); + fprintf(stdout, "Entries: %ld\n", num_); + fprintf(stdout, "RawSize: %.1f MB (estimated)\n", + ((static_cast(FLAGS_key_size + FLAGS_value_size) * num_) + / 1048576.0)); + fprintf(stdout, "FileSize: %.1f MB (estimated)\n", + (((FLAGS_key_size + FLAGS_value_size * FLAGS_compression_ratio) * num_) + / 1048576.0)); + + switch (FLAGS_compression_type) { + case leveldb::kNoCompression: + fprintf(stdout, "Compression: none\n"); + break; + case leveldb::kSnappyCompression: + fprintf(stdout, "Compression: snappy\n"); + break; + case leveldb::kZlibCompression: + fprintf(stdout, "Compression: zlib\n"); + break; + case leveldb::kBZip2Compression: + fprintf(stdout, "Compression: bzip2\n"); + break; + } + + PrintWarnings(); + fprintf(stdout, "------------------------------------------------\n"); + } + + void PrintWarnings() { +#if defined(__GNUC__) && !defined(__OPTIMIZE__) + fprintf(stdout, + "WARNING: Optimization is disabled: benchmarks unnecessarily slow\n" + ); +#endif +#ifndef NDEBUG + fprintf(stdout, + "WARNING: Assertions are enabled; benchmarks unnecessarily slow\n"); +#endif + + if (FLAGS_compression_type != leveldb::kNoCompression) { + // The test string should not be too small. + const int len = FLAGS_block_size; + char* text = (char*) malloc(len+1); + bool result = true; + const char* name = nullptr; + std::string compressed; + + memset(text, (int) 'y', len); + text[len] = '\0'; + + switch (FLAGS_compression_type) { + case kSnappyCompression: + result = port::Snappy_Compress(Options().compression_opts, text, + strlen(text), &compressed); + name = "Snappy"; + break; + case kZlibCompression: + result = port::Zlib_Compress(Options().compression_opts, text, + strlen(text), &compressed); + name = "Zlib"; + break; + case kBZip2Compression: + result = port::BZip2_Compress(Options().compression_opts, text, + strlen(text), &compressed); + name = "BZip2"; + break; + case kNoCompression: + assert(false); // cannot happen + break; + } + + if (!result) { + fprintf(stdout, "WARNING: %s compression is not enabled\n", name); + } else if (name && compressed.size() >= strlen(text)) { + fprintf(stdout, "WARNING: %s compression is not effective\n", name); + } + + free(text); + } + } + + void PrintEnvironment() { + fprintf(stderr, "LevelDB: version %d.%d\n", + kMajorVersion, kMinorVersion); + +#if defined(__linux) + time_t now = time(nullptr); + fprintf(stderr, "Date: %s", ctime(&now)); // ctime() adds newline + + FILE* cpuinfo = fopen("/proc/cpuinfo", "r"); + if (cpuinfo != nullptr) { + char line[1000]; + int num_cpus = 0; + std::string cpu_type; + std::string cache_size; + while (fgets(line, sizeof(line), cpuinfo) != nullptr) { + const char* sep = strchr(line, ':'); + if (sep == nullptr) { + continue; + } + Slice key = TrimSpace(Slice(line, sep - 1 - line)); + Slice val = TrimSpace(Slice(sep + 1)); + if (key == "model name") { + ++num_cpus; + cpu_type = val.ToString(); + } else if (key == "cache size") { + cache_size = val.ToString(); + } + } + fclose(cpuinfo); + fprintf(stderr, "CPU: %d * %s\n", num_cpus, cpu_type.c_str()); + fprintf(stderr, "CPUCache: %s\n", cache_size.c_str()); + } +#endif + } + + void PrintHistogram(Histograms histogram_type, std::string name) { + HistogramData histogramData; + dbstats->histogramData(histogram_type, &histogramData); + fprintf(stdout, "%s statistics : \n", name.c_str()); + fprintf(stdout, "Median : %f\n",histogramData.median); + fprintf(stdout, "99ile : %f\n", histogramData.percentile99); + } + + void PrintStatistics() { + if (FLAGS_statistics) { + fprintf(stdout, "File opened:%ld closed:%ld errors:%ld\n" + "Block Cache Hit Count:%ld Block Cache Miss Count:%ld\n" + "Bloom Filter Useful: %ld \n" + "Compaction key_drop_newer_entry: %ld key_drop_obsolete: %ld " + "Compaction key_drop_user: %ld\n", + dbstats->getTickerCount(NO_FILE_OPENS), + dbstats->getTickerCount(NO_FILE_CLOSES), + dbstats->getTickerCount(NO_FILE_ERRORS), + dbstats->getTickerCount(BLOCK_CACHE_HIT), + dbstats->getTickerCount(BLOCK_CACHE_MISS), + dbstats->getTickerCount(BLOOM_FILTER_USEFUL), + dbstats->getTickerCount(COMPACTION_KEY_DROP_NEWER_ENTRY), + dbstats->getTickerCount(COMPACTION_KEY_DROP_OBSOLETE), + dbstats->getTickerCount(COMPACTION_KEY_DROP_USER)); + PrintHistogram(DB_GET, "DB_GET"); + PrintHistogram(DB_WRITE, "DB_WRITE"); + } + } + + public: + Benchmark() + : cache_(FLAGS_cache_size >= 0 ? + (FLAGS_cache_numshardbits >= 1 ? + NewLRUCache(FLAGS_cache_size, FLAGS_cache_numshardbits) : + NewLRUCache(FLAGS_cache_size)) : nullptr), + filter_policy_(FLAGS_bloom_bits >= 0 + ? NewBloomFilterPolicy(FLAGS_bloom_bits) + : nullptr), + db_(nullptr), + num_(FLAGS_num), + value_size_(FLAGS_value_size), + key_size_(FLAGS_key_size), + entries_per_batch_(1), + reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads), + writes_(FLAGS_writes < 0 ? FLAGS_num : FLAGS_writes), + readwrites_((FLAGS_writes < 0 && FLAGS_reads < 0)? FLAGS_num : + ((FLAGS_writes > FLAGS_reads) ? FLAGS_writes : FLAGS_reads) + ), + heap_counter_(0) { + std::vector files; + FLAGS_env->GetChildren(FLAGS_db, &files); + for (unsigned int i = 0; i < files.size(); i++) { + if (Slice(files[i]).starts_with("heap-")) { + FLAGS_env->DeleteFile(std::string(FLAGS_db) + "/" + files[i]); + } + } + if (!FLAGS_use_existing_db) { + DestroyDB(FLAGS_db, Options()); + } + } + + ~Benchmark() { + delete db_; + delete filter_policy_; + } +//this function will construct string format for key. e.g "%016d" +void ConstructStrFormatForKey(char* str, int keySize) +{ + str[0] = '%'; + str[1] = '0'; + sprintf(str+2, "%dd", keySize); +} + +unique_ptr GenerateKeyFromInt(int v) +{ + unique_ptr keyInStr(new char[MAX_KEY_SIZE]); + snprintf(keyInStr.get(), MAX_KEY_SIZE, keyFormat_, v); + return keyInStr; +} + void Run() { + PrintHeader(); + Open(); + + const char* benchmarks = FLAGS_benchmarks; + while (benchmarks != nullptr) { + const char* sep = strchr(benchmarks, ','); + Slice name; + if (sep == nullptr) { + name = benchmarks; + benchmarks = nullptr; + } else { + name = Slice(benchmarks, sep - benchmarks); + benchmarks = sep + 1; + } + + // Reset parameters that may be overriddden bwlow + num_ = FLAGS_num; + reads_ = (FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads); + writes_ = (FLAGS_writes < 0 ? FLAGS_num : FLAGS_writes); + value_size_ = FLAGS_value_size; + key_size_ = FLAGS_key_size; + ConstructStrFormatForKey(keyFormat_, key_size_); + entries_per_batch_ = 1; + write_options_ = WriteOptions(); + if (FLAGS_sync) { + write_options_.sync = true; + } + write_options_.disableWAL = FLAGS_disable_wal; + + void (Benchmark::*method)(ThreadState*) = nullptr; + bool fresh_db = false; + int num_threads = FLAGS_threads; + + if (name == Slice("fillseq")) { + fresh_db = true; + method = &Benchmark::WriteSeq; + } else if (name == Slice("fillbatch")) { + fresh_db = true; + entries_per_batch_ = 1000; + method = &Benchmark::WriteSeq; + } else if (name == Slice("fillrandom")) { + fresh_db = true; + method = &Benchmark::WriteRandom; + } else if (name == Slice("overwrite")) { + fresh_db = false; + method = &Benchmark::WriteRandom; + } else if (name == Slice("fillsync")) { + fresh_db = true; + num_ /= 1000; + write_options_.sync = true; + method = &Benchmark::WriteRandom; + } else if (name == Slice("fill100K")) { + fresh_db = true; + num_ /= 1000; + value_size_ = 100 * 1000; + method = &Benchmark::WriteRandom; + } else if (name == Slice("readseq")) { + method = &Benchmark::ReadSequential; + } else if (name == Slice("readreverse")) { + method = &Benchmark::ReadReverse; + } else if (name == Slice("readrandom")) { + method = &Benchmark::ReadRandom; + } else if (name == Slice("readmissing")) { + method = &Benchmark::ReadMissing; + } else if (name == Slice("seekrandom")) { + method = &Benchmark::SeekRandom; + } else if (name == Slice("readhot")) { + method = &Benchmark::ReadHot; + } else if (name == Slice("readrandomsmall")) { + reads_ /= 1000; + method = &Benchmark::ReadRandom; + } else if (name == Slice("deleteseq")) { + method = &Benchmark::DeleteSeq; + } else if (name == Slice("deleterandom")) { + method = &Benchmark::DeleteRandom; + } else if (name == Slice("readwhilewriting")) { + num_threads++; // Add extra thread for writing + method = &Benchmark::ReadWhileWriting; + } else if (name == Slice("readrandomwriterandom")) { + method = &Benchmark::ReadRandomWriteRandom; + } else if (name == Slice("randomwithverify")) { + method = &Benchmark::RandomWithVerify; + } else if (name == Slice("compact")) { + method = &Benchmark::Compact; + } else if (name == Slice("crc32c")) { + method = &Benchmark::Crc32c; + } else if (name == Slice("acquireload")) { + method = &Benchmark::AcquireLoad; + } else if (name == Slice("snappycomp")) { + method = &Benchmark::SnappyCompress; + } else if (name == Slice("snappyuncomp")) { + method = &Benchmark::SnappyUncompress; + } else if (name == Slice("heapprofile")) { + HeapProfile(); + } else if (name == Slice("stats")) { + PrintStats("leveldb.stats"); + } else if (name == Slice("sstables")) { + PrintStats("leveldb.sstables"); + } else { + if (name != Slice()) { // No error message for empty name + fprintf(stderr, "unknown benchmark '%s'\n", name.ToString().c_str()); + } + } + + if (fresh_db) { + if (FLAGS_use_existing_db) { + fprintf(stdout, "%-12s : skipped (--use_existing_db is true)\n", + name.ToString().c_str()); + method = nullptr; + } else { + delete db_; + db_ = nullptr; + DestroyDB(FLAGS_db, Options()); + Open(); + } + } + + if (method != nullptr) { + RunBenchmark(num_threads, name, method); + } + } + PrintStatistics(); + } + + private: + struct ThreadArg { + Benchmark* bm; + SharedState* shared; + ThreadState* thread; + void (Benchmark::*method)(ThreadState*); + }; + + static void ThreadBody(void* v) { + ThreadArg* arg = reinterpret_cast(v); + SharedState* shared = arg->shared; + ThreadState* thread = arg->thread; + { + MutexLock l(&shared->mu); + shared->num_initialized++; + if (shared->num_initialized >= shared->total) { + shared->cv.SignalAll(); + } + while (!shared->start) { + shared->cv.Wait(); + } + } + + thread->stats.Start(thread->tid); + (arg->bm->*(arg->method))(thread); + thread->stats.Stop(); + + { + MutexLock l(&shared->mu); + shared->num_done++; + if (shared->num_done >= shared->total) { + shared->cv.SignalAll(); + } + } + } + + void RunBenchmark(int n, Slice name, + void (Benchmark::*method)(ThreadState*)) { + SharedState shared; + shared.total = n; + shared.num_initialized = 0; + shared.num_done = 0; + shared.start = false; + + ThreadArg* arg = new ThreadArg[n]; + for (int i = 0; i < n; i++) { + arg[i].bm = this; + arg[i].method = method; + arg[i].shared = &shared; + arg[i].thread = new ThreadState(i); + arg[i].thread->shared = &shared; + FLAGS_env->StartThread(ThreadBody, &arg[i]); + } + + shared.mu.Lock(); + while (shared.num_initialized < n) { + shared.cv.Wait(); + } + + shared.start = true; + shared.cv.SignalAll(); + while (shared.num_done < n) { + shared.cv.Wait(); + } + shared.mu.Unlock(); + + for (int i = 1; i < n; i++) { + arg[0].thread->stats.Merge(arg[i].thread->stats); + } + arg[0].thread->stats.Report(name); + + for (int i = 0; i < n; i++) { + delete arg[i].thread; + } + delete[] arg; + } + + void Crc32c(ThreadState* thread) { + // Checksum about 500MB of data total + const int size = 4096; + const char* label = "(4K per op)"; + std::string data(size, 'x'); + int64_t bytes = 0; + uint32_t crc = 0; + while (bytes < 500 * 1048576) { + crc = crc32c::Value(data.data(), size); + thread->stats.FinishedSingleOp(nullptr); + bytes += size; + } + // Print so result is not dead + fprintf(stderr, "... crc=0x%x\r", static_cast(crc)); + + thread->stats.AddBytes(bytes); + thread->stats.AddMessage(label); + } + + void AcquireLoad(ThreadState* thread) { + int dummy; + port::AtomicPointer ap(&dummy); + int count = 0; + void *ptr = nullptr; + thread->stats.AddMessage("(each op is 1000 loads)"); + while (count < 100000) { + for (int i = 0; i < 1000; i++) { + ptr = ap.Acquire_Load(); + } + count++; + thread->stats.FinishedSingleOp(nullptr); + } + if (ptr == nullptr) exit(1); // Disable unused variable warning. + } + + void SnappyCompress(ThreadState* thread) { + RandomGenerator gen; + Slice input = gen.Generate(Options().block_size); + int64_t bytes = 0; + int64_t produced = 0; + bool ok = true; + std::string compressed; + while (ok && bytes < 1024 * 1048576) { // Compress 1G + ok = port::Snappy_Compress(Options().compression_opts, input.data(), + input.size(), &compressed); + produced += compressed.size(); + bytes += input.size(); + thread->stats.FinishedSingleOp(nullptr); + } + + if (!ok) { + thread->stats.AddMessage("(snappy failure)"); + } else { + char buf[100]; + snprintf(buf, sizeof(buf), "(output: %.1f%%)", + (produced * 100.0) / bytes); + thread->stats.AddMessage(buf); + thread->stats.AddBytes(bytes); + } + } + + void SnappyUncompress(ThreadState* thread) { + RandomGenerator gen; + Slice input = gen.Generate(Options().block_size); + std::string compressed; + bool ok = port::Snappy_Compress(Options().compression_opts, input.data(), + input.size(), &compressed); + int64_t bytes = 0; + char* uncompressed = new char[input.size()]; + while (ok && bytes < 1024 * 1048576) { // Compress 1G + ok = port::Snappy_Uncompress(compressed.data(), compressed.size(), + uncompressed); + bytes += input.size(); + thread->stats.FinishedSingleOp(nullptr); + } + delete[] uncompressed; + + if (!ok) { + thread->stats.AddMessage("(snappy failure)"); + } else { + thread->stats.AddBytes(bytes); + } + } + + void Open() { + assert(db_ == nullptr); + Options options; + options.create_if_missing = !FLAGS_use_existing_db; + options.block_cache = cache_; + if (cache_ == nullptr) { + options.no_block_cache = true; + } + options.write_buffer_size = FLAGS_write_buffer_size; + options.max_write_buffer_number = FLAGS_max_write_buffer_number; + options.max_background_compactions = FLAGS_max_background_compactions; + options.block_size = FLAGS_block_size; + options.filter_policy = filter_policy_; + options.max_open_files = FLAGS_open_files; + options.statistics = dbstats; + options.env = FLAGS_env; + options.disableDataSync = FLAGS_disable_data_sync; + options.use_fsync = FLAGS_use_fsync; + options.num_levels = FLAGS_num_levels; + options.target_file_size_base = FLAGS_target_file_size_base; + options.target_file_size_multiplier = FLAGS_target_file_size_multiplier; + options.max_bytes_for_level_base = FLAGS_max_bytes_for_level_base; + options.max_bytes_for_level_multiplier = + FLAGS_max_bytes_for_level_multiplier; + options.level0_stop_writes_trigger = FLAGS_level0_stop_writes_trigger; + options.level0_file_num_compaction_trigger = + FLAGS_level0_file_num_compaction_trigger; + options.level0_slowdown_writes_trigger = + FLAGS_level0_slowdown_writes_trigger; + options.compression = FLAGS_compression_type; + options.WAL_ttl_seconds = FLAGS_WAL_ttl_seconds; + if (FLAGS_min_level_to_compress >= 0) { + assert(FLAGS_min_level_to_compress <= FLAGS_num_levels); + options.compression_per_level.resize(FLAGS_num_levels); + for (int i = 0; i < FLAGS_min_level_to_compress; i++) { + options.compression_per_level[i] = kNoCompression; + } + for (unsigned int i = FLAGS_min_level_to_compress; + i < FLAGS_num_levels; i++) { + options.compression_per_level[i] = FLAGS_compression_type; + } + } + options.disable_seek_compaction = FLAGS_disable_seek_compaction; + options.delete_obsolete_files_period_micros = + FLAGS_delete_obsolete_files_period_micros; + options.rate_limit = FLAGS_rate_limit; + options.rate_limit_delay_milliseconds = FLAGS_rate_limit_delay_milliseconds; + options.table_cache_numshardbits = FLAGS_table_cache_numshardbits; + options.max_grandparent_overlap_factor = + FLAGS_max_grandparent_overlap_factor; + options.disable_auto_compactions = FLAGS_disable_auto_compactions; + options.source_compaction_factor = FLAGS_source_compaction_factor; + Status s; + if(FLAGS_read_only) { + s = DB::OpenForReadOnly(options, FLAGS_db, &db_); + } else { + s = DB::Open(options, FLAGS_db, &db_); + } + if (!s.ok()) { + fprintf(stderr, "open error: %s\n", s.ToString().c_str()); + exit(1); + } + if (FLAGS_min_level_to_compress >= 0) { + options.compression_per_level.clear(); + } + } + + void WriteSeq(ThreadState* thread) { + DoWrite(thread, true); + } + + void WriteRandom(ThreadState* thread) { + DoWrite(thread, false); + } + + void DoWrite(ThreadState* thread, bool seq) { + if (num_ != FLAGS_num) { + char msg[100]; + snprintf(msg, sizeof(msg), "(%ld ops)", num_); + thread->stats.AddMessage(msg); + } + + RandomGenerator gen; + WriteBatch batch; + Status s; + int64_t bytes = 0; + for (int i = 0; i < writes_; i += entries_per_batch_) { + batch.Clear(); + for (int j = 0; j < entries_per_batch_; j++) { + const int k = seq ? i+j : (thread->rand.Next() % FLAGS_num); + unique_ptr key = GenerateKeyFromInt(k); + batch.Put(key.get(), gen.Generate(value_size_)); + bytes += value_size_ + strlen(key.get()); + thread->stats.FinishedSingleOp(db_); + } + s = db_->Write(write_options_, &batch); + if (!s.ok()) { + fprintf(stderr, "put error: %s\n", s.ToString().c_str()); + exit(1); + } + } + thread->stats.AddBytes(bytes); + } + + void ReadSequential(ThreadState* thread) { + Iterator* iter = db_->NewIterator(ReadOptions(FLAGS_verify_checksum, true)); + long i = 0; + int64_t bytes = 0; + for (iter->SeekToFirst(); i < reads_ && iter->Valid(); iter->Next()) { + bytes += iter->key().size() + iter->value().size(); + thread->stats.FinishedSingleOp(db_); + ++i; + } + delete iter; + thread->stats.AddBytes(bytes); + } + + void ReadReverse(ThreadState* thread) { + Iterator* iter = db_->NewIterator(ReadOptions(FLAGS_verify_checksum, true)); + long i = 0; + int64_t bytes = 0; + for (iter->SeekToLast(); i < reads_ && iter->Valid(); iter->Prev()) { + bytes += iter->key().size() + iter->value().size(); + thread->stats.FinishedSingleOp(db_); + ++i; + } + delete iter; + thread->stats.AddBytes(bytes); + } + + void ReadRandom(ThreadState* thread) { + ReadOptions options(FLAGS_verify_checksum, true); + Iterator* iter = db_->NewIterator(options); + + std::string value; + long found = 0; + for (long i = 0; i < reads_; i++) { + const int k = thread->rand.Next() % FLAGS_num; + unique_ptr key = GenerateKeyFromInt(k); + if (FLAGS_read_range < 2) { + if (db_->Get(options, key.get(), &value).ok()) { + found++; + } + } else { + Slice skey(key.get()); + int count = 1; + for (iter->Seek(skey); + iter->Valid() && count <= FLAGS_read_range; + ++count, iter->Next()) { + found++; + } + } + + thread->stats.FinishedSingleOp(db_); + } + delete iter; + char msg[100]; + snprintf(msg, sizeof(msg), "(%ld of %ld found)", found, num_); + thread->stats.AddMessage(msg); + } + + void ReadMissing(ThreadState* thread) { + ReadOptions options(FLAGS_verify_checksum, true); + std::string value; + for (long i = 0; i < reads_; i++) { + const int k = thread->rand.Next() % FLAGS_num; + unique_ptr key = GenerateKeyFromInt(k); + db_->Get(options, key.get(), &value); + thread->stats.FinishedSingleOp(db_); + } + } + + void ReadHot(ThreadState* thread) { + ReadOptions options(FLAGS_verify_checksum, true); + std::string value; + const long range = (FLAGS_num + 99) / 100; + for (long i = 0; i < reads_; i++) { + const int k = thread->rand.Next() % range; + unique_ptr key = GenerateKeyFromInt(k); + db_->Get(options, key.get(), &value); + thread->stats.FinishedSingleOp(db_); + } + } + + void SeekRandom(ThreadState* thread) { + ReadOptions options(FLAGS_verify_checksum, true); + std::string value; + long found = 0; + for (long i = 0; i < reads_; i++) { + Iterator* iter = db_->NewIterator(options); + const int k = thread->rand.Next() % FLAGS_num; + unique_ptr key = GenerateKeyFromInt(k); + iter->Seek(key.get()); + if (iter->Valid() && iter->key() == key.get()) found++; + delete iter; + thread->stats.FinishedSingleOp(db_); + } + char msg[100]; + snprintf(msg, sizeof(msg), "(%ld of %ld found)", found, num_); + thread->stats.AddMessage(msg); + } + + void DoDelete(ThreadState* thread, bool seq) { + RandomGenerator gen; + WriteBatch batch; + Status s; + for (int i = 0; i < num_; i += entries_per_batch_) { + batch.Clear(); + for (int j = 0; j < entries_per_batch_; j++) { + const int k = seq ? i+j : (thread->rand.Next() % FLAGS_num); + unique_ptr key = GenerateKeyFromInt(k); + batch.Delete(key.get()); + thread->stats.FinishedSingleOp(db_); + } + s = db_->Write(write_options_, &batch); + if (!s.ok()) { + fprintf(stderr, "del error: %s\n", s.ToString().c_str()); + exit(1); + } + } + } + + void DeleteSeq(ThreadState* thread) { + DoDelete(thread, true); + } + + void DeleteRandom(ThreadState* thread) { + DoDelete(thread, false); + } + + void ReadWhileWriting(ThreadState* thread) { + if (thread->tid > 0) { + ReadRandom(thread); + } else { + // Special thread that keeps writing until other threads are done. + RandomGenerator gen; + while (true) { + { + MutexLock l(&thread->shared->mu); + if (thread->shared->num_done + 1 >= thread->shared->num_initialized) { + // Other threads have finished + break; + } + } + + const int k = thread->rand.Next() % FLAGS_num; + unique_ptr key = GenerateKeyFromInt(k); + Status s = db_->Put(write_options_, key.get(), gen.Generate(value_size_)); + if (!s.ok()) { + fprintf(stderr, "put error: %s\n", s.ToString().c_str()); + exit(1); + } + } + + // Do not count any of the preceding work/delay in stats. + thread->stats.Start(thread->tid); + } + } + + // Given a key K and value V, this puts (K+"0", V), (K+"1", V), (K+"2", V) + // in DB atomically i.e in a single batch. Also refer MultiGet. + Status MultiPut(const WriteOptions& writeoptions, + const Slice& key, const Slice& value) { + std::string suffixes[3] = {"2", "1", "0"}; + std::string keys[3]; + + WriteBatch batch; + Status s; + for (int i = 0; i < 3; i++) { + keys[i] = key.ToString() + suffixes[i]; + batch.Put(keys[i], value); + } + + s = db_->Write(writeoptions, &batch); + return s; + } + + + // Given a key K, this deletes (K+"0", V), (K+"1", V), (K+"2", V) + // in DB atomically i.e in a single batch. Also refer MultiGet. + Status MultiDelete(const WriteOptions& writeoptions, + const Slice& key) { + std::string suffixes[3] = {"1", "2", "0"}; + std::string keys[3]; + + WriteBatch batch; + Status s; + for (int i = 0; i < 3; i++) { + keys[i] = key.ToString() + suffixes[i]; + batch.Delete(keys[i]); + } + + s = db_->Write(writeoptions, &batch); + return s; + } + + // Given a key K and value V, this gets values for K+"0", K+"1" and K+"2" + // in the same snapshot, and verifies that all the values are identical. + // ASSUMES that MultiPut was used to put (K, V) into the DB. + Status MultiGet(const ReadOptions& readoptions, + const Slice& key, std::string* value) { + std::string suffixes[3] = {"0", "1", "2"}; + std::string keys[3]; + Slice key_slices[3]; + std::string values[3]; + ReadOptions readoptionscopy = readoptions; + readoptionscopy.snapshot = db_->GetSnapshot(); + Status s; + for (int i = 0; i < 3; i++) { + keys[i] = key.ToString() + suffixes[i]; + key_slices[i] = keys[i]; + s = db_->Get(readoptionscopy, key_slices[i], value); + if (!s.ok() && !s.IsNotFound()) { + fprintf(stderr, "get error: %s\n", s.ToString().c_str()); + values[i] = ""; + // we continue after error rather than exiting so that we can + // find more errors if any + } else if (s.IsNotFound()) { + values[i] = ""; + } else { + values[i] = *value; + } + } + db_->ReleaseSnapshot(readoptionscopy.snapshot); + + if ((values[0] != values[1]) || (values[1] != values[2])) { + fprintf(stderr, "inconsistent values for key %s: %s, %s, %s\n", + key.ToString().c_str(), values[0].c_str(), values[1].c_str(), + values[2].c_str()); + // we continue after error rather than exiting so that we can + // find more errors if any + } + + return s; + } + + // Differs from readrandomwriterandom in the following ways: + // (a) Uses MultiGet/MultiPut to read/write key values. Refer to those funcs. + // (b) Does deletes as well (per FLAGS_deletepercent) + // (c) In order to achieve high % of 'found' during lookups, and to do + // multiple writes (including puts and deletes) it uses upto + // FLAGS_numdistinct distinct keys instead of FLAGS_num distinct keys. + void RandomWithVerify(ThreadState* thread) { + ReadOptions options(FLAGS_verify_checksum, true); + RandomGenerator gen; + std::string value; + long found = 0; + int get_weight = 0; + int put_weight = 0; + int delete_weight = 0; + long gets_done = 0; + long puts_done = 0; + long deletes_done = 0; + // the number of iterations is the larger of read_ or write_ + for (long i = 0; i < readwrites_; i++) { + const int k = thread->rand.Next() % (FLAGS_numdistinct); + unique_ptr key = GenerateKeyFromInt(k); + if (get_weight == 0 && put_weight == 0 && delete_weight == 0) { + // one batch complated, reinitialize for next batch + get_weight = FLAGS_readwritepercent; + delete_weight = FLAGS_deletepercent; + put_weight = 100 - get_weight - delete_weight; + } + if (get_weight > 0) { + // do all the gets first + Status s = MultiGet(options, key.get(), &value); + if (!s.ok() && !s.IsNotFound()) { + fprintf(stderr, "get error: %s\n", s.ToString().c_str()); + // we continue after error rather than exiting so that we can + // find more errors if any + } else if (!s.IsNotFound()) { + found++; + } + get_weight--; + gets_done++; + } else if (put_weight > 0) { + // then do all the corresponding number of puts + // for all the gets we have done earlier + Status s = MultiPut(write_options_, key.get(), gen.Generate(value_size_)); + if (!s.ok()) { + fprintf(stderr, "multiput error: %s\n", s.ToString().c_str()); + exit(1); + } + put_weight--; + puts_done++; + } else if (delete_weight > 0) { + Status s = MultiDelete(write_options_, key.get()); + if (!s.ok()) { + fprintf(stderr, "multidelete error: %s\n", s.ToString().c_str()); + exit(1); + } + delete_weight--; + deletes_done++; + } + + thread->stats.FinishedSingleOp(db_); + } + char msg[100]; + snprintf(msg, sizeof(msg), "( get:%ld put:%ld del:%ld total:%ld found:%ld)", + gets_done, puts_done, deletes_done, readwrites_, found); + thread->stats.AddMessage(msg); + } + + // + // This is diffferent from ReadWhileWriting because it does not use + // an extra thread. + // + void ReadRandomWriteRandom(ThreadState* thread) { + ReadOptions options(FLAGS_verify_checksum, true); + RandomGenerator gen; + std::string value; + long found = 0; + int get_weight = 0; + int put_weight = 0; + long reads_done = 0; + long writes_done = 0; + // the number of iterations is the larger of read_ or write_ + for (long i = 0; i < readwrites_; i++) { + const int k = thread->rand.Next() % FLAGS_num; + unique_ptr key = GenerateKeyFromInt(k); + if (get_weight == 0 && put_weight == 0) { + // one batch complated, reinitialize for next batch + get_weight = FLAGS_readwritepercent; + put_weight = 100 - get_weight; + } + if (get_weight > 0) { + // do all the gets first + Status s = db_->Get(options, key.get(), &value); + if (!s.ok() && !s.IsNotFound()) { + fprintf(stderr, "get error: %s\n", s.ToString().c_str()); + // we continue after error rather than exiting so that we can + // find more errors if any + } else if (!s.IsNotFound()) { + found++; + } + + if (db_->Get(options, key.get(), &value).ok()) { + found++; + } + get_weight--; + reads_done++; + } else if (put_weight > 0) { + // then do all the corresponding number of puts + // for all the gets we have done earlier + Status s = db_->Put(write_options_, key.get(), gen.Generate(value_size_)); + if (!s.ok()) { + fprintf(stderr, "put error: %s\n", s.ToString().c_str()); + exit(1); + } + put_weight--; + writes_done++; + } + thread->stats.FinishedSingleOp(db_); + } + char msg[100]; + snprintf(msg, sizeof(msg), "( reads:%ld writes:%ld total:%ld found:%ld)", + reads_done, writes_done, readwrites_, found); + thread->stats.AddMessage(msg); + } + + void Compact(ThreadState* thread) { + db_->CompactRange(nullptr, nullptr); + } + + void PrintStats(const char* key) { + std::string stats; + if (!db_->GetProperty(key, &stats)) { + stats = "(failed)"; + } + fprintf(stdout, "\n%s\n", stats.c_str()); + } + + static void WriteToFile(void* arg, const char* buf, int n) { + reinterpret_cast(arg)->Append(Slice(buf, n)); + } + + void HeapProfile() { + char fname[100]; + snprintf(fname, sizeof(fname), "%s/heap-%04d", FLAGS_db, ++heap_counter_); + unique_ptr file; + Status s = FLAGS_env->NewWritableFile(fname, &file); + if (!s.ok()) { + fprintf(stderr, "%s\n", s.ToString().c_str()); + return; + } + bool ok = port::GetHeapProfile(WriteToFile, file.get()); + if (!ok) { + fprintf(stderr, "heap profiling not supported\n"); + FLAGS_env->DeleteFile(fname); + } + } +}; + +} // namespace leveldb + +int main(int argc, char** argv) { + FLAGS_write_buffer_size = leveldb::Options().write_buffer_size; + FLAGS_max_write_buffer_number = leveldb::Options().max_write_buffer_number; + FLAGS_open_files = leveldb::Options().max_open_files; + FLAGS_max_background_compactions = + leveldb::Options().max_background_compactions; + // Compression test code above refers to FLAGS_block_size + FLAGS_block_size = leveldb::Options().block_size; + std::string default_db_path; + + for (int i = 1; i < argc; i++) { + double d; + int n; + long l; + char junk; + char hdfsname[2048]; + if (leveldb::Slice(argv[i]).starts_with("--benchmarks=")) { + FLAGS_benchmarks = argv[i] + strlen("--benchmarks="); + } else if (sscanf(argv[i], "--compression_ratio=%lf%c", &d, &junk) == 1) { + FLAGS_compression_ratio = d; + } else if (sscanf(argv[i], "--histogram=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_histogram = n; + } else if (sscanf(argv[i], "--use_existing_db=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_use_existing_db = n; + } else if (sscanf(argv[i], "--num=%ld%c", &l, &junk) == 1) { + FLAGS_num = l; + } else if (sscanf(argv[i], "--numdistinct=%ld%c", &l, &junk) == 1) { + FLAGS_numdistinct = l; + } else if (sscanf(argv[i], "--reads=%d%c", &n, &junk) == 1) { + FLAGS_reads = n; + } else if (sscanf(argv[i], "--read_range=%d%c", &n, &junk) == 1) { + FLAGS_read_range = n; + } else if (sscanf(argv[i], "--seed=%ld%c", &l, &junk) == 1) { + FLAGS_seed = l; + } else if (sscanf(argv[i], "--threads=%d%c", &n, &junk) == 1) { + FLAGS_threads = n; + } else if (sscanf(argv[i], "--value_size=%d%c", &n, &junk) == 1) { + FLAGS_value_size = n; + } else if (sscanf(argv[i], "--key_size=%d%c", &n, &junk) == 1) { + if (MAX_KEY_SIZE < n) { + fprintf(stderr, "key_size should not be larger than %d\n", MAX_KEY_SIZE); + exit(1); + } else { + FLAGS_key_size = n; + } + } else if (sscanf(argv[i], "--write_buffer_size=%d%c", &n, &junk) == 1) { + FLAGS_write_buffer_size = n; + } else if (sscanf(argv[i], "--max_write_buffer_number=%d%c", &n, &junk) == 1) { + FLAGS_max_write_buffer_number = n; + } else if (sscanf(argv[i], "--max_background_compactions=%d%c", &n, &junk) == 1) { + FLAGS_max_background_compactions = n; + } else if (sscanf(argv[i], "--cache_size=%ld%c", &l, &junk) == 1) { + FLAGS_cache_size = l; + } else if (sscanf(argv[i], "--block_size=%d%c", &n, &junk) == 1) { + FLAGS_block_size = n; + } else if (sscanf(argv[i], "--cache_numshardbits=%d%c", &n, &junk) == 1) { + if (n < 20) { + FLAGS_cache_numshardbits = n; + } else { + fprintf(stderr, "The cache cannot be sharded into 2**%d pieces\n", n); + exit(1); + } + } else if (sscanf(argv[i], "--table_cache_numshardbits=%d%c", + &n, &junk) == 1) { + if (n <= 0 || n > 20) { + fprintf(stderr, "The cache cannot be sharded into 2**%d pieces\n", n); + exit(1); + } + FLAGS_table_cache_numshardbits = n; + } else if (sscanf(argv[i], "--bloom_bits=%d%c", &n, &junk) == 1) { + FLAGS_bloom_bits = n; + } else if (sscanf(argv[i], "--open_files=%d%c", &n, &junk) == 1) { + FLAGS_open_files = n; + } else if (strncmp(argv[i], "--db=", 5) == 0) { + FLAGS_db = argv[i] + 5; + } else if (sscanf(argv[i], "--verify_checksum=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_verify_checksum = n; + } else if (sscanf(argv[i], "--bufferedio=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + useOsBuffer = n; + } else if (sscanf(argv[i], "--mmap_read=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + useMmapRead = n; + } else if (sscanf(argv[i], "--mmap_write=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + useMmapWrite = n; + } else if (sscanf(argv[i], "--readahead=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + useFsReadAhead = n; + } else if (sscanf(argv[i], "--statistics=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + if (n == 1) { + dbstats = new leveldb::DBStatistics(); + FLAGS_statistics = true; + } + } else if (sscanf(argv[i], "--writes=%d%c", &n, &junk) == 1) { + FLAGS_writes = n; + } else if (sscanf(argv[i], "--sync=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_sync = n; + } else if (sscanf(argv[i], "--readwritepercent=%d%c", &n, &junk) == 1 && + n > 0 && n < 100) { + FLAGS_readwritepercent = n; + } else if (sscanf(argv[i], "--deletepercent=%d%c", &n, &junk) == 1 && + n > 0 && n < 100) { + FLAGS_deletepercent = n; + } else if (sscanf(argv[i], "--disable_data_sync=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_disable_data_sync = n; + } else if (sscanf(argv[i], "--use_fsync=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_use_fsync = n; + } else if (sscanf(argv[i], "--disable_wal=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_disable_wal = n; + } else if (sscanf(argv[i], "--hdfs=%s", hdfsname) == 1) { + FLAGS_env = new leveldb::HdfsEnv(hdfsname); + } else if (sscanf(argv[i], "--num_levels=%d%c", + &n, &junk) == 1) { + FLAGS_num_levels = n; + } else if (sscanf(argv[i], "--target_file_size_base=%d%c", + &n, &junk) == 1) { + FLAGS_target_file_size_base = n; + } else if ( sscanf(argv[i], "--target_file_size_multiplier=%d%c", + &n, &junk) == 1) { + FLAGS_target_file_size_multiplier = n; + } else if ( + sscanf(argv[i], "--max_bytes_for_level_base=%ld%c", &l, &junk) == 1) { + FLAGS_max_bytes_for_level_base = l; + } else if (sscanf(argv[i], "--max_bytes_for_level_multiplier=%d%c", + &n, &junk) == 1) { + FLAGS_max_bytes_for_level_multiplier = n; + } else if (sscanf(argv[i],"--level0_stop_writes_trigger=%d%c", + &n, &junk) == 1) { + FLAGS_level0_stop_writes_trigger = n; + } else if (sscanf(argv[i],"--level0_slowdown_writes_trigger=%d%c", + &n, &junk) == 1) { + FLAGS_level0_slowdown_writes_trigger = n; + } else if (sscanf(argv[i],"--level0_file_num_compaction_trigger=%d%c", + &n, &junk) == 1) { + FLAGS_level0_file_num_compaction_trigger = n; + } else if (strncmp(argv[i], "--compression_type=", 19) == 0) { + const char* ctype = argv[i] + 19; + if (!strcasecmp(ctype, "none")) + FLAGS_compression_type = leveldb::kNoCompression; + else if (!strcasecmp(ctype, "snappy")) + FLAGS_compression_type = leveldb::kSnappyCompression; + else if (!strcasecmp(ctype, "zlib")) + FLAGS_compression_type = leveldb::kZlibCompression; + else if (!strcasecmp(ctype, "bzip2")) + FLAGS_compression_type = leveldb::kBZip2Compression; + else { + fprintf(stdout, "Cannot parse %s\n", argv[i]); + } + } else if (sscanf(argv[i], "--min_level_to_compress=%d%c", &n, &junk) == 1 + && n >= 0) { + FLAGS_min_level_to_compress = n; + } else if (sscanf(argv[i], "--disable_seek_compaction=%d%c", &n, &junk) == 1 + && (n == 0 || n == 1)) { + FLAGS_disable_seek_compaction = n; + } else if (sscanf(argv[i], "--delete_obsolete_files_period_micros=%ld%c", + &l, &junk) == 1) { + FLAGS_delete_obsolete_files_period_micros = l; + } else if (sscanf(argv[i], "--stats_interval=%d%c", &n, &junk) == 1 && + n >= 0 && n < 2000000000) { + FLAGS_stats_interval = n; + } else if (sscanf(argv[i], "--stats_per_interval=%d%c", &n, &junk) == 1 + && (n == 0 || n == 1)) { + FLAGS_stats_per_interval = n; + } else if (sscanf(argv[i], "--rate_limit=%lf%c", &d, &junk) == 1 && + d > 1.0) { + FLAGS_rate_limit = d; + } else if (sscanf(argv[i], + "--rate_limit_delay_milliseconds=%d%c", &n, &junk) == 1 + && n > 0) { + FLAGS_rate_limit_delay_milliseconds = n; + } else if (sscanf(argv[i], "--readonly=%d%c", &n, &junk) == 1 && + (n == 0 || n ==1 )) { + FLAGS_read_only = n; + } else if (sscanf(argv[i], "--max_grandparent_overlap_factor=%d%c", + &n, &junk) == 1) { + FLAGS_max_grandparent_overlap_factor = n; + } else if (sscanf(argv[i], "--disable_auto_compactions=%d%c", + &n, &junk) == 1 && (n == 0 || n ==1)) { + FLAGS_disable_auto_compactions = n; + } else if (sscanf(argv[i], "--source_compaction_factor=%d%c", + &n, &junk) == 1 && n > 0) { + FLAGS_source_compaction_factor = n; + } else if (sscanf(argv[i], "--wal_ttl=%d%c", &n, &junk) == 1) { + FLAGS_WAL_ttl_seconds = static_cast(n); + } else { + fprintf(stderr, "Invalid flag '%s'\n", argv[i]); + exit(1); + } + } + + // The number of background threads should be at least as much the + // max number of concurrent compactions. + FLAGS_env->SetBackgroundThreads(FLAGS_max_background_compactions); + + // Choose a location for the test database if none given with --db= + if (FLAGS_db == nullptr) { + leveldb::Env::Default()->GetTestDirectory(&default_db_path); + default_db_path += "/dbbench"; + FLAGS_db = default_db_path.c_str(); + } + + leveldb::Benchmark benchmark; + benchmark.Run(); + return 0; +} diff --git a/db/db_filesnapshot.cc b/db/db_filesnapshot.cc new file mode 100644 index 00000000..43e0065f --- /dev/null +++ b/db/db_filesnapshot.cc @@ -0,0 +1,67 @@ +// Copyright (c) 2012 Facebook. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "db/db_impl.h" +#include "db/filename.h" +#include +#include +#include "db/version_set.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "port/port.h" +#include "util/mutexlock.h" + +namespace leveldb { + +Status DBImpl::DisableFileDeletions() { + MutexLock l(&mutex_); + disable_delete_obsolete_files_ = true; + return Status::OK(); +} + +Status DBImpl::EnableFileDeletions() { + MutexLock l(&mutex_); + disable_delete_obsolete_files_ = false; + return Status::OK(); +} + +Status DBImpl::GetLiveFiles(std::vector& ret, + uint64_t* manifest_file_size) { + + *manifest_file_size = 0; + + // flush all dirty data to disk. + Status status = Flush(FlushOptions()); + if (!status.ok()) { + Log(options_.info_log, "Cannot Flush data %s\n", + status.ToString().c_str()); + return status; + } + + MutexLock l(&mutex_); + + // Make a set of all of the live *.sst files + std::set live; + versions_->AddLiveFilesCurrentVersion(&live); + + ret.resize(live.size() + 2); //*.sst + CURRENT + MANIFEST + + // create names of the live files. The names are not absolute + // paths, instead they are relative to dbname_; + std::set::iterator it = live.begin(); + for (unsigned int i = 0; i < live.size(); i++, it++) { + ret[i] = TableFileName("", *it); + } + + ret[live.size()] = CurrentFileName(""); + ret[live.size()+1] = DescriptorFileName("", + versions_->ManifestFileNumber()); + + // find length of manifest file while holding the mutex lock + *manifest_file_size = versions_->ManifestFileSize(); + + return Status::OK(); +} + +} diff --git a/db/db_impl.cc b/db/db_impl.cc new file mode 100644 index 00000000..e4443c75 --- /dev/null +++ b/db/db_impl.cc @@ -0,0 +1,2435 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/db_impl.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "db/builder.h" +#include "db/db_iter.h" +#include "db/dbformat.h" +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "db/memtable.h" +#include "db/memtablelist.h" +#include "db/table_cache.h" +#include "db/version_set.h" +#include "db/write_batch_internal.h" +#include "db/transaction_log_iterator_impl.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/statistics.h" +#include "leveldb/status.h" +#include "leveldb/table.h" +#include "leveldb/table_builder.h" +#include "port/port.h" +#include "table/block.h" +#include "table/merger.h" +#include "table/two_level_iterator.h" +#include "util/auto_roll_logger.h" +#include "util/build_version.h" +#include "util/coding.h" +#include "util/logging.h" +#include "util/mutexlock.h" +#include "util/stop_watch.h" + +namespace leveldb { + +void dumpLeveldbBuildVersion(Logger * log); + +// Information kept for every waiting writer +struct DBImpl::Writer { + Status status; + WriteBatch* batch; + bool sync; + bool disableWAL; + bool done; + port::CondVar cv; + + explicit Writer(port::Mutex* mu) : cv(mu) { } +}; + +struct DBImpl::CompactionState { + Compaction* const compaction; + + // If there were two snapshots with seq numbers s1 and + // s2 and s1 < s2, and if we find two instances of a key k1 then lies + // entirely within s1 and s2, then the earlier version of k1 can be safely + // deleted because that version is not visible in any snapshot. + std::vector existing_snapshots; + + // Files produced by compaction + struct Output { + uint64_t number; + uint64_t file_size; + InternalKey smallest, largest; + }; + std::vector outputs; + std::list allocated_file_numbers; + + // State kept for output being generated + unique_ptr outfile; + unique_ptr builder; + + uint64_t total_bytes; + + Output* current_output() { return &outputs[outputs.size()-1]; } + + explicit CompactionState(Compaction* c) + : compaction(c), + total_bytes(0) { + } +}; + +struct DBImpl::DeletionState { + + // the set of all live files that cannot be deleted + std::set live; + + // a list of all siles that exists in the db directory + std::vector allfiles; + + // the current filenumber, lognumber and prevlognumber + // that corresponds to the set of files in 'live'. + uint64_t filenumber, lognumber, prevlognumber; + + // the list of all files to be evicted from the table cahce + std::vector files_to_evict; +}; + +// Fix user-supplied options to be reasonable +template +static void ClipToRange(T* ptr, V minvalue, V maxvalue) { + if (static_cast(*ptr) > maxvalue) *ptr = maxvalue; + if (static_cast(*ptr) < minvalue) *ptr = minvalue; +} +Options SanitizeOptions(const std::string& dbname, + const InternalKeyComparator* icmp, + const InternalFilterPolicy* ipolicy, + const Options& src) { + Options result = src; + result.comparator = icmp; + result.filter_policy = (src.filter_policy != nullptr) ? ipolicy : nullptr; + ClipToRange(&result.max_open_files, 20, 1000000); + ClipToRange(&result.write_buffer_size, 64<<10, 1<<30); + ClipToRange(&result.block_size, 1<<10, 4<<20); + if (result.info_log == nullptr) { + Status s = CreateLoggerFromOptions(dbname, result.db_log_dir, src.env, + result, &result.info_log); + if (!s.ok()) { + // No place suitable for logging + result.info_log = nullptr; + } + } + if (result.block_cache == nullptr && !result.no_block_cache) { + result.block_cache = NewLRUCache(8 << 20); + } + result.compression_per_level = src.compression_per_level; + return result; +} + +DBImpl::DBImpl(const Options& options, const std::string& dbname) + : env_(options.env), + dbname_(dbname), + internal_comparator_(options.comparator), + options_(SanitizeOptions( + dbname, &internal_comparator_, &internal_filter_policy_, options)), + internal_filter_policy_(options.filter_policy), + owns_info_log_(options_.info_log != options.info_log), + db_lock_(nullptr), + shutting_down_(nullptr), + bg_cv_(&mutex_), + mem_(new MemTable(internal_comparator_, NumberLevels())), + logfile_number_(0), + tmp_batch_(new WriteBatch), + bg_compaction_scheduled_(0), + bg_logstats_scheduled_(false), + manual_compaction_(nullptr), + logger_(nullptr), + disable_delete_obsolete_files_(false), + delete_obsolete_files_last_run_(0), + stall_level0_slowdown_(0), + stall_memtable_compaction_(0), + stall_level0_num_files_(0), + started_at_(options.env->NowMicros()), + flush_on_destroy_(false), + delayed_writes_(0), + last_flushed_sequence_(0) { + + mem_->Ref(); + + env_->GetAbsolutePath(dbname, &db_absolute_path_); + stats_ = new CompactionStats[options.num_levels]; + + stall_leveln_slowdown_.resize(options.num_levels); + for (int i = 0; i < options.num_levels; ++i) + stall_leveln_slowdown_[i] = 0; + + // Reserve ten files or so for other uses and give the rest to TableCache. + const int table_cache_size = options_.max_open_files - 10; + table_cache_.reset(new TableCache(dbname_, &options_, table_cache_size)); + + versions_.reset(new VersionSet(dbname_, &options_, table_cache_.get(), + &internal_comparator_)); + + dumpLeveldbBuildVersion(options_.info_log.get()); + options_.Dump(options_.info_log.get()); + +#ifdef USE_SCRIBE + logger_ = new ScribeLogger("localhost", 1456); +#endif + + char name[100]; + Status st = env_->GetHostName(name, 100L); + if(st.ok()) { + host_name_ = name; + } else { + Log(options_.info_log, "Can't get hostname, use localhost as host name."); + host_name_ = "localhost"; + } + last_log_ts = 0; + +} + +DBImpl::~DBImpl() { + // Wait for background work to finish + if (flush_on_destroy_) { + FlushMemTable(FlushOptions()); + } + mutex_.Lock(); + shutting_down_.Release_Store(this); // Any non-nullptr value is ok + while (bg_compaction_scheduled_ || bg_logstats_scheduled_) { + bg_cv_.Wait(); + } + mutex_.Unlock(); + + if (db_lock_ != nullptr) { + env_->UnlockFile(db_lock_); + } + + if (mem_ != nullptr) mem_->Unref(); + imm_.UnrefAll(); + delete tmp_batch_; + delete[] stats_; + + delete logger_; +} + +// Do not flush and close database elegantly. Simulate a crash. +void DBImpl::TEST_Destroy_DBImpl() { + // ensure that no new memtable flushes can occur + flush_on_destroy_ = false; + + // wait till all background compactions are done. + mutex_.Lock(); + while (bg_compaction_scheduled_ || bg_logstats_scheduled_) { + bg_cv_.Wait(); + } + + // Prevent new compactions from occuring. + const int LargeNumber = 10000000; + bg_compaction_scheduled_ += LargeNumber; + mutex_.Unlock(); + + // force release the lock file. + if (db_lock_ != nullptr) { + env_->UnlockFile(db_lock_); + } + + log_.reset(); + versions_.reset(); + table_cache_.reset(); +} + +uint64_t DBImpl::TEST_Current_Manifest_FileNo() { + return versions_->ManifestFileNumber(); +} + +Status DBImpl::NewDB() { + VersionEdit new_db(NumberLevels()); + new_db.SetComparatorName(user_comparator()->Name()); + new_db.SetLogNumber(0); + new_db.SetNextFile(2); + new_db.SetLastSequence(0); + + const std::string manifest = DescriptorFileName(dbname_, 1); + unique_ptr file; + Status s = env_->NewWritableFile(manifest, &file); + if (!s.ok()) { + return s; + } + file->SetPreallocationBlockSize(options_.manifest_preallocation_size); + { + log::Writer log(std::move(file)); + std::string record; + new_db.EncodeTo(&record); + s = log.AddRecord(record); + } + if (s.ok()) { + // Make "CURRENT" file that points to the new manifest file. + s = SetCurrentFile(env_, dbname_, 1); + } else { + env_->DeleteFile(manifest); + } + return s; +} + +void DBImpl::MaybeIgnoreError(Status* s) const { + if (s->ok() || options_.paranoid_checks) { + // No change needed + } else { + Log(options_.info_log, "Ignoring error %s", s->ToString().c_str()); + *s = Status::OK(); + } +} + +const Status DBImpl::CreateArchivalDirectory() { + if (options_.WAL_ttl_seconds > 0) { + std::string archivalPath = ArchivalDirectory(dbname_); + return env_->CreateDirIfMissing(archivalPath); + } + return Status::OK(); +} + +// Returns the list of live files in 'live' and the list +// of all files in the filesystem in 'allfiles'. +void DBImpl::FindObsoleteFiles(DeletionState& deletion_state) { + mutex_.AssertHeld(); + + // if deletion is disabled, do nothing + if (disable_delete_obsolete_files_) { + return; + } + + // This method is costly when the number of files is large. + // Do not allow it to trigger more often than once in + // delete_obsolete_files_period_micros. + if (options_.delete_obsolete_files_period_micros != 0) { + const uint64_t now_micros = env_->NowMicros(); + if (delete_obsolete_files_last_run_ + + options_.delete_obsolete_files_period_micros > now_micros) { + return; + } + delete_obsolete_files_last_run_ = now_micros; + } + + // Make a set of all of the live files + deletion_state.live = pending_outputs_; + versions_->AddLiveFiles(&deletion_state.live); + + // set of all files in the directory + env_->GetChildren(dbname_, &deletion_state.allfiles); // Ignore errors + + // store the current filenum, lognum, etc + deletion_state.filenumber = versions_->ManifestFileNumber(); + deletion_state.lognumber = versions_->LogNumber(); + deletion_state.prevlognumber = versions_->PrevLogNumber(); +} + +// Diffs the files listed in filenames and those that do not +// belong to live files are posibly removed. If the removed file +// is a sst file, then it returns the file number in files_to_evict. +// It is not necesary to hold the mutex when invoking this method. +void DBImpl::PurgeObsoleteFiles(DeletionState& state) { + uint64_t number; + FileType type; + std::vector old_log_files; + + for (size_t i = 0; i < state.allfiles.size(); i++) { + if (ParseFileName(state.allfiles[i], &number, &type)) { + bool keep = true; + switch (type) { + case kLogFile: + keep = ((number >= state.lognumber) || + (number == state.prevlognumber)); + break; + case kDescriptorFile: + // Keep my manifest file, and any newer incarnations' + // (in case there is a race that allows other incarnations) + keep = (number >= state.filenumber); + break; + case kTableFile: + keep = (state.live.find(number) != state.live.end()); + break; + case kTempFile: + // Any temp files that are currently being written to must + // be recorded in pending_outputs_, which is inserted into "live" + keep = (state.live.find(number) != state.live.end()); + break; + case kInfoLogFile: + keep = true; + if (number != 0) { + old_log_files.push_back(state.allfiles[i]); + } + break; + case kCurrentFile: + case kDBLockFile: + case kMetaDatabase: + keep = true; + break; + } + + if (!keep) { + if (type == kTableFile) { + // record the files to be evicted from the cache + state.files_to_evict.push_back(number); + } + Log(options_.info_log, "Delete type=%d #%lld\n", + int(type), + static_cast(number)); + if (type == kLogFile && options_.WAL_ttl_seconds > 0) { + Status st = env_->RenameFile(LogFileName(dbname_, number), + ArchivedLogFileName(dbname_, number)); + if (!st.ok()) { + Log(options_.info_log, "RenameFile type=%d #%lld FAILED\n", + int(type), + static_cast(number)); + } + } else { + Status st = env_->DeleteFile(dbname_ + "/" + state.allfiles[i]); + if(!st.ok()) { + Log(options_.info_log, "Delete type=%d #%lld FAILED\n", + int(type), + static_cast(number)); + } + } + } + } + } + + // Delete old log files. + size_t old_log_file_count = old_log_files.size(); + // NOTE: Currently we only support log purge when options_.db_log_dir is + // located in `dbname` directory. + if (old_log_file_count >= options_.keep_log_file_num && + options_.db_log_dir.empty()) { + std::sort(old_log_files.begin(), old_log_files.end()); + size_t end = old_log_file_count - options_.keep_log_file_num; + for (int i = 0; i <= end; i++) { + std::string& to_delete = old_log_files.at(i); + // Log(options_.info_log, "Delete type=%d %s\n", + // int(kInfoLogFile), to_delete.c_str()); + env_->DeleteFile(dbname_ + "/" + to_delete); + } + } +} + +void DBImpl::EvictObsoleteFiles(DeletionState& state) { + for (unsigned int i = 0; i < state.files_to_evict.size(); i++) { + table_cache_->Evict(state.files_to_evict[i]); + } +} + +void DBImpl::DeleteObsoleteFiles() { + mutex_.AssertHeld(); + DeletionState deletion_state; + FindObsoleteFiles(deletion_state); + PurgeObsoleteFiles(deletion_state); + EvictObsoleteFiles(deletion_state); + PurgeObsoleteWALFiles(); +} + +void DBImpl::PurgeObsoleteWALFiles() { + if (options_.WAL_ttl_seconds != ULONG_MAX && options_.WAL_ttl_seconds > 0) { + std::vector WALFiles; + std::string archivalDir = ArchivalDirectory(dbname_); + env_->GetChildren(archivalDir, &WALFiles); + int64_t currentTime; + const Status status = env_->GetCurrentTime(¤tTime); + assert(status.ok()); + for (std::vector::iterator it = WALFiles.begin(); + it != WALFiles.end(); + ++it) { + + uint64_t fileMTime; + const std::string filePath = archivalDir + "/" + *it; + const Status s = env_->GetFileModificationTime(filePath, &fileMTime); + if (s.ok()) { + if (status.ok() && + (currentTime - fileMTime > options_.WAL_ttl_seconds)) { + Status delStatus = env_->DeleteFile(filePath); + if (!delStatus.ok()) { + Log(options_.info_log, + "Failed Deleting a WAL file Error : i%s", + delStatus.ToString().c_str()); + } + } + } // Ignore errors. + } + } +} + +// If externalTable is set, then apply recovered transactions +// to that table. This is used for readonly mode. +Status DBImpl::Recover(VersionEdit* edit, MemTable* external_table, + bool error_if_log_file_exist) { + mutex_.AssertHeld(); + + assert(db_lock_ == nullptr); + if (!external_table) { + // We call CreateDirIfMissing() as the directory may already exist (if we + // are reopening a DB), when this happens we don't want creating the + // directory to cause an error. However, we need to check if creating the + // directory fails or else we may get an obscure message about the lock + // file not existing. One real-world example of this occurring is if + // env->CreateDirIfMissing() doesn't create intermediate directories, e.g. + // when dbname_ is "dir/db" but when "dir" doesn't exist. + Status s = env_->CreateDirIfMissing(dbname_); + if (!s.ok()) { + return s; + } + + s = env_->LockFile(LockFileName(dbname_), &db_lock_); + if (!s.ok()) { + return s; + } + + if (!env_->FileExists(CurrentFileName(dbname_))) { + if (options_.create_if_missing) { + s = NewDB(); + if (!s.ok()) { + return s; + } + } else { + return Status::InvalidArgument( + dbname_, "does not exist (create_if_missing is false)"); + } + } else { + if (options_.error_if_exists) { + return Status::InvalidArgument( + dbname_, "exists (error_if_exists is true)"); + } + } + } + + Status s = versions_->Recover(); + if (s.ok()) { + SequenceNumber max_sequence(0); + + // Recover from all newer log files than the ones named in the + // descriptor (new log files may have been added by the previous + // incarnation without registering them in the descriptor). + // + // Note that PrevLogNumber() is no longer used, but we pay + // attention to it in case we are recovering a database + // produced by an older version of leveldb. + const uint64_t min_log = versions_->LogNumber(); + const uint64_t prev_log = versions_->PrevLogNumber(); + std::vector filenames; + s = env_->GetChildren(dbname_, &filenames); + if (!s.ok()) { + return s; + } + uint64_t number; + FileType type; + std::vector logs; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type) + && type == kLogFile + && ((number >= min_log) || (number == prev_log))) { + logs.push_back(number); + } + } + + if (logs.size() > 0 && error_if_log_file_exist) { + return Status::Corruption("" + "The db was opened in readonly mode with error_if_log_file_exist" + "flag but a log file already exists"); + } + + // Recover in the order in which the logs were generated + std::sort(logs.begin(), logs.end()); + for (size_t i = 0; i < logs.size(); i++) { + s = RecoverLogFile(logs[i], edit, &max_sequence, external_table); + // The previous incarnation may not have written any MANIFEST + // records after allocating this log number. So we manually + // update the file number allocation counter in VersionSet. + versions_->MarkFileNumberUsed(logs[i]); + } + // This could be the last_flushed_sequence as the next sequences will be + // greater than this. + last_flushed_sequence_ = max_sequence; + + if (s.ok()) { + if (versions_->LastSequence() < max_sequence) { + versions_->SetLastSequence(max_sequence); + } + } + } + + return s; +} + +Status DBImpl::RecoverLogFile(uint64_t log_number, + VersionEdit* edit, + SequenceNumber* max_sequence, + MemTable* external_table) { + struct LogReporter : public log::Reader::Reporter { + Env* env; + Logger* info_log; + const char* fname; + Status* status; // nullptr if options_.paranoid_checks==false + virtual void Corruption(size_t bytes, const Status& s) { + Log(info_log, "%s%s: dropping %d bytes; %s", + (this->status == nullptr ? "(ignoring error) " : ""), + fname, static_cast(bytes), s.ToString().c_str()); + if (this->status != nullptr && this->status->ok()) *this->status = s; + } + }; + + mutex_.AssertHeld(); + + // Open the log file + std::string fname = LogFileName(dbname_, log_number); + unique_ptr file; + Status status = env_->NewSequentialFile(fname, &file); + if (!status.ok()) { + MaybeIgnoreError(&status); + return status; + } + + // Create the log reader. + LogReporter reporter; + reporter.env = env_; + reporter.info_log = options_.info_log.get(); + reporter.fname = fname.c_str(); + reporter.status = (options_.paranoid_checks ? &status : nullptr); + // We intentially make log::Reader do checksumming even if + // paranoid_checks==false so that corruptions cause entire commits + // to be skipped instead of propagating bad information (like overly + // large sequence numbers). + log::Reader reader(std::move(file), &reporter, true/*checksum*/, + 0/*initial_offset*/); + Log(options_.info_log, "Recovering log #%llu", + (unsigned long long) log_number); + + // Read all the records and add to a memtable + std::string scratch; + Slice record; + WriteBatch batch; + MemTable* mem = nullptr; + if (external_table) { + mem = external_table; + } + while (reader.ReadRecord(&record, &scratch) && + status.ok()) { + if (record.size() < 12) { + reporter.Corruption( + record.size(), Status::Corruption("log record too small")); + continue; + } + WriteBatchInternal::SetContents(&batch, record); + + if (mem == nullptr) { + mem = new MemTable(internal_comparator_, NumberLevels()); + mem->Ref(); + } + status = WriteBatchInternal::InsertInto(&batch, mem); + MaybeIgnoreError(&status); + if (!status.ok()) { + break; + } + const SequenceNumber last_seq = + WriteBatchInternal::Sequence(&batch) + + WriteBatchInternal::Count(&batch) - 1; + if (last_seq > *max_sequence) { + *max_sequence = last_seq; + } + + if (!external_table && + mem->ApproximateMemoryUsage() > options_.write_buffer_size) { + status = WriteLevel0TableForRecovery(mem, edit); + if (!status.ok()) { + // Reflect errors immediately so that conditions like full + // file-systems cause the DB::Open() to fail. + break; + } + mem->Unref(); + mem = nullptr; + } + } + + if (status.ok() && mem != nullptr && !external_table) { + status = WriteLevel0TableForRecovery(mem, edit); + // Reflect errors immediately so that conditions like full + // file-systems cause the DB::Open() to fail. + } + + if (mem != nullptr && !external_table) mem->Unref(); + return status; +} + +Status DBImpl::WriteLevel0TableForRecovery(MemTable* mem, VersionEdit* edit) { + mutex_.AssertHeld(); + const uint64_t start_micros = env_->NowMicros(); + FileMetaData meta; + meta.number = versions_->NewFileNumber(); + pending_outputs_.insert(meta.number); + Iterator* iter = mem->NewIterator(); + const SequenceNumber newest_snapshot = snapshots_.GetNewest(); + const SequenceNumber earliest_seqno_in_memtable = + mem->GetFirstSequenceNumber(); + Log(options_.info_log, "Level-0 table #%llu: started", + (unsigned long long) meta.number); + + Status s; + { + mutex_.Unlock(); + s = BuildTable(dbname_, env_, options_, table_cache_.get(), iter, &meta, + user_comparator(), newest_snapshot, + earliest_seqno_in_memtable); + mutex_.Lock(); + } + + Log(options_.info_log, "Level-0 table #%llu: %lld bytes %s", + (unsigned long long) meta.number, + (unsigned long long) meta.file_size, + s.ToString().c_str()); + delete iter; + + pending_outputs_.erase(meta.number); + + // Note that if file_size is zero, the file has been deleted and + // should not be added to the manifest. + int level = 0; + if (s.ok() && meta.file_size > 0) { + edit->AddFile(level, meta.number, meta.file_size, + meta.smallest, meta.largest); + } + + CompactionStats stats; + stats.micros = env_->NowMicros() - start_micros; + stats.bytes_written = meta.file_size; + stats.files_out_levelnp1 = 1; + stats_[level].Add(stats); + return s; +} + + +Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit, + uint64_t* filenumber) { + mutex_.AssertHeld(); + const uint64_t start_micros = env_->NowMicros(); + FileMetaData meta; + meta.number = versions_->NewFileNumber(); + *filenumber = meta.number; + pending_outputs_.insert(meta.number); + Iterator* iter = mem->NewIterator(); + const SequenceNumber newest_snapshot = snapshots_.GetNewest(); + const SequenceNumber earliest_seqno_in_memtable = + mem->GetFirstSequenceNumber(); + Log(options_.info_log, "Level-0 flush table #%llu: started", + (unsigned long long) meta.number); + + Version* base = versions_->current(); + base->Ref(); + Status s; + { + mutex_.Unlock(); + s = BuildTable(dbname_, env_, options_, table_cache_.get(), iter, &meta, + user_comparator(), newest_snapshot, + earliest_seqno_in_memtable); + mutex_.Lock(); + } + base->Unref(); + + Log(options_.info_log, "Level-0 flush table #%llu: %lld bytes %s", + (unsigned long long) meta.number, + (unsigned long long) meta.file_size, + s.ToString().c_str()); + delete iter; + + // re-acquire the most current version + base = versions_->current(); + + // There could be multiple threads writing to its own level-0 file. + // The pending_outputs cannot be cleared here, otherwise this newly + // created file might not be considered as a live-file by another + // compaction thread that is concurrently deleting obselete files. + // The pending_outputs can be cleared only after the new version is + // committed so that other threads can recognize this file as a + // valid one. + // pending_outputs_.erase(meta.number); + + // Note that if file_size is zero, the file has been deleted and + // should not be added to the manifest. + int level = 0; + if (s.ok() && meta.file_size > 0) { + const Slice min_user_key = meta.smallest.user_key(); + const Slice max_user_key = meta.largest.user_key(); + // if we have more than 1 background thread, then we cannot + // insert files directly into higher levels because some other + // threads could be concurrently producing compacted files for + // that key range. + if (base != nullptr && options_.max_background_compactions <= 1) { + level = base->PickLevelForMemTableOutput(min_user_key, max_user_key); + } + edit->AddFile(level, meta.number, meta.file_size, + meta.smallest, meta.largest); + } + + CompactionStats stats; + stats.micros = env_->NowMicros() - start_micros; + stats.bytes_written = meta.file_size; + stats_[level].Add(stats); + return s; +} + +Status DBImpl::CompactMemTable(bool* madeProgress) { + mutex_.AssertHeld(); + assert(imm_.size() != 0); + + if (!imm_.IsFlushPending()) { + Log(options_.info_log, "Memcompaction already in progress"); + Status s = Status::IOError("Memcompaction already in progress"); + return s; + } + + // Save the contents of the earliest memtable as a new Table + // This will release and re-acquire the mutex. + uint64_t file_number; + MemTable* m = imm_.PickMemtableToFlush(); + if (m == nullptr) { + Log(options_.info_log, "Nothing in memstore to flush"); + Status s = Status::IOError("Nothing in memstore to flush"); + return s; + } + + // record the logfile_number_ before we release the mutex + VersionEdit* edit = m->GetEdits(); + edit->SetPrevLogNumber(0); + edit->SetLogNumber(logfile_number_); // Earlier logs no longer needed + + Status s = WriteLevel0Table(m, edit, &file_number); + + if (s.ok() && shutting_down_.Acquire_Load()) { + s = Status::IOError("Deleting DB during memtable compaction"); + } + + // Replace immutable memtable with the generated Table + s = imm_.InstallMemtableFlushResults( + m, versions_.get(), s, &mutex_, options_.info_log.get(), + file_number, pending_outputs_); + + if (s.ok()) { + if (madeProgress) { + *madeProgress = 1; + } + MaybeScheduleLogDBDeployStats(); + // we could have deleted obsolete files here, but it is not + // absolutely necessary because it could be also done as part + // of other background compaction + } + return s; +} + +void DBImpl::CompactRange(const Slice* begin, const Slice* end) { + int max_level_with_files = 1; + { + MutexLock l(&mutex_); + Version* base = versions_->current(); + for (int level = 1; level < NumberLevels(); level++) { + if (base->OverlapInLevel(level, begin, end)) { + max_level_with_files = level; + } + } + } + TEST_CompactMemTable(); // TODO(sanjay): Skip if memtable does not overlap + for (int level = 0; level < max_level_with_files; level++) { + TEST_CompactRange(level, begin, end); + } +} + +int DBImpl::NumberLevels() { + return options_.num_levels; +} + +int DBImpl::MaxMemCompactionLevel() { + return options_.max_mem_compaction_level; +} + +int DBImpl::Level0StopWriteTrigger() { + return options_.level0_stop_writes_trigger; +} + +Status DBImpl::Flush(const FlushOptions& options) { + Status status = FlushMemTable(options); + return status; +} + +SequenceNumber DBImpl::GetLatestSequenceNumber() { + return versions_->LastSequence(); +} + +Status DBImpl::GetUpdatesSince(SequenceNumber seq, + unique_ptr* iter) { + + // Get All Log Files. + // Sort Files + // Get the first entry from each file. + // Do binary search and open files and find the seq number. + + std::vector walFiles; + // list wal files in main db dir. + Status s = ListAllWALFiles(dbname_, &walFiles, kAliveLogFile); + if (!s.ok()) { + return s; + } + // list wal files in archive dir. + std::string archivedir = ArchivalDirectory(dbname_); + if (env_->FileExists(archivedir)) { + s = ListAllWALFiles(archivedir, &walFiles, kArchivedLogFile); + if (!s.ok()) { + return s; + } + } + + if (walFiles.empty()) { + return Status::IOError(" NO WAL Files present in the db"); + } + // std::shared_ptr would have been useful here. + + std::vector* probableWALFiles = new std::vector(); + s = FindProbableWALFiles(&walFiles, probableWALFiles, seq); + if (!s.ok()) { + return s; + } + iter->reset( + new TransactionLogIteratorImpl(dbname_, + &options_, + seq, + probableWALFiles, + &last_flushed_sequence_)); + iter->get()->Next(); + return Status::OK(); +} + +Status DBImpl::FindProbableWALFiles(std::vector* const allLogs, + std::vector* const result, + const SequenceNumber target) { + assert(allLogs != nullptr); + assert(result != nullptr); + + std::sort(allLogs->begin(), allLogs->end()); + long start = 0; // signed to avoid overflow when target is < first file. + long end = static_cast(allLogs->size()) - 1; + // Binary Search. avoid opening all files. + while (end >= start) { + long mid = start + (end - start) / 2; // Avoid overflow. + WriteBatch batch; + Status s = ReadFirstRecord(allLogs->at(mid), &batch); + if (!s.ok()) { + return s; + } + SequenceNumber currentSeqNum = WriteBatchInternal::Sequence(&batch); + if (currentSeqNum == target) { + start = mid; + end = mid; + break; + } else if (currentSeqNum < target) { + start = mid + 1; + } else { + end = mid - 1; + } + } + size_t startIndex = std::max(0l, end); // end could be -ve. + for( size_t i = startIndex; i < allLogs->size(); ++i) { + result->push_back(allLogs->at(i)); + } + return Status::OK(); +} + +Status DBImpl::ReadFirstRecord(const LogFile& file, WriteBatch* const result) { + + if (file.type == kAliveLogFile) { + std::string fname = LogFileName(dbname_, file.logNumber); + Status status = ReadFirstLine(fname, result); + if (!status.ok()) { + // check if the file got moved to archive. + std::string archivedFile = ArchivedLogFileName(dbname_, file.logNumber); + Status s = ReadFirstLine(archivedFile, result); + if (!s.ok()) { + return Status::IOError("Log File Has been deleted"); + } + } + return Status::OK(); + } else if (file.type == kArchivedLogFile) { + std::string fname = ArchivedLogFileName(dbname_, file.logNumber); + Status status = ReadFirstLine(fname, result); + return status; + } + return Status::NotSupported("File Type Not Known"); +} + +Status DBImpl::ReadFirstLine(const std::string& fname, + WriteBatch* const batch) { + struct LogReporter : public log::Reader::Reporter { + Env* env; + Logger* info_log; + const char* fname; + Status* status; // nullptr if options_.paranoid_checks==false + virtual void Corruption(size_t bytes, const Status& s) { + Log(info_log, "%s%s: dropping %d bytes; %s", + (this->status == nullptr ? "(ignoring error) " : ""), + fname, static_cast(bytes), s.ToString().c_str()); + if (this->status != nullptr && this->status->ok()) *this->status = s; + } + }; + + unique_ptr file; + Status status = env_->NewSequentialFile(fname, &file); + + if (!status.ok()) { + return status; + } + + + LogReporter reporter; + reporter.env = env_; + reporter.info_log = options_.info_log.get(); + reporter.fname = fname.c_str(); + reporter.status = (options_.paranoid_checks ? &status : nullptr); + log::Reader reader(std::move(file), &reporter, true/*checksum*/, + 0/*initial_offset*/); + std::string scratch; + Slice record; + if (reader.ReadRecord(&record, &scratch) && status.ok()) { + if (record.size() < 12) { + reporter.Corruption( + record.size(), Status::Corruption("log record too small")); + return Status::IOError("Corruption noted"); + // TODO read record's till the first no corrupt entry? + } + WriteBatchInternal::SetContents(batch, record); + return Status::OK(); + } + return Status::IOError("Error reading from file " + fname); +} + +Status DBImpl::ListAllWALFiles(const std::string& path, + std::vector* const logFiles, + WalFileType logType) { + assert(logFiles != nullptr); + std::vector allFiles; + const Status status = env_->GetChildren(path, &allFiles); + if (!status.ok()) { + return status; + } + for(std::vector::iterator it = allFiles.begin(); + it != allFiles.end(); + ++it) { + uint64_t number; + FileType type; + if (ParseFileName(*it, &number, &type) && type == kLogFile){ + logFiles->push_back(LogFile(number, logType)); + } + } + return status; +} + +void DBImpl::TEST_CompactRange(int level, const Slice* begin,const Slice* end) { + assert(level >= 0); + + InternalKey begin_storage, end_storage; + + ManualCompaction manual; + manual.level = level; + manual.done = false; + manual.in_progress = false; + if (begin == nullptr) { + manual.begin = nullptr; + } else { + begin_storage = InternalKey(*begin, kMaxSequenceNumber, kValueTypeForSeek); + manual.begin = &begin_storage; + } + if (end == nullptr) { + manual.end = nullptr; + } else { + end_storage = InternalKey(*end, 0, static_cast(0)); + manual.end = &end_storage; + } + + MutexLock l(&mutex_); + + // When a manual compaction arrives, temporarily throttle down + // the number of background compaction threads to 1. This is + // needed to ensure that this manual compaction can compact + // any range of keys/files. We artificialy increase + // bg_compaction_scheduled_ by a large number, this causes + // the system to have a single background thread. Now, + // this manual compaction can progress without stomping + // on any other concurrent compactions. + const int LargeNumber = 10000000; + const int newvalue = options_.max_background_compactions-1; + bg_compaction_scheduled_ += LargeNumber; + while (bg_compaction_scheduled_ > LargeNumber) { + Log(options_.info_log, "Manual compaction request waiting for background threads to fall below 1"); + bg_cv_.Wait(); + } + Log(options_.info_log, "Manual compaction starting"); + + while (!manual.done) { + while (manual_compaction_ != nullptr) { + bg_cv_.Wait(); + } + manual_compaction_ = &manual; + if (bg_compaction_scheduled_ == LargeNumber) { + bg_compaction_scheduled_ = newvalue; + } + MaybeScheduleCompaction(); + while (manual_compaction_ == &manual) { + bg_cv_.Wait(); + } + } + assert(!manual.in_progress); + + // wait till there are no background threads scheduled + bg_compaction_scheduled_ += LargeNumber; + while (bg_compaction_scheduled_ > LargeNumber + newvalue) { + Log(options_.info_log, "Manual compaction resetting background threads"); + bg_cv_.Wait(); + } + bg_compaction_scheduled_ = 0; +} + +Status DBImpl::FlushMemTable(const FlushOptions& options) { + // nullptr batch means just wait for earlier writes to be done + Status s = Write(WriteOptions(), nullptr); + if (s.ok() && options.wait) { + // Wait until the compaction completes + s = WaitForCompactMemTable(); + } + return s; +} + +Status DBImpl::WaitForCompactMemTable() { + Status s; + // Wait until the compaction completes + MutexLock l(&mutex_); + while (imm_.size() > 0 && bg_error_.ok()) { + bg_cv_.Wait(); + } + if (imm_.size() != 0) { + s = bg_error_; + } + return s; +} + +Status DBImpl::TEST_CompactMemTable() { + return FlushMemTable(FlushOptions()); +} + +Status DBImpl::TEST_WaitForCompactMemTable() { + return WaitForCompactMemTable(); +} + +Status DBImpl::TEST_WaitForCompact() { + // Wait until the compaction completes + MutexLock l(&mutex_); + while (bg_compaction_scheduled_ && bg_error_.ok()) { + bg_cv_.Wait(); + } + return bg_error_; +} + +void DBImpl::MaybeScheduleCompaction() { + mutex_.AssertHeld(); + if (bg_compaction_scheduled_ >= options_.max_background_compactions) { + // Already scheduled + } else if (shutting_down_.Acquire_Load()) { + // DB is being deleted; no more background compactions + } else if (!imm_.IsFlushPending() && + manual_compaction_ == nullptr && + !versions_->NeedsCompaction()) { + // No work to be done + } else { + bg_compaction_scheduled_++; + env_->Schedule(&DBImpl::BGWork, this); + } +} + +void DBImpl::BGWork(void* db) { + reinterpret_cast(db)->BackgroundCall(); +} + +void DBImpl::BackgroundCall() { + bool madeProgress = false; + DeletionState deletion_state; + MutexLock l(&mutex_); + // Log(options_.info_log, "XXX BG Thread %llx process new work item", pthread_self()); + assert(bg_compaction_scheduled_); + if (!shutting_down_.Acquire_Load()) { + Status s = BackgroundCompaction(&madeProgress, deletion_state); + if (!s.ok()) { + // Wait a little bit before retrying background compaction in + // case this is an environmental problem and we do not want to + // chew up resources for failed compactions for the duration of + // the problem. + bg_cv_.SignalAll(); // In case a waiter can proceed despite the error + Log(options_.info_log, "Waiting after background compaction error: %s", + s.ToString().c_str()); + mutex_.Unlock(); + env_->SleepForMicroseconds(1000000); + mutex_.Lock(); + } + } + + // delete unnecessary files if any, this is done outside the mutex + if (!deletion_state.live.empty()) { + mutex_.Unlock(); + PurgeObsoleteFiles(deletion_state); + EvictObsoleteFiles(deletion_state); + mutex_.Lock(); + } + + bg_compaction_scheduled_--; + + MaybeScheduleLogDBDeployStats(); + + // Previous compaction may have produced too many files in a level, + // So reschedule another compaction if we made progress in the + // last compaction. + if (madeProgress) { + MaybeScheduleCompaction(); + } + bg_cv_.SignalAll(); +} + +Status DBImpl::BackgroundCompaction(bool* madeProgress, + DeletionState& deletion_state) { + *madeProgress = false; + mutex_.AssertHeld(); + + while (imm_.IsFlushPending()) { + Log(options_.info_log, + "BackgroundCompaction doing CompactMemTable, compaction slots available %d", + options_.max_background_compactions - bg_compaction_scheduled_); + Status stat = CompactMemTable(madeProgress); + if (!stat.ok()) { + return stat; + } + } + + unique_ptr c; + bool is_manual = (manual_compaction_ != nullptr) && + (manual_compaction_->in_progress == false); + InternalKey manual_end; + if (is_manual) { + ManualCompaction* m = manual_compaction_; + assert(!m->in_progress); + m->in_progress = true; // another thread cannot pick up the same work + c.reset(versions_->CompactRange(m->level, m->begin, m->end)); + if (c) { + manual_end = c->input(0, c->num_input_files(0) - 1)->largest; + } else { + m->done = true; + } + Log(options_.info_log, + "Manual compaction at level-%d from %s .. %s; will stop at %s\n", + m->level, + (m->begin ? m->begin->DebugString().c_str() : "(begin)"), + (m->end ? m->end->DebugString().c_str() : "(end)"), + (m->done ? "(end)" : manual_end.DebugString().c_str())); + } else if (!options_.disable_auto_compactions) { + c.reset(versions_->PickCompaction()); + } + + Status status; + if (!c) { + // Nothing to do + Log(options_.info_log, "Compaction nothing to do"); + } else if (!is_manual && c->IsTrivialMove()) { + // Move file to next level + assert(c->num_input_files(0) == 1); + FileMetaData* f = c->input(0, 0); + c->edit()->DeleteFile(c->level(), f->number); + c->edit()->AddFile(c->level() + 1, f->number, f->file_size, + f->smallest, f->largest); + status = versions_->LogAndApply(c->edit(), &mutex_); + VersionSet::LevelSummaryStorage tmp; + Log(options_.info_log, "Moved #%lld to level-%d %lld bytes %s: %s\n", + static_cast(f->number), + c->level() + 1, + static_cast(f->file_size), + status.ToString().c_str(), + versions_->LevelSummary(&tmp)); + versions_->ReleaseCompactionFiles(c.get(), status); + *madeProgress = true; + } else { + CompactionState* compact = new CompactionState(c.get()); + status = DoCompactionWork(compact); + CleanupCompaction(compact); + versions_->ReleaseCompactionFiles(c.get(), status); + c->ReleaseInputs(); + FindObsoleteFiles(deletion_state); + *madeProgress = true; + } + c.reset(); + + if (status.ok()) { + // Done + } else if (shutting_down_.Acquire_Load()) { + // Ignore compaction errors found during shutting down + } else { + Log(options_.info_log, + "Compaction error: %s", status.ToString().c_str()); + if (options_.paranoid_checks && bg_error_.ok()) { + bg_error_ = status; + } + } + + if (is_manual) { + ManualCompaction* m = manual_compaction_; + if (!status.ok()) { + m->done = true; + } + if (!m->done) { + // We only compacted part of the requested range. Update *m + // to the range that is left to be compacted. + m->tmp_storage = manual_end; + m->begin = &m->tmp_storage; + } + m->in_progress = false; // not being processed anymore + manual_compaction_ = nullptr; + } + return status; +} + +void DBImpl::CleanupCompaction(CompactionState* compact) { + mutex_.AssertHeld(); + if (compact->builder != nullptr) { + // May happen if we get a shutdown call in the middle of compaction + compact->builder->Abandon(); + compact->builder.reset(); + } else { + assert(compact->outfile == nullptr); + } + for (size_t i = 0; i < compact->outputs.size(); i++) { + const CompactionState::Output& out = compact->outputs[i]; + pending_outputs_.erase(out.number); + } + delete compact; +} + +// Allocate the file numbers for the output file. We allocate as +// many output file numbers as there are files in level+1. +// Insert them into pending_outputs so that they do not get deleted. +void DBImpl::AllocateCompactionOutputFileNumbers(CompactionState* compact) { + mutex_.AssertHeld(); + assert(compact != nullptr); + assert(compact->builder == nullptr); + int filesNeeded = compact->compaction->num_input_files(1); + for (int i = 0; i < filesNeeded; i++) { + uint64_t file_number = versions_->NewFileNumber(); + pending_outputs_.insert(file_number); + compact->allocated_file_numbers.push_back(file_number); + } +} + +// Frees up unused file number. +void DBImpl::ReleaseCompactionUnusedFileNumbers(CompactionState* compact) { + mutex_.AssertHeld(); + for (std::list::iterator it = + compact->allocated_file_numbers.begin(); + it != compact->allocated_file_numbers.end(); ++it) { + uint64_t file_number = *it; + pending_outputs_.erase(file_number); + // Log(options_.info_log, "XXX releasing unused file num %d", file_number); + } +} + +Status DBImpl::OpenCompactionOutputFile(CompactionState* compact) { + assert(compact != nullptr); + assert(compact->builder == nullptr); + uint64_t file_number; + // If we have not yet exhausted the pre-allocated file numbers, + // then use the one from the front. Otherwise, we have to acquire + // the heavyweight lock and allocate a new file number. + if (!compact->allocated_file_numbers.empty()) { + file_number = compact->allocated_file_numbers.front(); + compact->allocated_file_numbers.pop_front(); + } else { + mutex_.Lock(); + file_number = versions_->NewFileNumber(); + pending_outputs_.insert(file_number); + mutex_.Unlock(); + } + CompactionState::Output out; + out.number = file_number; + out.smallest.Clear(); + out.largest.Clear(); + compact->outputs.push_back(out); + + // Make the output file + std::string fname = TableFileName(dbname_, file_number); + Status s = env_->NewWritableFile(fname, &compact->outfile); + + // Over-estimate slightly so we don't end up just barely crossing + // the threshold. + compact->outfile->SetPreallocationBlockSize( + 1.1 * versions_->MaxFileSizeForLevel(compact->compaction->level() + 1)); + + if (s.ok()) { + compact->builder.reset(new TableBuilder(options_, compact->outfile.get(), + compact->compaction->level() + 1)); + } + return s; +} + +Status DBImpl::FinishCompactionOutputFile(CompactionState* compact, + Iterator* input) { + assert(compact != nullptr); + assert(compact->outfile); + assert(compact->builder != nullptr); + + const uint64_t output_number = compact->current_output()->number; + assert(output_number != 0); + + // Check for iterator errors + Status s = input->status(); + const uint64_t current_entries = compact->builder->NumEntries(); + if (s.ok()) { + s = compact->builder->Finish(); + } else { + compact->builder->Abandon(); + } + const uint64_t current_bytes = compact->builder->FileSize(); + compact->current_output()->file_size = current_bytes; + compact->total_bytes += current_bytes; + compact->builder.reset(); + + // Finish and check for file errors + if (s.ok() && !options_.disableDataSync) { + if (options_.use_fsync) { + s = compact->outfile->Fsync(); + } else { + s = compact->outfile->Sync(); + } + } + if (s.ok()) { + s = compact->outfile->Close(); + } + compact->outfile.reset(); + + if (s.ok() && current_entries > 0) { + // Verify that the table is usable + Iterator* iter = table_cache_->NewIterator(ReadOptions(), + output_number, + current_bytes); + s = iter->status(); + delete iter; + if (s.ok()) { + Log(options_.info_log, + "Generated table #%llu: %lld keys, %lld bytes", + (unsigned long long) output_number, + (unsigned long long) current_entries, + (unsigned long long) current_bytes); + } + } + return s; +} + + +Status DBImpl::InstallCompactionResults(CompactionState* compact) { + mutex_.AssertHeld(); + + // paranoia: verify that the files that we started with + // still exist in the current version and in the same original level. + // This ensures that a concurrent compaction did not erroneously + // pick the same files to compact. + if (!versions_->VerifyCompactionFileConsistency(compact->compaction)) { + Log(options_.info_log, "Compaction %d@%d + %d@%d files aborted", + compact->compaction->num_input_files(0), + compact->compaction->level(), + compact->compaction->num_input_files(1), + compact->compaction->level() + 1); + return Status::IOError("Compaction input files inconsistent"); + } + + Log(options_.info_log, "Compacted %d@%d + %d@%d files => %lld bytes", + compact->compaction->num_input_files(0), + compact->compaction->level(), + compact->compaction->num_input_files(1), + compact->compaction->level() + 1, + static_cast(compact->total_bytes)); + + // Add compaction outputs + compact->compaction->AddInputDeletions(compact->compaction->edit()); + const int level = compact->compaction->level(); + for (size_t i = 0; i < compact->outputs.size(); i++) { + const CompactionState::Output& out = compact->outputs[i]; + compact->compaction->edit()->AddFile( + level + 1, + out.number, out.file_size, out.smallest, out.largest); + } + return versions_->LogAndApply(compact->compaction->edit(), &mutex_); +} + +// +// Given a sequence number, return the sequence number of the +// earliest snapshot that this sequence number is visible in. +// The snapshots themselves are arranged in ascending order of +// sequence numbers. +// Employ a sequential search because the total number of +// snapshots are typically small. +inline SequenceNumber DBImpl::findEarliestVisibleSnapshot( + SequenceNumber in, std::vector& snapshots) { + SequenceNumber prev __attribute__((unused)) = 0; + for (std::vector::iterator it = snapshots.begin(); + it < snapshots.end(); it++) { + assert (prev <= *it); + if (*it >= in) { + return *it; + } + assert(prev = *it); // assignment + } + Log(options_.info_log, + "Looking for seqid %ld but maxseqid is %ld", in, + snapshots[snapshots.size()-1]); + assert(0); + return 0; +} + +Status DBImpl::DoCompactionWork(CompactionState* compact) { + int64_t imm_micros = 0; // Micros spent doing imm_ compactions + + Log(options_.info_log, + "Compacting %d@%d + %d@%d files, score %.2f slots available %d", + compact->compaction->num_input_files(0), + compact->compaction->level(), + compact->compaction->num_input_files(1), + compact->compaction->level() + 1, + compact->compaction->score(), + options_.max_background_compactions - bg_compaction_scheduled_); + char scratch[256]; + compact->compaction->Summary(scratch, sizeof(scratch)); + Log(options_.info_log, "Compaction start summary: %s\n", scratch); + + assert(versions_->NumLevelFiles(compact->compaction->level()) > 0); + assert(compact->builder == nullptr); + assert(!compact->outfile); + + SequenceNumber visible_at_tip = 0; + SequenceNumber earliest_snapshot; + snapshots_.getAll(compact->existing_snapshots); + if (compact->existing_snapshots.size() == 0) { + // optimize for fast path if there are no snapshots + visible_at_tip = versions_->LastSequence(); + earliest_snapshot = visible_at_tip; + } else { + // Add the current seqno as the 'latest' virtual + // snapshot to the end of this list. + compact->existing_snapshots.push_back(versions_->LastSequence()); + earliest_snapshot = compact->existing_snapshots[0]; + } + + // Is this compaction producing files at the bottommost level? + bool bottommost_level = true; + for (int i = compact->compaction->level() + 2; + i < versions_->NumberLevels(); i++) { + if (versions_->NumLevelFiles(i) > 0) { + bottommost_level = false; + break; + } + } + + // Allocate the output file numbers before we release the lock + AllocateCompactionOutputFileNumbers(compact); + + // Release mutex while we're actually doing the compaction work + mutex_.Unlock(); + + const uint64_t start_micros = env_->NowMicros(); + unique_ptr input(versions_->MakeInputIterator(compact->compaction)); + input->SeekToFirst(); + Status status; + ParsedInternalKey ikey; + std::string current_user_key; + bool has_current_user_key = false; + SequenceNumber last_sequence_for_key __attribute__((unused)) = + kMaxSequenceNumber; + SequenceNumber visible_in_snapshot = kMaxSequenceNumber; + for (; input->Valid() && !shutting_down_.Acquire_Load(); ) { + // Prioritize immutable compaction work + if (imm_.imm_flush_needed.NoBarrier_Load() != nullptr) { + const uint64_t imm_start = env_->NowMicros(); + mutex_.Lock(); + if (imm_.IsFlushPending()) { + CompactMemTable(); + bg_cv_.SignalAll(); // Wakeup MakeRoomForWrite() if necessary + } + mutex_.Unlock(); + imm_micros += (env_->NowMicros() - imm_start); + } + + Slice key = input->key(); + Slice value = input->value(); + Slice* compaction_filter_value = nullptr; + if (compact->compaction->ShouldStopBefore(key) && + compact->builder != nullptr) { + status = FinishCompactionOutputFile(compact, input.get()); + if (!status.ok()) { + break; + } + } + + // Handle key/value, add to state, etc. + bool drop = false; + if (!ParseInternalKey(key, &ikey)) { + // Do not hide error keys + current_user_key.clear(); + has_current_user_key = false; + last_sequence_for_key = kMaxSequenceNumber; + visible_in_snapshot = kMaxSequenceNumber; + } else { + if (!has_current_user_key || + user_comparator()->Compare(ikey.user_key, + Slice(current_user_key)) != 0) { + // First occurrence of this user key + current_user_key.assign(ikey.user_key.data(), ikey.user_key.size()); + has_current_user_key = true; + last_sequence_for_key = kMaxSequenceNumber; + visible_in_snapshot = kMaxSequenceNumber; + } + + // If there are no snapshots, then this kv affect visibility at tip. + // Otherwise, search though all existing snapshots to find + // the earlist snapshot that is affected by this kv. + SequenceNumber visible = visible_at_tip ? visible_at_tip : + findEarliestVisibleSnapshot(ikey.sequence, + compact->existing_snapshots); + + if (visible_in_snapshot == visible) { + // If the earliest snapshot is which this key is visible in + // is the same as the visibily of a previous instance of the + // same key, then this kv is not visible in any snapshot. + // Hidden by an newer entry for same user key + assert(last_sequence_for_key >= ikey.sequence); + drop = true; // (A) + RecordTick(options_.statistics, COMPACTION_KEY_DROP_NEWER_ENTRY); + } else if (ikey.type == kTypeDeletion && + ikey.sequence <= earliest_snapshot && + compact->compaction->IsBaseLevelForKey(ikey.user_key)) { + // For this user key: + // (1) there is no data in higher levels + // (2) data in lower levels will have larger sequence numbers + // (3) data in layers that are being compacted here and have + // smaller sequence numbers will be dropped in the next + // few iterations of this loop (by rule (A) above). + // Therefore this deletion marker is obsolete and can be dropped. + drop = true; + RecordTick(options_.statistics, COMPACTION_KEY_DROP_OBSOLETE); + } else if (options_.CompactionFilter != nullptr && + ikey.type != kTypeDeletion && + ikey.sequence < earliest_snapshot) { + // If the user has specified a compaction filter, then invoke + // it. If this key is not visible via any snapshot and the + // return value of the compaction filter is true and then + // drop this key from the output. + drop = options_.CompactionFilter(options_.compaction_filter_args, + compact->compaction->level(), + ikey.user_key, value, &compaction_filter_value); + + if (drop) { + RecordTick(options_.statistics, COMPACTION_KEY_DROP_USER); + } + // If the application wants to change the value, then do so here. + if (compaction_filter_value != nullptr) { + value = *compaction_filter_value; + delete compaction_filter_value; + } + } + + last_sequence_for_key = ikey.sequence; + visible_in_snapshot = visible; + } +#if 0 + Log(options_.info_log, + " Compact: %s, seq %d, type: %d %d, drop: %d, is_base: %d, " + "%d smallest_snapshot: %d level: %d bottommost %d", + ikey.user_key.ToString().c_str(), + (int)ikey.sequence, ikey.type, kTypeValue, drop, + compact->compaction->IsBaseLevelForKey(ikey.user_key), + (int)last_sequence_for_key, (int)earliest_snapshot, + compact->compaction->level(), bottommost_level); +#endif + + if (!drop) { + + char* kptr = (char*)key.data(); + std::string kstr; + + // Zeroing out the sequence number leads to better compression. + // If this is the bottommost level (no files in lower levels) + // and the earliest snapshot is larger than this seqno + // then we can squash the seqno to zero. + if (bottommost_level && ikey.sequence < earliest_snapshot) { + assert(ikey.type != kTypeDeletion); + // make a copy because updating in place would cause problems + // with the priority queue that is managing the input key iterator + kstr.assign(key.data(), key.size()); + kptr = (char *)kstr.c_str(); + UpdateInternalKey(kptr, key.size(), (uint64_t)0, ikey.type); + } + + Slice newkey(kptr, key.size()); + assert((key.clear(), 1)); // we do not need 'key' anymore + + // Open output file if necessary + if (compact->builder == nullptr) { + status = OpenCompactionOutputFile(compact); + if (!status.ok()) { + break; + } + } + if (compact->builder->NumEntries() == 0) { + compact->current_output()->smallest.DecodeFrom(newkey); + } + compact->current_output()->largest.DecodeFrom(newkey); + compact->builder->Add(newkey, value); + + // Close output file if it is big enough + if (compact->builder->FileSize() >= + compact->compaction->MaxOutputFileSize()) { + status = FinishCompactionOutputFile(compact, input.get()); + if (!status.ok()) { + break; + } + } + } + + input->Next(); + } + + if (status.ok() && shutting_down_.Acquire_Load()) { + status = Status::IOError("Deleting DB during compaction"); + } + if (status.ok() && compact->builder != nullptr) { + status = FinishCompactionOutputFile(compact, input.get()); + } + if (status.ok()) { + status = input->status(); + } + input.reset(); + + CompactionStats stats; + stats.micros = env_->NowMicros() - start_micros - imm_micros; + if (options_.statistics) { + options_.statistics->measureTime(COMPACTION_TIME, stats.micros); + } + stats.files_in_leveln = compact->compaction->num_input_files(0); + stats.files_in_levelnp1 = compact->compaction->num_input_files(1); + + int num_output_files = compact->outputs.size(); + if (compact->builder != nullptr) { + // An error occured so ignore the last output. + assert(num_output_files > 0); + --num_output_files; + } + stats.files_out_levelnp1 = num_output_files; + + for (int i = 0; i < compact->compaction->num_input_files(0); i++) + stats.bytes_readn += compact->compaction->input(0, i)->file_size; + + for (int i = 0; i < compact->compaction->num_input_files(1); i++) + stats.bytes_readnp1 += compact->compaction->input(1, i)->file_size; + + for (int i = 0; i < num_output_files; i++) { + stats.bytes_written += compact->outputs[i].file_size; + } + + mutex_.Lock(); + stats_[compact->compaction->level() + 1].Add(stats); + + // if there were any unused file number (mostly in case of + // compaction error), free up the entry from pending_putputs + ReleaseCompactionUnusedFileNumbers(compact); + + if (status.ok()) { + status = InstallCompactionResults(compact); + } + VersionSet::LevelSummaryStorage tmp; + Log(options_.info_log, + "compacted to: %s, %.1f MB/sec, level %d, files in(%d, %d) out(%d) " + "MB in(%.1f, %.1f) out(%.1f), amplify(%.1f) %s\n", + versions_->LevelSummary(&tmp), + (stats.bytes_readn + stats.bytes_readnp1 + stats.bytes_written) / + (double) stats.micros, + compact->compaction->level() + 1, + stats.files_in_leveln, stats.files_in_levelnp1, stats.files_out_levelnp1, + stats.bytes_readn / 1048576.0, + stats.bytes_readnp1 / 1048576.0, + stats.bytes_written / 1048576.0, + (stats.bytes_written + stats.bytes_readnp1) / + (double) stats.bytes_readn, + status.ToString().c_str()); + + return status; +} + +namespace { +struct IterState { + port::Mutex* mu; + Version* version; + std::vector mem; // includes both mem_ and imm_ +}; + +static void CleanupIteratorState(void* arg1, void* arg2) { + IterState* state = reinterpret_cast(arg1); + state->mu->Lock(); + for (unsigned int i = 0; i < state->mem.size(); i++) { + state->mem[i]->Unref(); + } + state->version->Unref(); + state->mu->Unlock(); + delete state; +} +} // namespace + +Iterator* DBImpl::NewInternalIterator(const ReadOptions& options, + SequenceNumber* latest_snapshot) { + IterState* cleanup = new IterState; + mutex_.Lock(); + *latest_snapshot = versions_->LastSequence(); + + // Collect together all needed child iterators for mem + std::vector list; + mem_->Ref(); + list.push_back(mem_->NewIterator()); + cleanup->mem.push_back(mem_); + + // Collect together all needed child iterators for imm_ + std::vector immutables; + imm_.GetMemTables(&immutables); + for (unsigned int i = 0; i < immutables.size(); i++) { + MemTable* m = immutables[i]; + m->Ref(); + list.push_back(m->NewIterator()); + cleanup->mem.push_back(m); + } + + // Collect iterators for files in L0 - Ln + versions_->current()->AddIterators(options, &list); + Iterator* internal_iter = + NewMergingIterator(&internal_comparator_, &list[0], list.size()); + versions_->current()->Ref(); + + cleanup->mu = &mutex_; + cleanup->version = versions_->current(); + internal_iter->RegisterCleanup(CleanupIteratorState, cleanup, nullptr); + + mutex_.Unlock(); + return internal_iter; +} + +Iterator* DBImpl::TEST_NewInternalIterator() { + SequenceNumber ignored; + return NewInternalIterator(ReadOptions(), &ignored); +} + +int64_t DBImpl::TEST_MaxNextLevelOverlappingBytes() { + MutexLock l(&mutex_); + return versions_->MaxNextLevelOverlappingBytes(); +} + +Status DBImpl::Get(const ReadOptions& options, + const Slice& key, + std::string* value) { + Status s; + MutexLock l(&mutex_); + std::unique_ptr sw = stats::StartStopWatch(env_, + options_.statistics, + DB_GET); + SequenceNumber snapshot; + if (options.snapshot != nullptr) { + snapshot = reinterpret_cast(options.snapshot)->number_; + } else { + snapshot = versions_->LastSequence(); + } + + MemTable* mem = mem_; + MemTableList imm = imm_; + Version* current = versions_->current(); + mem->Ref(); + imm.RefAll(); + current->Ref(); + + bool have_stat_update = false; + Version::GetStats stats; + + // Unlock while reading from files and memtables + { + mutex_.Unlock(); + // First look in the memtable, then in the immutable memtable (if any). + LookupKey lkey(key, snapshot); + if (mem->Get(lkey, value, &s)) { + // Done + } else if (imm.Get(lkey, value, &s)) { + // Done + } else { + s = current->Get(options, lkey, value, &stats); + have_stat_update = true; + } + mutex_.Lock(); + } + + if (!options_.disable_seek_compaction && + have_stat_update && current->UpdateStats(stats)) { + MaybeScheduleCompaction(); + } + mem->Unref(); + imm.UnrefAll(); + current->Unref(); + RecordTick(options_.statistics, NUMBER_KEYS_READ); + RecordTick(options_.statistics, BYTES_READ, value->size()); + return s; +} + +Iterator* DBImpl::NewIterator(const ReadOptions& options) { + SequenceNumber latest_snapshot; + Iterator* internal_iter = NewInternalIterator(options, &latest_snapshot); + return NewDBIterator( + &dbname_, env_, user_comparator(), internal_iter, + (options.snapshot != nullptr + ? reinterpret_cast(options.snapshot)->number_ + : latest_snapshot)); +} + +const Snapshot* DBImpl::GetSnapshot() { + MutexLock l(&mutex_); + return snapshots_.New(versions_->LastSequence()); +} + +void DBImpl::ReleaseSnapshot(const Snapshot* s) { + MutexLock l(&mutex_); + snapshots_.Delete(reinterpret_cast(s)); +} + +// Convenience methods +Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) { + return DB::Put(o, key, val); +} + +Status DBImpl::Delete(const WriteOptions& options, const Slice& key) { + return DB::Delete(options, key); +} + +Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) { + Writer w(&mutex_); + w.batch = my_batch; + w.sync = options.sync; + w.disableWAL = options.disableWAL; + w.done = false; + + MutexLock l(&mutex_); + std::unique_ptr sw = stats::StartStopWatch(env_, + options_.statistics, + DB_WRITE); + writers_.push_back(&w); + while (!w.done && &w != writers_.front()) { + w.cv.Wait(); + } + if (w.done) { + return w.status; + } + + // May temporarily unlock and wait. + Status status = MakeRoomForWrite(my_batch == nullptr); + uint64_t last_sequence = versions_->LastSequence(); + Writer* last_writer = &w; + if (status.ok() && my_batch != nullptr) { // nullptr batch is for compactions + WriteBatch* updates = BuildBatchGroup(&last_writer); + const SequenceNumber current_sequence = last_sequence + 1; + WriteBatchInternal::SetSequence(updates, current_sequence); + int my_batch_count = WriteBatchInternal::Count(updates); + last_sequence += my_batch_count; + // Record statistics + RecordTick(options_.statistics, NUMBER_KEYS_WRITTEN, my_batch_count); + RecordTick(options_.statistics, + BYTES_WRITTEN, + WriteBatchInternal::ByteSize(updates)); + // Add to log and apply to memtable. We can release the lock + // during this phase since &w is currently responsible for logging + // and protects against concurrent loggers and concurrent writes + // into mem_. + { + mutex_.Unlock(); + if (options.disableWAL) { + flush_on_destroy_ = true; + } + + if (!options.disableWAL) { + status = log_->AddRecord(WriteBatchInternal::Contents(updates)); + if (status.ok() && options.sync) { + if (options_.use_fsync) { + status = log_->file()->Fsync(); + } else { + status = log_->file()->Sync(); + } + } + } + if (status.ok()) { + status = WriteBatchInternal::InsertInto(updates, mem_); + } + mutex_.Lock(); + } + last_flushed_sequence_ = current_sequence; + if (updates == tmp_batch_) tmp_batch_->Clear(); + + versions_->SetLastSequence(last_sequence); + } + + while (true) { + Writer* ready = writers_.front(); + writers_.pop_front(); + if (ready != &w) { + ready->status = status; + ready->done = true; + ready->cv.Signal(); + } + if (ready == last_writer) break; + } + + // Notify new head of write queue + if (!writers_.empty()) { + writers_.front()->cv.Signal(); + } + return status; +} + +// REQUIRES: Writer list must be non-empty +// REQUIRES: First writer must have a non-nullptr batch +WriteBatch* DBImpl::BuildBatchGroup(Writer** last_writer) { + assert(!writers_.empty()); + Writer* first = writers_.front(); + WriteBatch* result = first->batch; + assert(result != nullptr); + + size_t size = WriteBatchInternal::ByteSize(first->batch); + + // Allow the group to grow up to a maximum size, but if the + // original write is small, limit the growth so we do not slow + // down the small write too much. + size_t max_size = 1 << 20; + if (size <= (128<<10)) { + max_size = size + (128<<10); + } + + *last_writer = first; + std::deque::iterator iter = writers_.begin(); + ++iter; // Advance past "first" + for (; iter != writers_.end(); ++iter) { + Writer* w = *iter; + if (w->sync && !first->sync) { + // Do not include a sync write into a batch handled by a non-sync write. + break; + } + + if (!w->disableWAL && first->disableWAL) { + // Do not include a write that needs WAL into a batch that has + // WAL disabled. + break; + } + + if (w->batch != nullptr) { + size += WriteBatchInternal::ByteSize(w->batch); + if (size > max_size) { + // Do not make batch too big + break; + } + + // Append to *reuslt + if (result == first->batch) { + // Switch to temporary batch instead of disturbing caller's batch + result = tmp_batch_; + assert(WriteBatchInternal::Count(result) == 0); + WriteBatchInternal::Append(result, first->batch); + } + WriteBatchInternal::Append(result, w->batch); + } + *last_writer = w; + } + return result; +} + +// REQUIRES: mutex_ is held +// REQUIRES: this thread is currently at the front of the writer queue +Status DBImpl::MakeRoomForWrite(bool force) { + mutex_.AssertHeld(); + assert(!writers_.empty()); + bool allow_delay = !force; + bool allow_rate_limit_delay = !force; + uint64_t rate_limit_delay_millis = 0; + Status s; + double score; + + while (true) { + if (!bg_error_.ok()) { + // Yield previous error + s = bg_error_; + break; + } else if ( + allow_delay && + versions_->NumLevelFiles(0) >= + options_.level0_slowdown_writes_trigger) { + // We are getting close to hitting a hard limit on the number of + // L0 files. Rather than delaying a single write by several + // seconds when we hit the hard limit, start delaying each + // individual write by 1ms to reduce latency variance. Also, + // this delay hands over some CPU to the compaction thread in + // case it is sharing the same core as the writer. + mutex_.Unlock(); + uint64_t t1 = env_->NowMicros(); + env_->SleepForMicroseconds(1000); + uint64_t delayed = env_->NowMicros() - t1; + stall_level0_slowdown_ += delayed; + allow_delay = false; // Do not delay a single write more than once + //Log(options_.info_log, + // "delaying write %llu usecs for level0_slowdown_writes_trigger\n", + // (long long unsigned int)delayed); + mutex_.Lock(); + delayed_writes_++; + } else if (!force && + (mem_->ApproximateMemoryUsage() <= options_.write_buffer_size)) { + // There is room in current memtable + if (allow_delay) { + DelayLoggingAndReset(); + } + break; + } else if (imm_.size() == options_.max_write_buffer_number - 1) { + // We have filled up the current memtable, but the previous + // ones are still being compacted, so we wait. + DelayLoggingAndReset(); + Log(options_.info_log, "wait for memtable compaction...\n"); + uint64_t t1 = env_->NowMicros(); + bg_cv_.Wait(); + stall_memtable_compaction_ += env_->NowMicros() - t1; + } else if (versions_->NumLevelFiles(0) >= + options_.level0_stop_writes_trigger) { + // There are too many level-0 files. + DelayLoggingAndReset(); + uint64_t t1 = env_->NowMicros(); + Log(options_.info_log, "wait for fewer level0 files...\n"); + bg_cv_.Wait(); + stall_level0_num_files_ += env_->NowMicros() - t1; + } else if ( + allow_rate_limit_delay && + options_.rate_limit > 1.0 && + (score = versions_->MaxCompactionScore()) > options_.rate_limit) { + // Delay a write when the compaction score for any level is too large. + int max_level = versions_->MaxCompactionScoreLevel(); + mutex_.Unlock(); + uint64_t t1 = env_->NowMicros(); + env_->SleepForMicroseconds(1000); + uint64_t delayed = env_->NowMicros() - t1; + stall_leveln_slowdown_[max_level] += delayed; + // Make sure the following value doesn't round to zero. + rate_limit_delay_millis += std::max((delayed / 1000), (uint64_t) 1); + if (rate_limit_delay_millis >= options_.rate_limit_delay_milliseconds) { + allow_rate_limit_delay = false; + } + // Log(options_.info_log, + // "delaying write %llu usecs for rate limits with max score %.2f\n", + // (long long unsigned int)delayed, score); + mutex_.Lock(); + } else { + // Attempt to switch to a new memtable and trigger compaction of old + DelayLoggingAndReset(); + assert(versions_->PrevLogNumber() == 0); + uint64_t new_log_number = versions_->NewFileNumber(); + unique_ptr lfile; + s = env_->NewWritableFile(LogFileName(dbname_, new_log_number), &lfile); + if (!s.ok()) { + // Avoid chewing through file number space in a tight loop. + versions_->ReuseFileNumber(new_log_number); + break; + } + // Our final size should be less than write_buffer_size + // (compression, etc) but err on the side of caution. + lfile->SetPreallocationBlockSize(1.1 * options_.write_buffer_size); + logfile_number_ = new_log_number; + log_.reset(new log::Writer(std::move(lfile))); + imm_.Add(mem_); + mem_ = new MemTable(internal_comparator_, NumberLevels()); + mem_->Ref(); + force = false; // Do not force another compaction if have room + MaybeScheduleCompaction(); + } + } + return s; +} + +bool DBImpl::GetProperty(const Slice& property, std::string* value) { + value->clear(); + + MutexLock l(&mutex_); + Slice in = property; + Slice prefix("leveldb."); + if (!in.starts_with(prefix)) return false; + in.remove_prefix(prefix.size()); + + if (in.starts_with("num-files-at-level")) { + in.remove_prefix(strlen("num-files-at-level")); + uint64_t level; + bool ok = ConsumeDecimalNumber(&in, &level) && in.empty(); + if (!ok || (int)level >= NumberLevels()) { + return false; + } else { + char buf[100]; + snprintf(buf, sizeof(buf), "%d", + versions_->NumLevelFiles(static_cast(level))); + *value = buf; + return true; + } + } else if (in == "stats") { + char buf[1000]; + uint64_t total_bytes = 0; + uint64_t micros_up = env_->NowMicros() - started_at_; + double seconds_up = micros_up / 1000000.0; + uint64_t total_slowdown = 0; + + // Pardon the long line but I think it is easier to read this way. + snprintf(buf, sizeof(buf), + " Compactions\n" + "Level Files Size(MB) Time(sec) Read(MB) Write(MB) Rn(MB) Rnp1(MB) Wnew(MB) Amplify Read(MB/s) Write(MB/s) Rn Rnp1 Wnp1 NewW Count Ln-stall\n" + "----------------------------------------------------------------------------------------------------------------------------------------------------------------------\n" + ); + value->append(buf); + for (int level = 0; level < NumberLevels(); level++) { + int files = versions_->NumLevelFiles(level); + if (stats_[level].micros > 0 || files > 0) { + int64_t bytes_read = stats_[level].bytes_readn + + stats_[level].bytes_readnp1; + int64_t bytes_new = stats_[level].bytes_written - + stats_[level].bytes_readnp1; + double amplify = (stats_[level].bytes_readn == 0) + ? 0.0 + : (stats_[level].bytes_written + stats_[level].bytes_readnp1) / + (double) stats_[level].bytes_readn; + + total_bytes += bytes_read + stats_[level].bytes_written; + snprintf( + buf, sizeof(buf), + "%3d %8d %8.0f %9.0f %9.0f %9.0f %9.0f %9.0f %9.0f %7.1f %9.1f %11.1f %8d %8d %8d %8d %8d %9.1f\n", + level, + files, + versions_->NumLevelBytes(level) / 1048576.0, + stats_[level].micros / 1e6, + bytes_read / 1048576.0, + stats_[level].bytes_written / 1048576.0, + stats_[level].bytes_readn / 1048576.0, + stats_[level].bytes_readnp1 / 1048576.0, + bytes_new / 1048576.0, + amplify, + (bytes_read / 1048576.0) / (stats_[level].micros / 1000000.0), + (stats_[level].bytes_written / 1048576.0) / + (stats_[level].micros / 1000000.0), + stats_[level].files_in_leveln, + stats_[level].files_in_levelnp1, + stats_[level].files_out_levelnp1, + stats_[level].files_out_levelnp1 - stats_[level].files_in_levelnp1, + stats_[level].count, + stall_leveln_slowdown_[level] / 1000000.0); + total_slowdown += stall_leveln_slowdown_[level]; + value->append(buf); + } + } + + snprintf(buf, sizeof(buf), + "Amplification: %.1f rate, %.2f GB in, %.2f GB out, %.2f MB/sec in, %.2f MB/sec out\n", + (double) total_bytes / stats_[0].bytes_written, + stats_[0].bytes_written / (1048576.0 * 1024), + total_bytes / (1048576.0 * 1024), + stats_[0].bytes_written / 1048576.0 / seconds_up, + total_bytes / 1048576.0 / seconds_up); + value->append(buf); + + snprintf(buf, sizeof(buf), "Uptime(secs): %.1f\n", seconds_up); + value->append(buf); + + snprintf(buf, sizeof(buf), + "Stalls(secs): %.3f level0_slowdown, %.3f level0_numfiles, " + "%.3f memtable_compaction, %.3f leveln_slowdown\n", + stall_level0_slowdown_ / 1000000.0, + stall_level0_num_files_ / 1000000.0, + stall_memtable_compaction_ / 1000000.0, + total_slowdown / 1000000.0); + value->append(buf); + + return true; + } else if (in == "sstables") { + *value = versions_->current()->DebugString(); + return true; + } + + return false; +} + +void DBImpl::GetApproximateSizes( + const Range* range, int n, + uint64_t* sizes) { + // TODO(opt): better implementation + Version* v; + { + MutexLock l(&mutex_); + versions_->current()->Ref(); + v = versions_->current(); + } + + for (int i = 0; i < n; i++) { + // Convert user_key into a corresponding internal key. + InternalKey k1(range[i].start, kMaxSequenceNumber, kValueTypeForSeek); + InternalKey k2(range[i].limit, kMaxSequenceNumber, kValueTypeForSeek); + uint64_t start = versions_->ApproximateOffsetOf(v, k1); + uint64_t limit = versions_->ApproximateOffsetOf(v, k2); + sizes[i] = (limit >= start ? limit - start : 0); + } + + { + MutexLock l(&mutex_); + v->Unref(); + } +} + +inline void DBImpl::DelayLoggingAndReset() { + if (delayed_writes_ > 0) { + Log(options_.info_log, "delayed %d write...\n", delayed_writes_ ); + delayed_writes_ = 0; + } +} + +// Default implementations of convenience methods that subclasses of DB +// can call if they wish +Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { + WriteBatch batch; + batch.Put(key, value); + return Write(opt, &batch); +} + +Status DB::Delete(const WriteOptions& opt, const Slice& key) { + WriteBatch batch; + batch.Delete(key); + return Write(opt, &batch); +} + +DB::~DB() { } + +Status DB::Open(const Options& options, const std::string& dbname, + DB** dbptr) { + *dbptr = nullptr; + + if (options.block_cache != nullptr && options.no_block_cache) { + return Status::InvalidArgument( + "no_block_cache is true while block_cache is not nullptr"); + } + DBImpl* impl = new DBImpl(options, dbname); + Status s = impl->CreateArchivalDirectory(); + if (!s.ok()) { + delete impl; + return s; + } + impl->mutex_.Lock(); + VersionEdit edit(impl->NumberLevels()); + s = impl->Recover(&edit); // Handles create_if_missing, error_if_exists + if (s.ok()) { + uint64_t new_log_number = impl->versions_->NewFileNumber(); + unique_ptr lfile; + s = options.env->NewWritableFile(LogFileName(dbname, new_log_number), + &lfile); + if (s.ok()) { + lfile->SetPreallocationBlockSize(1.1 * options.write_buffer_size); + edit.SetLogNumber(new_log_number); + impl->logfile_number_ = new_log_number; + impl->log_.reset(new log::Writer(std::move(lfile))); + s = impl->versions_->LogAndApply(&edit, &impl->mutex_); + } + if (s.ok()) { + impl->DeleteObsoleteFiles(); + impl->MaybeScheduleCompaction(); + impl->MaybeScheduleLogDBDeployStats(); + } + } + impl->mutex_.Unlock(); + if (s.ok()) { + *dbptr = impl; + } else { + delete impl; + } + return s; +} + +Snapshot::~Snapshot() { +} + +Status DestroyDB(const std::string& dbname, const Options& options) { + Env* env = options.env; + std::vector filenames; + std::vector archiveFiles; + + // Ignore error in case directory does not exist + env->GetChildren(dbname, &filenames); + env->GetChildren(ArchivalDirectory(dbname), &archiveFiles); + + if (filenames.empty()) { + return Status::OK(); + } + + FileLock* lock; + const std::string lockname = LockFileName(dbname); + Status result = env->LockFile(lockname, &lock); + if (result.ok()) { + uint64_t number; + FileType type; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type) && + type != kDBLockFile) { // Lock file will be deleted at end + Status del; + if (type == kMetaDatabase) { + del = DestroyDB(dbname + "/" + filenames[i], options); + } else { + del = env->DeleteFile(dbname + "/" + filenames[i]); + } + if (result.ok() && !del.ok()) { + result = del; + } + } + } + + // Delete archival files. + for (size_t i = 0; i < archiveFiles.size(); ++i) { + ParseFileName(archiveFiles[i], &number, &type); + if (type == kLogFile) { + Status del = env->DeleteFile(ArchivalDirectory(dbname) + "/" + + archiveFiles[i]); + if (result.ok() && !del.ok()) { + result = del; + } + } + } + // ignore case where no archival directory is present. + env->DeleteDir(ArchivalDirectory(dbname)); + + env->UnlockFile(lock); // Ignore error since state is already gone + env->DeleteFile(lockname); + env->DeleteDir(dbname); // Ignore error in case dir contains other files + } + return result; +} + +// +// A global method that can dump out the build version +void dumpLeveldbBuildVersion(Logger * log) { + Log(log, "Git sha %s", leveldb_build_git_sha); + Log(log, "Compile time %s %s", + leveldb_build_compile_time, leveldb_build_compile_date); +} + +} // namespace leveldb diff --git a/db/db_impl.h b/db/db_impl.h new file mode 100644 index 00000000..e5a2936c --- /dev/null +++ b/db/db_impl.h @@ -0,0 +1,351 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_DB_IMPL_H_ +#define STORAGE_LEVELDB_DB_DB_IMPL_H_ + +#include +#include +#include "db/dbformat.h" +#include "db/log_file.h" +#include "db/log_writer.h" +#include "db/snapshot.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "port/port.h" +#include "util/stats_logger.h" +#include "memtablelist.h" + +#ifdef USE_SCRIBE +#include "scribe/scribe_logger.h" +#endif + +namespace leveldb { + +class MemTable; +class TableCache; +class Version; +class VersionEdit; +class VersionSet; + +class DBImpl : public DB { + public: + DBImpl(const Options& options, const std::string& dbname); + virtual ~DBImpl(); + + // Implementations of the DB interface + virtual Status Put(const WriteOptions&, const Slice& key, const Slice& value); + virtual Status Delete(const WriteOptions&, const Slice& key); + virtual Status Write(const WriteOptions& options, WriteBatch* updates); + virtual Status Get(const ReadOptions& options, + const Slice& key, + std::string* value); + virtual Iterator* NewIterator(const ReadOptions&); + virtual const Snapshot* GetSnapshot(); + virtual void ReleaseSnapshot(const Snapshot* snapshot); + virtual bool GetProperty(const Slice& property, std::string* value); + virtual void GetApproximateSizes(const Range* range, int n, uint64_t* sizes); + virtual void CompactRange(const Slice* begin, const Slice* end); + virtual int NumberLevels(); + virtual int MaxMemCompactionLevel(); + virtual int Level0StopWriteTrigger(); + virtual Status Flush(const FlushOptions& options); + virtual Status DisableFileDeletions(); + virtual Status EnableFileDeletions(); + virtual Status GetLiveFiles(std::vector&, + uint64_t* manifest_file_size); + virtual SequenceNumber GetLatestSequenceNumber(); + virtual Status GetUpdatesSince(SequenceNumber seq_number, + unique_ptr* iter); + + // Extra methods (for testing) that are not in the public DB interface + + // Compact any files in the named level that overlap [*begin,*end] + void TEST_CompactRange(int level, const Slice* begin, const Slice* end); + + // Force current memtable contents to be compacted. + Status TEST_CompactMemTable(); + + // Wait for memtable compaction + Status TEST_WaitForCompactMemTable(); + + // Wait for any compaction + Status TEST_WaitForCompact(); + + // Return an internal iterator over the current state of the database. + // The keys of this iterator are internal keys (see format.h). + // The returned iterator should be deleted when no longer needed. + Iterator* TEST_NewInternalIterator(); + + // Return the maximum overlapping data (in bytes) at next level for any + // file at a level >= 1. + int64_t TEST_MaxNextLevelOverlappingBytes(); + + // Simulate a db crash, no elegant closing of database. + void TEST_Destroy_DBImpl(); + + // Return the current manifest file no. + uint64_t TEST_Current_Manifest_FileNo(); + protected: + Env* const env_; + const std::string dbname_; + unique_ptr versions_; + const InternalKeyComparator internal_comparator_; + const Options options_; // options_.comparator == &internal_comparator_ + + const Comparator* user_comparator() const { + return internal_comparator_.user_comparator(); + } + + MemTable* GetMemTable() { + return mem_; + } + + Iterator* NewInternalIterator(const ReadOptions&, + SequenceNumber* latest_snapshot); + + private: + friend class DB; + struct CompactionState; + struct Writer; + struct DeletionState; + + Status NewDB(); + + // Recover the descriptor from persistent storage. May do a significant + // amount of work to recover recently logged updates. Any changes to + // be made to the descriptor are added to *edit. + Status Recover(VersionEdit* edit, MemTable* external_table = nullptr, + bool error_if_log_file_exist = false); + + void MaybeIgnoreError(Status* s) const; + + const Status CreateArchivalDirectory(); + + // Delete any unneeded files and stale in-memory entries. + void DeleteObsoleteFiles(); + + // Compact the in-memory write buffer to disk. Switches to a new + // log-file/memtable and writes a new descriptor iff successful. + Status CompactMemTable(bool* madeProgress = nullptr); + + Status RecoverLogFile(uint64_t log_number, + VersionEdit* edit, + SequenceNumber* max_sequence, + MemTable* external_table); + + // The following two methods are used to flush a memtable to + // storage. The first one is used atdatabase RecoveryTime (when the + // database is opened) and is heavyweight because it holds the mutex + // for the entire period. The second method WriteLevel0Table supports + // concurrent flush memtables to storage. + Status WriteLevel0TableForRecovery(MemTable* mem, VersionEdit* edit); + Status WriteLevel0Table(MemTable* mem, VersionEdit* edit, + uint64_t* filenumber); + + Status MakeRoomForWrite(bool force /* compact even if there is room? */); + WriteBatch* BuildBatchGroup(Writer** last_writer); + + // Force current memtable contents to be flushed. + Status FlushMemTable(const FlushOptions& options); + + // Wait for memtable compaction + Status WaitForCompactMemTable(); + + void MaybeScheduleLogDBDeployStats(); + static void BGLogDBDeployStats(void* db); + void LogDBDeployStats(); + + void MaybeScheduleCompaction(); + static void BGWork(void* db); + void BackgroundCall(); + Status BackgroundCompaction(bool* madeProgress, DeletionState& deletion_state); + void CleanupCompaction(CompactionState* compact); + Status DoCompactionWork(CompactionState* compact); + + Status OpenCompactionOutputFile(CompactionState* compact); + Status FinishCompactionOutputFile(CompactionState* compact, Iterator* input); + Status InstallCompactionResults(CompactionState* compact); + void AllocateCompactionOutputFileNumbers(CompactionState* compact); + void ReleaseCompactionUnusedFileNumbers(CompactionState* compact); + + + // Returns the list of live files in 'live' and the list + // of all files in the filesystem in 'allfiles'. + void FindObsoleteFiles(DeletionState& deletion_state); + + // Diffs the files listed in filenames and those that do not + // belong to live files are posibly removed. If the removed file + // is a sst file, then it returns the file number in files_to_evict. + void PurgeObsoleteFiles(DeletionState& deletion_state); + + // Removes the file listed in files_to_evict from the table_cache + void EvictObsoleteFiles(DeletionState& deletion_state); + + void PurgeObsoleteWALFiles(); + + Status ListAllWALFiles(const std::string& path, + std::vector* logFiles, + WalFileType type); + + // Find's all the log files which contain updates with seq no. + // Greater Than or Equal to the requested SequenceNumber + Status FindProbableWALFiles(std::vector* const allLogs, + std::vector* const result, + const SequenceNumber target); + + + Status ReadFirstRecord(const LogFile& file, WriteBatch* const result); + + + Status ReadFirstLine(const std::string& fname, WriteBatch* const batch); + // Constant after construction + const InternalFilterPolicy internal_filter_policy_; + bool owns_info_log_; + + // table_cache_ provides its own synchronization + unique_ptr table_cache_; + + // Lock over the persistent DB state. Non-nullptr iff successfully acquired. + FileLock* db_lock_; + + // State below is protected by mutex_ + port::Mutex mutex_; + port::AtomicPointer shutting_down_; + port::CondVar bg_cv_; // Signalled when background work finishes + MemTable* mem_; + MemTableList imm_; // Memtable that are not changing + uint64_t logfile_number_; + unique_ptr log_; + + std::string host_name_; + + // Queue of writers. + std::deque writers_; + WriteBatch* tmp_batch_; + + SnapshotList snapshots_; + + // Set of table files to protect from deletion because they are + // part of ongoing compactions. + std::set pending_outputs_; + + // count how many background compaction been scheduled or is running? + int bg_compaction_scheduled_; + + // Has a background stats log thread scheduled? + bool bg_logstats_scheduled_; + + // Information for a manual compaction + struct ManualCompaction { + int level; + bool done; + bool in_progress; // compaction request being processed? + const InternalKey* begin; // nullptr means beginning of key range + const InternalKey* end; // nullptr means end of key range + InternalKey tmp_storage; // Used to keep track of compaction progress + }; + ManualCompaction* manual_compaction_; + + // Have we encountered a background error in paranoid mode? + Status bg_error_; + + StatsLogger* logger_; + + int64_t volatile last_log_ts; + + // shall we disable deletion of obsolete files + bool disable_delete_obsolete_files_; + + // last time when DeleteObsoleteFiles was invoked + uint64_t delete_obsolete_files_last_run_; + + // These count the number of microseconds for which MakeRoomForWrite stalls. + uint64_t stall_level0_slowdown_; + uint64_t stall_memtable_compaction_; + uint64_t stall_level0_num_files_; + std::vector stall_leveln_slowdown_; + + // Time at which this instance was started. + const uint64_t started_at_; + + bool flush_on_destroy_; // Used when disableWAL is true. + + // Per level compaction stats. stats_[level] stores the stats for + // compactions that produced data for the specified "level". + struct CompactionStats { + uint64_t micros; + + // Bytes read from level N during compaction between levels N and N+1 + int64_t bytes_readn; + + // Bytes read from level N+1 during compaction between levels N and N+1 + int64_t bytes_readnp1; + + // Total bytes written during compaction between levels N and N+1 + int64_t bytes_written; + + // Files read from level N during compaction between levels N and N+1 + int files_in_leveln; + + // Files read from level N+1 during compaction between levels N and N+1 + int files_in_levelnp1; + + // Files written during compaction between levels N and N+1 + int files_out_levelnp1; + + // Number of compactions done + int count; + + CompactionStats() : micros(0), bytes_readn(0), bytes_readnp1(0), + bytes_written(0), files_in_leveln(0), + files_in_levelnp1(0), files_out_levelnp1(0), + count(0) { } + + void Add(const CompactionStats& c) { + this->micros += c.micros; + this->bytes_readn += c.bytes_readn; + this->bytes_readnp1 += c.bytes_readnp1; + this->bytes_written += c.bytes_written; + this->files_in_leveln += c.files_in_leveln; + this->files_in_levelnp1 += c.files_in_levelnp1; + this->files_out_levelnp1 += c.files_out_levelnp1; + this->count += 1; + } + }; + + CompactionStats* stats_; + + static const int KEEP_LOG_FILE_NUM = 1000; + std::string db_absolute_path_; + + // count of the number of contiguous delaying writes + int delayed_writes_; + + // store the last flushed sequence. + // Used by transaction log iterator. + SequenceNumber last_flushed_sequence_; + + // No copying allowed + DBImpl(const DBImpl&); + void operator=(const DBImpl&); + + // dump the delayed_writes_ to the log file and reset counter. + void DelayLoggingAndReset(); + + // find the earliest snapshot where seqno is visible + inline SequenceNumber findEarliestVisibleSnapshot(SequenceNumber in, + std::vector& snapshots); +}; + +// Sanitize db options. The caller should delete result.info_log if +// it is not equal to src.info_log. +extern Options SanitizeOptions(const std::string& db, + const InternalKeyComparator* icmp, + const InternalFilterPolicy* ipolicy, + const Options& src); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_DB_IMPL_H_ diff --git a/db/db_impl_readonly.cc b/db/db_impl_readonly.cc new file mode 100644 index 00000000..28d9be45 --- /dev/null +++ b/db/db_impl_readonly.cc @@ -0,0 +1,94 @@ +// Copyright (c) 2012 Facebook. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "db/db_impl_readonly.h" +#include "db/db_impl.h" + +#include +#include +#include +#include +#include +#include +#include +#include "db/db_iter.h" +#include "db/dbformat.h" +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "db/memtable.h" +#include "db/table_cache.h" +#include "db/version_set.h" +#include "db/write_batch_internal.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/status.h" +#include "leveldb/table.h" +#include "leveldb/table_builder.h" +#include "port/port.h" +#include "table/block.h" +#include "table/merger.h" +#include "table/two_level_iterator.h" +#include "util/coding.h" +#include "util/logging.h" +#include "util/build_version.h" + +namespace leveldb { + +DBImplReadOnly::DBImplReadOnly(const Options& options, + const std::string& dbname) + : DBImpl(options, dbname) { + Log(options_.info_log, "Opening the db in read only mode"); +} + +DBImplReadOnly::~DBImplReadOnly() { +} + +// Implementations of the DB interface +Status DBImplReadOnly::Get(const ReadOptions& options, + const Slice& key, + std::string* value) { + Status s; + MemTable* mem = GetMemTable(); + Version* current = versions_->current(); + SequenceNumber snapshot = versions_->LastSequence(); + LookupKey lkey(key, snapshot); + if (mem->Get(lkey, value, &s)) { + } else { + Version::GetStats stats; + s = current->Get(options, lkey, value, &stats); + } + return s; +} + +Iterator* DBImplReadOnly::NewIterator(const ReadOptions& options) { + SequenceNumber latest_snapshot; + Iterator* internal_iter = NewInternalIterator(options, &latest_snapshot); + return NewDBIterator( + &dbname_, env_, user_comparator(), internal_iter, + (options.snapshot != nullptr + ? reinterpret_cast(options.snapshot)->number_ + : latest_snapshot)); +} + + +Status DB::OpenForReadOnly(const Options& options, const std::string& dbname, + DB** dbptr, bool error_if_log_file_exist) { + *dbptr = nullptr; + + DBImplReadOnly* impl = new DBImplReadOnly(options, dbname); + impl->mutex_.Lock(); + VersionEdit edit(impl->NumberLevels()); + Status s = impl->Recover(&edit, impl->GetMemTable(), + error_if_log_file_exist); + impl->mutex_.Unlock(); + if (s.ok()) { + *dbptr = impl; + } else { + delete impl; + } + return s; +} + +} diff --git a/db/db_impl_readonly.h b/db/db_impl_readonly.h new file mode 100644 index 00000000..403b3545 --- /dev/null +++ b/db/db_impl_readonly.h @@ -0,0 +1,72 @@ +// Copyright (c) 2012 Facebook. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef STORAGE_LEVELDB_DB_DB_IMPL_READONLY_H_ +#define STORAGE_LEVELDB_DB_DB_IMPL_READONLY_H_ + +#include "db/db_impl.h" + +#include +#include +#include "db/dbformat.h" +#include "db/log_writer.h" +#include "db/snapshot.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "port/port.h" +#include "util/stats_logger.h" + +#ifdef USE_SCRIBE +#include "scribe/scribe_logger.h" +#endif + +namespace leveldb { + +class DBImplReadOnly : public DBImpl { +public: + DBImplReadOnly(const Options& options, const std::string& dbname); + virtual ~DBImplReadOnly(); + + // Implementations of the DB interface + virtual Status Get(const ReadOptions& options, + const Slice& key, + std::string* value); + virtual Iterator* NewIterator(const ReadOptions&); + + virtual Status Put(const WriteOptions&, const Slice& key, const Slice& value) { + return Status::NotSupported("Not supported operation in read only mode."); + } + virtual Status Delete(const WriteOptions&, const Slice& key) { + return Status::NotSupported("Not supported operation in read only mode."); + } + virtual Status Write(const WriteOptions& options, WriteBatch* updates) { + return Status::NotSupported("Not supported operation in read only mode."); + } + virtual void CompactRange(const Slice* begin, const Slice* end) { + } + virtual Status DisableFileDeletions() { + return Status::NotSupported("Not supported operation in read only mode."); + } + virtual Status EnableFileDeletions() { + return Status::NotSupported("Not supported operation in read only mode."); + } + virtual Status GetLiveFiles(std::vector&, + uint64_t* manifest_file_size) { + return Status::NotSupported("Not supported operation in read only mode."); + } + virtual Status Flush(const FlushOptions& options) { + return Status::NotSupported("Not supported operation in read only mode."); + } + +private: + friend class DB; + + // No copying allowed + DBImplReadOnly(const DBImplReadOnly&); + void operator=(const DBImplReadOnly&); +}; + +} + +#endif diff --git a/db/db_iter.cc b/db/db_iter.cc new file mode 100644 index 00000000..87dca2de --- /dev/null +++ b/db/db_iter.cc @@ -0,0 +1,299 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/db_iter.h" + +#include "db/filename.h" +#include "db/dbformat.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "port/port.h" +#include "util/logging.h" +#include "util/mutexlock.h" + +namespace leveldb { + +#if 0 +static void DumpInternalIter(Iterator* iter) { + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + ParsedInternalKey k; + if (!ParseInternalKey(iter->key(), &k)) { + fprintf(stderr, "Corrupt '%s'\n", EscapeString(iter->key()).c_str()); + } else { + fprintf(stderr, "@ '%s'\n", k.DebugString().c_str()); + } + } +} +#endif + +namespace { + +// Memtables and sstables that make the DB representation contain +// (userkey,seq,type) => uservalue entries. DBIter +// combines multiple entries for the same userkey found in the DB +// representation into a single entry while accounting for sequence +// numbers, deletion markers, overwrites, etc. +class DBIter: public Iterator { + public: + // Which direction is the iterator currently moving? + // (1) When moving forward, the internal iterator is positioned at + // the exact entry that yields this->key(), this->value() + // (2) When moving backwards, the internal iterator is positioned + // just before all entries whose user key == this->key(). + enum Direction { + kForward, + kReverse + }; + + DBIter(const std::string* dbname, Env* env, + const Comparator* cmp, Iterator* iter, SequenceNumber s) + : dbname_(dbname), + env_(env), + user_comparator_(cmp), + iter_(iter), + sequence_(s), + direction_(kForward), + valid_(false) { + } + virtual ~DBIter() { + delete iter_; + } + virtual bool Valid() const { return valid_; } + virtual Slice key() const { + assert(valid_); + return (direction_ == kForward) ? ExtractUserKey(iter_->key()) : saved_key_; + } + virtual Slice value() const { + assert(valid_); + return (direction_ == kForward) ? iter_->value() : saved_value_; + } + virtual Status status() const { + if (status_.ok()) { + return iter_->status(); + } else { + return status_; + } + } + + virtual void Next(); + virtual void Prev(); + virtual void Seek(const Slice& target); + virtual void SeekToFirst(); + virtual void SeekToLast(); + + private: + void FindNextUserEntry(bool skipping, std::string* skip); + void FindPrevUserEntry(); + bool ParseKey(ParsedInternalKey* key); + + inline void SaveKey(const Slice& k, std::string* dst) { + dst->assign(k.data(), k.size()); + } + + inline void ClearSavedValue() { + if (saved_value_.capacity() > 1048576) { + std::string empty; + swap(empty, saved_value_); + } else { + saved_value_.clear(); + } + } + + const std::string* const dbname_; + Env* const env_; + const Comparator* const user_comparator_; + Iterator* const iter_; + SequenceNumber const sequence_; + + Status status_; + std::string saved_key_; // == current key when direction_==kReverse + std::string saved_value_; // == current raw value when direction_==kReverse + Direction direction_; + bool valid_; + + // No copying allowed + DBIter(const DBIter&); + void operator=(const DBIter&); +}; + +inline bool DBIter::ParseKey(ParsedInternalKey* ikey) { + if (!ParseInternalKey(iter_->key(), ikey)) { + status_ = Status::Corruption("corrupted internal key in DBIter"); + return false; + } else { + return true; + } +} + +void DBIter::Next() { + assert(valid_); + + if (direction_ == kReverse) { // Switch directions? + direction_ = kForward; + // iter_ is pointing just before the entries for this->key(), + // so advance into the range of entries for this->key() and then + // use the normal skipping code below. + if (!iter_->Valid()) { + iter_->SeekToFirst(); + } else { + iter_->Next(); + } + if (!iter_->Valid()) { + valid_ = false; + saved_key_.clear(); + return; + } + } + + // Temporarily use saved_key_ as storage for key to skip. + std::string* skip = &saved_key_; + SaveKey(ExtractUserKey(iter_->key()), skip); + FindNextUserEntry(true, skip); +} + +void DBIter::FindNextUserEntry(bool skipping, std::string* skip) { + // Loop until we hit an acceptable entry to yield + assert(iter_->Valid()); + assert(direction_ == kForward); + do { + ParsedInternalKey ikey; + if (ParseKey(&ikey) && ikey.sequence <= sequence_) { + switch (ikey.type) { + case kTypeDeletion: + // Arrange to skip all upcoming entries for this key since + // they are hidden by this deletion. + SaveKey(ikey.user_key, skip); + skipping = true; + break; + case kTypeValue: + if (skipping && + user_comparator_->Compare(ikey.user_key, *skip) <= 0) { + // Entry hidden + } else { + valid_ = true; + saved_key_.clear(); + return; + } + break; + } + } + iter_->Next(); + } while (iter_->Valid()); + saved_key_.clear(); + valid_ = false; +} + +void DBIter::Prev() { + assert(valid_); + + if (direction_ == kForward) { // Switch directions? + // iter_ is pointing at the current entry. Scan backwards until + // the key changes so we can use the normal reverse scanning code. + assert(iter_->Valid()); // Otherwise valid_ would have been false + SaveKey(ExtractUserKey(iter_->key()), &saved_key_); + while (true) { + iter_->Prev(); + if (!iter_->Valid()) { + valid_ = false; + saved_key_.clear(); + ClearSavedValue(); + return; + } + if (user_comparator_->Compare(ExtractUserKey(iter_->key()), + saved_key_) < 0) { + break; + } + } + direction_ = kReverse; + } + + FindPrevUserEntry(); +} + +void DBIter::FindPrevUserEntry() { + assert(direction_ == kReverse); + + ValueType value_type = kTypeDeletion; + if (iter_->Valid()) { + do { + ParsedInternalKey ikey; + if (ParseKey(&ikey) && ikey.sequence <= sequence_) { + if ((value_type != kTypeDeletion) && + user_comparator_->Compare(ikey.user_key, saved_key_) < 0) { + // We encountered a non-deleted value in entries for previous keys, + break; + } + value_type = ikey.type; + if (value_type == kTypeDeletion) { + saved_key_.clear(); + ClearSavedValue(); + } else { + Slice raw_value = iter_->value(); + if (saved_value_.capacity() > raw_value.size() + 1048576) { + std::string empty; + swap(empty, saved_value_); + } + SaveKey(ExtractUserKey(iter_->key()), &saved_key_); + saved_value_.assign(raw_value.data(), raw_value.size()); + } + } + iter_->Prev(); + } while (iter_->Valid()); + } + + if (value_type == kTypeDeletion) { + // End + valid_ = false; + saved_key_.clear(); + ClearSavedValue(); + direction_ = kForward; + } else { + valid_ = true; + } +} + +void DBIter::Seek(const Slice& target) { + direction_ = kForward; + ClearSavedValue(); + saved_key_.clear(); + AppendInternalKey( + &saved_key_, ParsedInternalKey(target, sequence_, kValueTypeForSeek)); + iter_->Seek(saved_key_); + if (iter_->Valid()) { + FindNextUserEntry(false, &saved_key_ /* temporary storage */); + } else { + valid_ = false; + } +} + +void DBIter::SeekToFirst() { + direction_ = kForward; + ClearSavedValue(); + iter_->SeekToFirst(); + if (iter_->Valid()) { + FindNextUserEntry(false, &saved_key_ /* temporary storage */); + } else { + valid_ = false; + } +} + +void DBIter::SeekToLast() { + direction_ = kReverse; + ClearSavedValue(); + iter_->SeekToLast(); + FindPrevUserEntry(); +} + +} // anonymous namespace + +Iterator* NewDBIterator( + const std::string* dbname, + Env* env, + const Comparator* user_key_comparator, + Iterator* internal_iter, + const SequenceNumber& sequence) { + return new DBIter(dbname, env, user_key_comparator, internal_iter, sequence); +} + +} // namespace leveldb diff --git a/db/db_iter.h b/db/db_iter.h new file mode 100644 index 00000000..d9e1b174 --- /dev/null +++ b/db/db_iter.h @@ -0,0 +1,26 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_DB_ITER_H_ +#define STORAGE_LEVELDB_DB_DB_ITER_H_ + +#include +#include "leveldb/db.h" +#include "db/dbformat.h" + +namespace leveldb { + +// Return a new iterator that converts internal keys (yielded by +// "*internal_iter") that were live at the specified "sequence" number +// into appropriate user keys. +extern Iterator* NewDBIterator( + const std::string* dbname, + Env* env, + const Comparator* user_key_comparator, + Iterator* internal_iter, + const SequenceNumber& sequence); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_DB_ITER_H_ diff --git a/db/db_statistics.h b/db/db_statistics.h new file mode 100644 index 00000000..de61edd5 --- /dev/null +++ b/db/db_statistics.h @@ -0,0 +1,60 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef LEVELDB_STORAGE_DB_DB_STATISTICS_H_ +#define LEVELDB_STORAGE_DB_DB_STATISTICS_H_ + +#include +#include +#include + +#include "leveldb/statistics.h" +#include "util/histogram.h" +#include "port/port.h" +#include "util/mutexlock.h" + + +namespace leveldb { + +class DBStatistics: public Statistics { + public: + DBStatistics() : allTickers_(TICKER_ENUM_MAX), + allHistograms_(HISTOGRAM_ENUM_MAX) { } + + virtual ~DBStatistics() {} + + virtual long getTickerCount(Tickers tickerType) { + assert(tickerType < TICKER_ENUM_MAX); + return allTickers_[tickerType].getCount(); + } + + virtual void recordTick(Tickers tickerType, uint64_t count) { + assert(tickerType < TICKER_ENUM_MAX); + allTickers_[tickerType].recordTick(count); + } + + virtual void measureTime(Histograms histogramType, uint64_t value) { + assert(histogramType < HISTOGRAM_ENUM_MAX); + allHistograms_[histogramType].Add(value); + } + + virtual void measureTime(Histograms histogramType, double value) { + assert(histogramType < HISTOGRAM_ENUM_MAX); + allHistograms_[histogramType].Add(value); + } + + virtual void histogramData(Histograms histogramType, + HistogramData * const data) { + assert(histogramType < HISTOGRAM_ENUM_MAX); + allHistograms_[histogramType].Data(data); + } + + std::vector allTickers_; + std::vector allHistograms_; +}; +} // namespace leveldb + +#endif // LEVELDB_STORAGE_DB_DB_STATISTICS_H_ + + diff --git a/db/db_stats_logger.cc b/db/db_stats_logger.cc new file mode 100644 index 00000000..4fd0f910 --- /dev/null +++ b/db/db_stats_logger.cc @@ -0,0 +1,88 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/db_impl.h" +#include +#include +#include +#include "db/version_set.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "port/port.h" +#include "util/mutexlock.h" + +namespace leveldb { + +void DBImpl::MaybeScheduleLogDBDeployStats() { + + // There is a lock in the actual logger. + if (!logger_ || options_.db_stats_log_interval < 0 + || host_name_.empty()) { + return; + } + + if(bg_logstats_scheduled_ || shutting_down_.Acquire_Load()) { + // Already scheduled + } else { + int64_t current_ts = 0; + Status st = env_->GetCurrentTime(¤t_ts); + if (!st.ok()) { + return; + } + if ((current_ts - last_log_ts) < options_.db_stats_log_interval) { + return; + } + last_log_ts = current_ts; + bg_logstats_scheduled_ = true; + env_->Schedule(&DBImpl::BGLogDBDeployStats, this); + } +} + +void DBImpl::BGLogDBDeployStats(void* db) { + DBImpl* db_inst = reinterpret_cast(db); + db_inst->LogDBDeployStats(); +} + +void DBImpl::LogDBDeployStats() { + mutex_.Lock(); + + if (shutting_down_.Acquire_Load()) { + bg_logstats_scheduled_ = false; + bg_cv_.SignalAll(); + mutex_.Unlock(); + return; + } + + char tmp_ver[100]; + sprintf(tmp_ver, "%d.%d", kMajorVersion, kMinorVersion); + std::string version_info(tmp_ver); + + uint64_t file_total_size = 0; + uint32_t file_total_num = 0; + for (int i = 0; i < versions_->NumberLevels(); i++) { + file_total_num += versions_->NumLevelFiles(i); + file_total_size += versions_->NumLevelBytes(i); + } + + VersionSet::LevelSummaryStorage scratch; + const char* file_num_summary = versions_->LevelSummary(&scratch); + std::string file_num_per_level(file_num_summary); + std::string data_size_per_level(file_num_summary); + + mutex_.Unlock(); + + int64_t unix_ts; + env_->GetCurrentTime(&unix_ts); + + logger_->Log_Deploy_Stats(version_info, host_name_, + db_absolute_path_, file_total_size, file_total_num, file_num_per_level, + data_size_per_level, unix_ts); + + mutex_.Lock(); + bg_logstats_scheduled_ = false; + bg_cv_.SignalAll(); + mutex_.Unlock(); +} + +} diff --git a/db/db_test.cc b/db/db_test.cc new file mode 100644 index 00000000..fcdb4917 --- /dev/null +++ b/db/db_test.cc @@ -0,0 +1,3135 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include + +#include "leveldb/db.h" +#include "leveldb/filter_policy.h" +#include "db/db_impl.h" +#include "db/filename.h" +#include "db/version_set.h" +#include "db/write_batch_internal.h" +#include "leveldb/cache.h" +#include "leveldb/env.h" +#include "leveldb/table.h" +#include "util/hash.h" +#include "util/logging.h" +#include "util/mutexlock.h" +#include "util/testharness.h" +#include "util/testutil.h" + +namespace leveldb { + +static bool SnappyCompressionSupported(const CompressionOptions& options) { + std::string out; + Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + return port::Snappy_Compress(options, in.data(), in.size(), &out); +} + +static bool ZlibCompressionSupported(const CompressionOptions& options) { + std::string out; + Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + return port::Zlib_Compress(options, in.data(), in.size(), &out); +} + +static bool BZip2CompressionSupported(const CompressionOptions& options) { + std::string out; + Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + return port::BZip2_Compress(options, in.data(), in.size(), &out); +} + +static std::string RandomString(Random* rnd, int len) { + std::string r; + test::RandomString(rnd, len, &r); + return r; +} + +namespace anon { +class AtomicCounter { + private: + port::Mutex mu_; + int count_; + public: + AtomicCounter() : count_(0) { } + void Increment() { + MutexLock l(&mu_); + count_++; + } + int Read() { + MutexLock l(&mu_); + return count_; + } + void Reset() { + MutexLock l(&mu_); + count_ = 0; + } +}; +} + +// Special Env used to delay background operations +class SpecialEnv : public EnvWrapper { + public: + // sstable Sync() calls are blocked while this pointer is non-nullptr. + port::AtomicPointer delay_sstable_sync_; + + // Simulate no-space errors while this pointer is non-nullptr. + port::AtomicPointer no_space_; + + // Simulate non-writable file system while this pointer is non-nullptr + port::AtomicPointer non_writable_; + + // Force sync of manifest files to fail while this pointer is non-nullptr + port::AtomicPointer manifest_sync_error_; + + // Force write to manifest files to fail while this pointer is non-nullptr + port::AtomicPointer manifest_write_error_; + + bool count_random_reads_; + anon::AtomicCounter random_read_counter_; + + anon::AtomicCounter sleep_counter_; + + explicit SpecialEnv(Env* base) : EnvWrapper(base) { + delay_sstable_sync_.Release_Store(nullptr); + no_space_.Release_Store(nullptr); + non_writable_.Release_Store(nullptr); + count_random_reads_ = false; + manifest_sync_error_.Release_Store(nullptr); + manifest_write_error_.Release_Store(nullptr); + } + + Status NewWritableFile(const std::string& f, unique_ptr* r) { + class SSTableFile : public WritableFile { + private: + SpecialEnv* env_; + unique_ptr base_; + + public: + SSTableFile(SpecialEnv* env, unique_ptr&& base) + : env_(env), + base_(std::move(base)) { + } + Status Append(const Slice& data) { + if (env_->no_space_.Acquire_Load() != nullptr) { + // Drop writes on the floor + return Status::OK(); + } else { + return base_->Append(data); + } + } + Status Close() { return base_->Close(); } + Status Flush() { return base_->Flush(); } + Status Sync() { + while (env_->delay_sstable_sync_.Acquire_Load() != nullptr) { + env_->SleepForMicroseconds(100000); + } + return base_->Sync(); + } + }; + class ManifestFile : public WritableFile { + private: + SpecialEnv* env_; + unique_ptr base_; + public: + ManifestFile(SpecialEnv* env, unique_ptr&& b) + : env_(env), base_(std::move(b)) { } + Status Append(const Slice& data) { + if (env_->manifest_write_error_.Acquire_Load() != nullptr) { + return Status::IOError("simulated writer error"); + } else { + return base_->Append(data); + } + } + Status Close() { return base_->Close(); } + Status Flush() { return base_->Flush(); } + Status Sync() { + if (env_->manifest_sync_error_.Acquire_Load() != nullptr) { + return Status::IOError("simulated sync error"); + } else { + return base_->Sync(); + } + } + }; + + if (non_writable_.Acquire_Load() != nullptr) { + return Status::IOError("simulated write error"); + } + + Status s = target()->NewWritableFile(f, r); + if (s.ok()) { + if (strstr(f.c_str(), ".sst") != nullptr) { + r->reset(new SSTableFile(this, std::move(*r))); + } else if (strstr(f.c_str(), "MANIFEST") != nullptr) { + r->reset(new ManifestFile(this, std::move(*r))); + } + } + return s; + } + + Status NewRandomAccessFile(const std::string& f, + unique_ptr* r) { + class CountingFile : public RandomAccessFile { + private: + unique_ptr target_; + anon::AtomicCounter* counter_; + public: + CountingFile(unique_ptr&& target, + anon::AtomicCounter* counter) + : target_(std::move(target)), counter_(counter) { + } + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const { + counter_->Increment(); + return target_->Read(offset, n, result, scratch); + } + }; + + Status s = target()->NewRandomAccessFile(f, r); + if (s.ok() && count_random_reads_) { + r->reset(new CountingFile(std::move(*r), &random_read_counter_)); + } + return s; + } + + virtual void SleepForMicroseconds(int micros) { + sleep_counter_.Increment(); + target()->SleepForMicroseconds(micros); + } +}; + +class DBTest { + private: + const FilterPolicy* filter_policy_; + + // Sequence of option configurations to try + enum OptionConfig { + kDefault, + kFilter, + kUncompressed, + kNumLevel_3, + kDBLogDir, + kManifestFileSize, + kCompactOnFlush, + kPerfOptions, + kEnd + }; + int option_config_; + + public: + std::string dbname_; + SpecialEnv* env_; + DB* db_; + + Options last_options_; + + DBTest() : option_config_(kDefault), + env_(new SpecialEnv(Env::Default())) { + filter_policy_ = NewBloomFilterPolicy(10); + dbname_ = test::TmpDir() + "/db_test"; + DestroyDB(dbname_, Options()); + db_ = nullptr; + Reopen(); + } + + ~DBTest() { + delete db_; + DestroyDB(dbname_, Options()); + delete env_; + delete filter_policy_; + } + + // Switch to a fresh database with the next option configuration to + // test. Return false if there are no more configurations to test. + bool ChangeOptions() { + option_config_++; + if (option_config_ >= kEnd) { + return false; + } else { + DestroyAndReopen(); + return true; + } + } + + // Return the current option configuration. + Options CurrentOptions() { + Options options; + switch (option_config_) { + case kFilter: + options.filter_policy = filter_policy_; + break; + case kUncompressed: + options.compression = kNoCompression; + break; + case kNumLevel_3: + options.num_levels = 3; + break; + case kDBLogDir: + options.db_log_dir = test::TmpDir(); + break; + case kManifestFileSize: + options.max_manifest_file_size = 50; // 50 bytes + case kCompactOnFlush: + options.purge_redundant_kvs_while_flush = !options.purge_redundant_kvs_while_flush; + break; + case kPerfOptions: + options.rate_limit = 2.0; + options.rate_limit_delay_milliseconds = 2; + // TODO -- test more options + break; + default: + break; + } + return options; + } + + DBImpl* dbfull() { + return reinterpret_cast(db_); + } + + void Reopen(Options* options = nullptr) { + ASSERT_OK(TryReopen(options)); + } + + void Close() { + delete db_; + db_ = nullptr; + } + + void DestroyAndReopen(Options* options = nullptr) { + delete db_; + db_ = nullptr; + DestroyDB(dbname_, Options()); + ASSERT_OK(TryReopen(options)); + } + + Status PureReopen(Options* options, DB** db) { + return DB::Open(*options, dbname_, db); + } + + Status TryReopen(Options* options) { + delete db_; + db_ = nullptr; + Options opts; + if (options != nullptr) { + opts = *options; + } else { + opts = CurrentOptions(); + opts.create_if_missing = true; + } + last_options_ = opts; + + return DB::Open(opts, dbname_, &db_); + } + + Status Put(const std::string& k, const std::string& v) { + return db_->Put(WriteOptions(), k, v); + } + + Status Delete(const std::string& k) { + return db_->Delete(WriteOptions(), k); + } + + std::string Get(const std::string& k, const Snapshot* snapshot = nullptr) { + ReadOptions options; + options.snapshot = snapshot; + std::string result; + Status s = db_->Get(options, k, &result); + if (s.IsNotFound()) { + result = "NOT_FOUND"; + } else if (!s.ok()) { + result = s.ToString(); + } + return result; + } + + // Return a string that contains all key,value pairs in order, + // formatted like "(k1->v1)(k2->v2)". + std::string Contents() { + std::vector forward; + std::string result; + Iterator* iter = db_->NewIterator(ReadOptions()); + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + std::string s = IterStatus(iter); + result.push_back('('); + result.append(s); + result.push_back(')'); + forward.push_back(s); + } + + // Check reverse iteration results are the reverse of forward results + unsigned int matched = 0; + for (iter->SeekToLast(); iter->Valid(); iter->Prev()) { + ASSERT_LT(matched, forward.size()); + ASSERT_EQ(IterStatus(iter), forward[forward.size() - matched - 1]); + matched++; + } + ASSERT_EQ(matched, forward.size()); + + delete iter; + return result; + } + + std::string AllEntriesFor(const Slice& user_key) { + Iterator* iter = dbfull()->TEST_NewInternalIterator(); + InternalKey target(user_key, kMaxSequenceNumber, kTypeValue); + iter->Seek(target.Encode()); + std::string result; + if (!iter->status().ok()) { + result = iter->status().ToString(); + } else { + result = "[ "; + bool first = true; + while (iter->Valid()) { + ParsedInternalKey ikey; + if (!ParseInternalKey(iter->key(), &ikey)) { + result += "CORRUPTED"; + } else { + if (last_options_.comparator->Compare(ikey.user_key, user_key) != 0) { + break; + } + if (!first) { + result += ", "; + } + first = false; + switch (ikey.type) { + case kTypeValue: + result += iter->value().ToString(); + break; + case kTypeDeletion: + result += "DEL"; + break; + } + } + iter->Next(); + } + if (!first) { + result += " "; + } + result += "]"; + } + delete iter; + return result; + } + + int NumTableFilesAtLevel(int level) { + std::string property; + ASSERT_TRUE( + db_->GetProperty("leveldb.num-files-at-level" + NumberToString(level), + &property)); + return atoi(property.c_str()); + } + + int TotalTableFiles() { + int result = 0; + for (int level = 0; level < db_->NumberLevels(); level++) { + result += NumTableFilesAtLevel(level); + } + return result; + } + + // Return spread of files per level + std::string FilesPerLevel() { + std::string result; + int last_non_zero_offset = 0; + for (int level = 0; level < db_->NumberLevels(); level++) { + int f = NumTableFilesAtLevel(level); + char buf[100]; + snprintf(buf, sizeof(buf), "%s%d", (level ? "," : ""), f); + result += buf; + if (f > 0) { + last_non_zero_offset = result.size(); + } + } + result.resize(last_non_zero_offset); + return result; + } + + int CountFiles() { + std::vector files; + env_->GetChildren(dbname_, &files); + return static_cast(files.size()); + } + + int CountLiveFiles() { + std::vector files; + uint64_t manifest_file_size; + db_->GetLiveFiles(files, &manifest_file_size); + return files.size(); + } + + uint64_t Size(const Slice& start, const Slice& limit) { + Range r(start, limit); + uint64_t size; + db_->GetApproximateSizes(&r, 1, &size); + return size; + } + + void Compact(const Slice& start, const Slice& limit) { + db_->CompactRange(&start, &limit); + } + + // Do n memtable compactions, each of which produces an sstable + // covering the range [small,large]. + void MakeTables(int n, const std::string& small, const std::string& large) { + for (int i = 0; i < n; i++) { + Put(small, "begin"); + Put(large, "end"); + dbfull()->TEST_CompactMemTable(); + } + } + + // Prevent pushing of new sstables into deeper levels by adding + // tables that cover a specified range to all levels. + void FillLevels(const std::string& smallest, const std::string& largest) { + MakeTables(db_->NumberLevels(), smallest, largest); + } + + void DumpFileCounts(const char* label) { + fprintf(stderr, "---\n%s:\n", label); + fprintf(stderr, "maxoverlap: %lld\n", + static_cast( + dbfull()->TEST_MaxNextLevelOverlappingBytes())); + for (int level = 0; level < db_->NumberLevels(); level++) { + int num = NumTableFilesAtLevel(level); + if (num > 0) { + fprintf(stderr, " level %3d : %d files\n", level, num); + } + } + } + + std::string DumpSSTableList() { + std::string property; + db_->GetProperty("leveldb.sstables", &property); + return property; + } + + std::string IterStatus(Iterator* iter) { + std::string result; + if (iter->Valid()) { + result = iter->key().ToString() + "->" + iter->value().ToString(); + } else { + result = "(invalid)"; + } + return result; + } +}; + +TEST(DBTest, Empty) { + do { + ASSERT_TRUE(db_ != nullptr); + ASSERT_EQ("NOT_FOUND", Get("foo")); + } while (ChangeOptions()); +} + +TEST(DBTest, ReadWrite) { + do { + ASSERT_OK(Put("foo", "v1")); + ASSERT_EQ("v1", Get("foo")); + ASSERT_OK(Put("bar", "v2")); + ASSERT_OK(Put("foo", "v3")); + ASSERT_EQ("v3", Get("foo")); + ASSERT_EQ("v2", Get("bar")); + } while (ChangeOptions()); +} + +static std::string Key(int i) { + char buf[100]; + snprintf(buf, sizeof(buf), "key%06d", i); + return std::string(buf); +} + +TEST(DBTest, LevelLimitReopen) { + Options options = CurrentOptions(); + Reopen(&options); + + const std::string value(1024 * 1024, ' '); + int i = 0; + while (NumTableFilesAtLevel(2) == 0) { + ASSERT_OK(Put(Key(i++), value)); + } + + options.num_levels = 1; + Status s = TryReopen(&options); + ASSERT_EQ(s.IsCorruption(), true); + ASSERT_EQ(s.ToString(), + "Corruption: VersionEdit: db already has " + "more levels than options.num_levels"); + + options.num_levels = 10; + ASSERT_OK(TryReopen(&options)); +} + +TEST(DBTest, Preallocation) { + const std::string src = dbname_ + "/alloc_test"; + unique_ptr srcfile; + ASSERT_OK(env_->NewWritableFile(src, &srcfile)); + srcfile->SetPreallocationBlockSize(1024 * 1024); + + // No writes should mean no preallocation + size_t block_size, last_allocated_block; + srcfile->GetPreallocationStatus(&block_size, &last_allocated_block); + ASSERT_EQ(last_allocated_block, 0UL); + + // Small write should preallocate one block + srcfile->Append("test"); + srcfile->GetPreallocationStatus(&block_size, &last_allocated_block); + ASSERT_EQ(last_allocated_block, 1UL); + + // Write an entire preallocation block, make sure we increased by two. + std::string buf(block_size, ' '); + srcfile->Append(buf); + srcfile->GetPreallocationStatus(&block_size, &last_allocated_block); + ASSERT_EQ(last_allocated_block, 2UL); + + // Write five more blocks at once, ensure we're where we need to be. + buf = std::string(block_size * 5, ' '); + srcfile->Append(buf); + srcfile->GetPreallocationStatus(&block_size, &last_allocated_block); + ASSERT_EQ(last_allocated_block, 7UL); +} + +TEST(DBTest, PutDeleteGet) { + do { + ASSERT_OK(db_->Put(WriteOptions(), "foo", "v1")); + ASSERT_EQ("v1", Get("foo")); + ASSERT_OK(db_->Put(WriteOptions(), "foo", "v2")); + ASSERT_EQ("v2", Get("foo")); + ASSERT_OK(db_->Delete(WriteOptions(), "foo")); + ASSERT_EQ("NOT_FOUND", Get("foo")); + } while (ChangeOptions()); +} + +TEST(DBTest, GetFromImmutableLayer) { + do { + Options options = CurrentOptions(); + options.env = env_; + options.write_buffer_size = 100000; // Small write buffer + Reopen(&options); + + ASSERT_OK(Put("foo", "v1")); + ASSERT_EQ("v1", Get("foo")); + + env_->delay_sstable_sync_.Release_Store(env_); // Block sync calls + Put("k1", std::string(100000, 'x')); // Fill memtable + Put("k2", std::string(100000, 'y')); // Trigger compaction + ASSERT_EQ("v1", Get("foo")); + env_->delay_sstable_sync_.Release_Store(nullptr); // Release sync calls + } while (ChangeOptions()); +} + +TEST(DBTest, GetFromVersions) { + do { + ASSERT_OK(Put("foo", "v1")); + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ("v1", Get("foo")); + } while (ChangeOptions()); +} + +TEST(DBTest, GetSnapshot) { + do { + // Try with both a short key and a long key + for (int i = 0; i < 2; i++) { + std::string key = (i == 0) ? std::string("foo") : std::string(200, 'x'); + ASSERT_OK(Put(key, "v1")); + const Snapshot* s1 = db_->GetSnapshot(); + ASSERT_OK(Put(key, "v2")); + ASSERT_EQ("v2", Get(key)); + ASSERT_EQ("v1", Get(key, s1)); + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ("v2", Get(key)); + ASSERT_EQ("v1", Get(key, s1)); + db_->ReleaseSnapshot(s1); + } + } while (ChangeOptions()); +} + +TEST(DBTest, GetLevel0Ordering) { + do { + // Check that we process level-0 files in correct order. The code + // below generates two level-0 files where the earlier one comes + // before the later one in the level-0 file list since the earlier + // one has a smaller "smallest" key. + ASSERT_OK(Put("bar", "b")); + ASSERT_OK(Put("foo", "v1")); + dbfull()->TEST_CompactMemTable(); + ASSERT_OK(Put("foo", "v2")); + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ("v2", Get("foo")); + } while (ChangeOptions()); +} + +TEST(DBTest, GetOrderedByLevels) { + do { + ASSERT_OK(Put("foo", "v1")); + Compact("a", "z"); + ASSERT_EQ("v1", Get("foo")); + ASSERT_OK(Put("foo", "v2")); + ASSERT_EQ("v2", Get("foo")); + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ("v2", Get("foo")); + } while (ChangeOptions()); +} + +TEST(DBTest, GetPicksCorrectFile) { + do { + // Arrange to have multiple files in a non-level-0 level. + ASSERT_OK(Put("a", "va")); + Compact("a", "b"); + ASSERT_OK(Put("x", "vx")); + Compact("x", "y"); + ASSERT_OK(Put("f", "vf")); + Compact("f", "g"); + ASSERT_EQ("va", Get("a")); + ASSERT_EQ("vf", Get("f")); + ASSERT_EQ("vx", Get("x")); + } while (ChangeOptions()); +} + +TEST(DBTest, GetEncountersEmptyLevel) { + do { + // Arrange for the following to happen: + // * sstable A in level 0 + // * nothing in level 1 + // * sstable B in level 2 + // Then do enough Get() calls to arrange for an automatic compaction + // of sstable A. A bug would cause the compaction to be marked as + // occuring at level 1 (instead of the correct level 0). + + // Step 1: First place sstables in levels 0 and 2 + int compaction_count = 0; + while (NumTableFilesAtLevel(0) == 0 || + NumTableFilesAtLevel(2) == 0) { + ASSERT_LE(compaction_count, 100) << "could not fill levels 0 and 2"; + compaction_count++; + Put("a", "begin"); + Put("z", "end"); + dbfull()->TEST_CompactMemTable(); + } + + // Step 2: clear level 1 if necessary. + dbfull()->TEST_CompactRange(1, nullptr, nullptr); + ASSERT_EQ(NumTableFilesAtLevel(0), 1); + ASSERT_EQ(NumTableFilesAtLevel(1), 0); + ASSERT_EQ(NumTableFilesAtLevel(2), 1); + + // Step 3: read a bunch of times + for (int i = 0; i < 1000; i++) { + ASSERT_EQ("NOT_FOUND", Get("missing")); + } + + // Step 4: Wait for compaction to finish + env_->SleepForMicroseconds(1000000); + + ASSERT_EQ(NumTableFilesAtLevel(0), 1); // XXX + } while (ChangeOptions()); +} + +TEST(DBTest, IterEmpty) { + Iterator* iter = db_->NewIterator(ReadOptions()); + + iter->SeekToFirst(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + iter->SeekToLast(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + iter->Seek("foo"); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + delete iter; +} + +TEST(DBTest, IterSingle) { + ASSERT_OK(Put("a", "va")); + Iterator* iter = db_->NewIterator(ReadOptions()); + + iter->SeekToFirst(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + iter->SeekToFirst(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + iter->SeekToLast(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + iter->SeekToLast(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + iter->Seek(""); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + iter->Seek("a"); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + iter->Seek("b"); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + delete iter; +} + +TEST(DBTest, IterMulti) { + ASSERT_OK(Put("a", "va")); + ASSERT_OK(Put("b", "vb")); + ASSERT_OK(Put("c", "vc")); + Iterator* iter = db_->NewIterator(ReadOptions()); + + iter->SeekToFirst(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "b->vb"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "c->vc"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + iter->SeekToFirst(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + iter->SeekToLast(); + ASSERT_EQ(IterStatus(iter), "c->vc"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "b->vb"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + iter->SeekToLast(); + ASSERT_EQ(IterStatus(iter), "c->vc"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + iter->Seek(""); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Seek("a"); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Seek("ax"); + ASSERT_EQ(IterStatus(iter), "b->vb"); + iter->Seek("b"); + ASSERT_EQ(IterStatus(iter), "b->vb"); + iter->Seek("z"); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + // Switch from reverse to forward + iter->SeekToLast(); + iter->Prev(); + iter->Prev(); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "b->vb"); + + // Switch from forward to reverse + iter->SeekToFirst(); + iter->Next(); + iter->Next(); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "b->vb"); + + // Make sure iter stays at snapshot + ASSERT_OK(Put("a", "va2")); + ASSERT_OK(Put("a2", "va3")); + ASSERT_OK(Put("b", "vb2")); + ASSERT_OK(Put("c", "vc2")); + ASSERT_OK(Delete("b")); + iter->SeekToFirst(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "b->vb"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "c->vc"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + iter->SeekToLast(); + ASSERT_EQ(IterStatus(iter), "c->vc"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "b->vb"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + delete iter; +} + +TEST(DBTest, IterSmallAndLargeMix) { + ASSERT_OK(Put("a", "va")); + ASSERT_OK(Put("b", std::string(100000, 'b'))); + ASSERT_OK(Put("c", "vc")); + ASSERT_OK(Put("d", std::string(100000, 'd'))); + ASSERT_OK(Put("e", std::string(100000, 'e'))); + + Iterator* iter = db_->NewIterator(ReadOptions()); + + iter->SeekToFirst(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "b->" + std::string(100000, 'b')); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "c->vc"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "d->" + std::string(100000, 'd')); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "e->" + std::string(100000, 'e')); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + iter->SeekToLast(); + ASSERT_EQ(IterStatus(iter), "e->" + std::string(100000, 'e')); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "d->" + std::string(100000, 'd')); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "c->vc"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "b->" + std::string(100000, 'b')); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + delete iter; +} + +TEST(DBTest, IterMultiWithDelete) { + do { + ASSERT_OK(Put("a", "va")); + ASSERT_OK(Put("b", "vb")); + ASSERT_OK(Put("c", "vc")); + ASSERT_OK(Delete("b")); + ASSERT_EQ("NOT_FOUND", Get("b")); + + Iterator* iter = db_->NewIterator(ReadOptions()); + iter->Seek("c"); + ASSERT_EQ(IterStatus(iter), "c->vc"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "a->va"); + delete iter; + } while (ChangeOptions()); +} + +TEST(DBTest, Recover) { + do { + ASSERT_OK(Put("foo", "v1")); + ASSERT_OK(Put("baz", "v5")); + + Reopen(); + ASSERT_EQ("v1", Get("foo")); + + ASSERT_EQ("v1", Get("foo")); + ASSERT_EQ("v5", Get("baz")); + ASSERT_OK(Put("bar", "v2")); + ASSERT_OK(Put("foo", "v3")); + + Reopen(); + ASSERT_EQ("v3", Get("foo")); + ASSERT_OK(Put("foo", "v4")); + ASSERT_EQ("v4", Get("foo")); + ASSERT_EQ("v2", Get("bar")); + ASSERT_EQ("v5", Get("baz")); + } while (ChangeOptions()); +} + +TEST(DBTest, RollLog) { + do { + ASSERT_OK(Put("foo", "v1")); + ASSERT_OK(Put("baz", "v5")); + + Reopen(); + for (int i = 0; i < 10; i++) { + Reopen(); + } + ASSERT_OK(Put("foo", "v4")); + for (int i = 0; i < 10; i++) { + Reopen(); + } + } while (ChangeOptions()); +} + +TEST(DBTest, WAL) { + Options options = CurrentOptions(); + WriteOptions writeOpt = WriteOptions(); + writeOpt.disableWAL = true; + ASSERT_OK(dbfull()->Put(writeOpt, "foo", "v1")); + ASSERT_OK(dbfull()->Put(writeOpt, "bar", "v1")); + + Reopen(); + ASSERT_EQ("v1", Get("foo")); + ASSERT_EQ("v1", Get("bar")); + + writeOpt.disableWAL = false; + ASSERT_OK(dbfull()->Put(writeOpt, "bar", "v2")); + writeOpt.disableWAL = true; + ASSERT_OK(dbfull()->Put(writeOpt, "foo", "v2")); + + Reopen(); + // Both value's should be present. + ASSERT_EQ("v2", Get("bar")); + ASSERT_EQ("v2", Get("foo")); + + writeOpt.disableWAL = true; + ASSERT_OK(dbfull()->Put(writeOpt, "bar", "v3")); + writeOpt.disableWAL = false; + ASSERT_OK(dbfull()->Put(writeOpt, "foo", "v3")); + + Reopen(); + // again both values should be present. + ASSERT_EQ("v3", Get("foo")); + ASSERT_EQ("v3", Get("bar")); +} + +TEST(DBTest, CheckLock) { + DB* localdb; + Options options = CurrentOptions(); + ASSERT_TRUE(TryReopen(&options).ok()); + ASSERT_TRUE(!(PureReopen(&options, &localdb).ok())); // second open should fail +} + +TEST(DBTest, FLUSH) { + Options options = CurrentOptions(); + WriteOptions writeOpt = WriteOptions(); + writeOpt.disableWAL = true; + ASSERT_OK(dbfull()->Put(writeOpt, "foo", "v1")); + // this will now also flush the last 2 writes + dbfull()->Flush(FlushOptions()); + ASSERT_OK(dbfull()->Put(writeOpt, "bar", "v1")); + + Reopen(); + ASSERT_EQ("v1", Get("foo")); + ASSERT_EQ("v1", Get("bar")); + + writeOpt.disableWAL = true; + ASSERT_OK(dbfull()->Put(writeOpt, "bar", "v2")); + ASSERT_OK(dbfull()->Put(writeOpt, "foo", "v2")); + dbfull()->Flush(FlushOptions()); + + Reopen(); + ASSERT_EQ("v2", Get("bar")); + ASSERT_EQ("v2", Get("foo")); + + writeOpt.disableWAL = false; + ASSERT_OK(dbfull()->Put(writeOpt, "bar", "v3")); + ASSERT_OK(dbfull()->Put(writeOpt, "foo", "v3")); + dbfull()->Flush(FlushOptions()); + + Reopen(); + // 'foo' should be there because its put + // has WAL enabled. + ASSERT_EQ("v3", Get("foo")); + ASSERT_EQ("v3", Get("bar")); +} + +TEST(DBTest, RecoveryWithEmptyLog) { + do { + ASSERT_OK(Put("foo", "v1")); + ASSERT_OK(Put("foo", "v2")); + Reopen(); + Reopen(); + ASSERT_OK(Put("foo", "v3")); + Reopen(); + ASSERT_EQ("v3", Get("foo")); + } while (ChangeOptions()); +} + +// Check that writes done during a memtable compaction are recovered +// if the database is shutdown during the memtable compaction. +TEST(DBTest, RecoverDuringMemtableCompaction) { + do { + Options options = CurrentOptions(); + options.env = env_; + options.write_buffer_size = 1000000; + Reopen(&options); + + // Trigger a long memtable compaction and reopen the database during it + ASSERT_OK(Put("foo", "v1")); // Goes to 1st log file + ASSERT_OK(Put("big1", std::string(10000000, 'x'))); // Fills memtable + ASSERT_OK(Put("big2", std::string(1000, 'y'))); // Triggers compaction + ASSERT_OK(Put("bar", "v2")); // Goes to new log file + + Reopen(&options); + ASSERT_EQ("v1", Get("foo")); + ASSERT_EQ("v2", Get("bar")); + ASSERT_EQ(std::string(10000000, 'x'), Get("big1")); + ASSERT_EQ(std::string(1000, 'y'), Get("big2")); + } while (ChangeOptions()); +} + +TEST(DBTest, MinorCompactionsHappen) { + Options options = CurrentOptions(); + options.write_buffer_size = 10000; + Reopen(&options); + + const int N = 500; + + int starting_num_tables = TotalTableFiles(); + for (int i = 0; i < N; i++) { + ASSERT_OK(Put(Key(i), Key(i) + std::string(1000, 'v'))); + } + int ending_num_tables = TotalTableFiles(); + ASSERT_GT(ending_num_tables, starting_num_tables); + + for (int i = 0; i < N; i++) { + ASSERT_EQ(Key(i) + std::string(1000, 'v'), Get(Key(i))); + } + + Reopen(); + + for (int i = 0; i < N; i++) { + ASSERT_EQ(Key(i) + std::string(1000, 'v'), Get(Key(i))); + } +} + +TEST(DBTest, ManifestRollOver) { + Options options = CurrentOptions(); + options.max_manifest_file_size = 10 ; // 10 bytes + Reopen(&options); + { + ASSERT_OK(Put("manifest_key1", std::string(1000, '1'))); + ASSERT_OK(Put("manifest_key2", std::string(1000, '2'))); + ASSERT_OK(Put("manifest_key3", std::string(1000, '3'))); + uint64_t manifest_before_fulsh = + dbfull()->TEST_Current_Manifest_FileNo(); + dbfull()->Flush(FlushOptions()); // This should trigger LogAndApply. + uint64_t manifest_after_flush = + dbfull()->TEST_Current_Manifest_FileNo(); + ASSERT_GT(manifest_after_flush, manifest_before_fulsh); + Reopen(&options); + ASSERT_GT(dbfull()->TEST_Current_Manifest_FileNo(), + manifest_after_flush); + // check if a new manifest file got inserted or not. + ASSERT_EQ(std::string(1000, '1'), Get("manifest_key1")); + ASSERT_EQ(std::string(1000, '2'), Get("manifest_key2")); + ASSERT_EQ(std::string(1000, '3'), Get("manifest_key3")); + } +} + + +TEST(DBTest, RecoverWithLargeLog) { + { + Options options = CurrentOptions(); + Reopen(&options); + ASSERT_OK(Put("big1", std::string(200000, '1'))); + ASSERT_OK(Put("big2", std::string(200000, '2'))); + ASSERT_OK(Put("small3", std::string(10, '3'))); + ASSERT_OK(Put("small4", std::string(10, '4'))); + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + } + + // Make sure that if we re-open with a small write buffer size that + // we flush table files in the middle of a large log file. + Options options = CurrentOptions(); + options.write_buffer_size = 100000; + Reopen(&options); + ASSERT_EQ(NumTableFilesAtLevel(0), 3); + ASSERT_EQ(std::string(200000, '1'), Get("big1")); + ASSERT_EQ(std::string(200000, '2'), Get("big2")); + ASSERT_EQ(std::string(10, '3'), Get("small3")); + ASSERT_EQ(std::string(10, '4'), Get("small4")); + ASSERT_GT(NumTableFilesAtLevel(0), 1); +} + +TEST(DBTest, CompactionsGenerateMultipleFiles) { + Options options = CurrentOptions(); + options.write_buffer_size = 100000000; // Large write buffer + Reopen(&options); + + Random rnd(301); + + // Write 8MB (80 values, each 100K) + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + std::vector values; + for (int i = 0; i < 80; i++) { + values.push_back(RandomString(&rnd, 100000)); + ASSERT_OK(Put(Key(i), values[i])); + } + + // Reopening moves updates to level-0 + Reopen(&options); + dbfull()->TEST_CompactRange(0, nullptr, nullptr); + + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + ASSERT_GT(NumTableFilesAtLevel(1), 1); + for (int i = 0; i < 80; i++) { + ASSERT_EQ(Get(Key(i)), values[i]); + } +} + +TEST(DBTest, CompactionTrigger) { + Options options = CurrentOptions(); + options.write_buffer_size = 100<<10; //100KB + options.num_levels = 3; + options.max_mem_compaction_level = 0; + options.level0_file_num_compaction_trigger = 3; + Reopen(&options); + + Random rnd(301); + + for (int num = 0; + num < options.level0_file_num_compaction_trigger - 1; + num++) { + std::vector values; + // Write 120KB (12 values, each 10K) + for (int i = 0; i < 12; i++) { + values.push_back(RandomString(&rnd, 10000)); + ASSERT_OK(Put(Key(i), values[i])); + } + dbfull()->TEST_WaitForCompactMemTable(); + ASSERT_EQ(NumTableFilesAtLevel(0), num + 1); + } + + //generate one more file in level-0, and should trigger level-0 compaction + std::vector values; + for (int i = 0; i < 12; i++) { + values.push_back(RandomString(&rnd, 10000)); + ASSERT_OK(Put(Key(i), values[i])); + } + dbfull()->TEST_WaitForCompact(); + + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + ASSERT_EQ(NumTableFilesAtLevel(1), 1); +} + +void MinLevelHelper(DBTest* self, Options& options) { + Random rnd(301); + + for (int num = 0; + num < options.level0_file_num_compaction_trigger - 1; + num++) + { + std::vector values; + // Write 120KB (12 values, each 10K) + for (int i = 0; i < 12; i++) { + values.push_back(RandomString(&rnd, 10000)); + ASSERT_OK(self->Put(Key(i), values[i])); + } + self->dbfull()->TEST_WaitForCompactMemTable(); + ASSERT_EQ(self->NumTableFilesAtLevel(0), num + 1); + } + + //generate one more file in level-0, and should trigger level-0 compaction + std::vector values; + for (int i = 0; i < 12; i++) { + values.push_back(RandomString(&rnd, 10000)); + ASSERT_OK(self->Put(Key(i), values[i])); + } + self->dbfull()->TEST_WaitForCompact(); + + ASSERT_EQ(self->NumTableFilesAtLevel(0), 0); + ASSERT_EQ(self->NumTableFilesAtLevel(1), 1); +} + +// returns false if the calling-Test should be skipped +bool MinLevelToCompress(CompressionType& type, Options& options, int wbits, + int lev, int strategy) { + fprintf(stderr, "Test with compression options : window_bits = %d, level = %d, strategy = %d}\n", wbits, lev, strategy); + options.write_buffer_size = 100<<10; //100KB + options.num_levels = 3; + options.max_mem_compaction_level = 0; + options.level0_file_num_compaction_trigger = 3; + options.create_if_missing = true; + + if (SnappyCompressionSupported(CompressionOptions(wbits, lev, strategy))) { + type = kSnappyCompression; + fprintf(stderr, "using snappy\n"); + } else if (ZlibCompressionSupported( + CompressionOptions(wbits, lev, strategy))) { + type = kZlibCompression; + fprintf(stderr, "using zlib\n"); + } else if (BZip2CompressionSupported( + CompressionOptions(wbits, lev, strategy))) { + type = kBZip2Compression; + fprintf(stderr, "using bzip2\n"); + } else { + fprintf(stderr, "skipping test, compression disabled\n"); + return false; + } + options.compression_per_level.resize(options.num_levels); + + // do not compress L0 + for (int i = 0; i < 1; i++) { + options.compression_per_level[i] = kNoCompression; + } + for (int i = 1; i < options.num_levels; i++) { + options.compression_per_level[i] = type; + } + return true; +} +TEST(DBTest, MinLevelToCompress1) { + Options options = CurrentOptions(); + CompressionType type; + if (!MinLevelToCompress(type, options, -14, -1, 0)) { + return; + } + Reopen(&options); + MinLevelHelper(this, options); + + // do not compress L0 and L1 + for (int i = 0; i < 2; i++) { + options.compression_per_level[i] = kNoCompression; + } + for (int i = 2; i < options.num_levels; i++) { + options.compression_per_level[i] = type; + } + DestroyAndReopen(&options); + MinLevelHelper(this, options); +} + +TEST(DBTest, MinLevelToCompress2) { + Options options = CurrentOptions(); + CompressionType type; + if (!MinLevelToCompress(type, options, 15, -1, 0)) { + return; + } + Reopen(&options); + MinLevelHelper(this, options); + + // do not compress L0 and L1 + for (int i = 0; i < 2; i++) { + options.compression_per_level[i] = kNoCompression; + } + for (int i = 2; i < options.num_levels; i++) { + options.compression_per_level[i] = type; + } + DestroyAndReopen(&options); + MinLevelHelper(this, options); +} + +TEST(DBTest, RepeatedWritesToSameKey) { + Options options = CurrentOptions(); + options.env = env_; + options.write_buffer_size = 100000; // Small write buffer + Reopen(&options); + + // We must have at most one file per level except for level-0, + // which may have up to kL0_StopWritesTrigger files. + const int kMaxFiles = dbfull()->NumberLevels() + + dbfull()->Level0StopWriteTrigger(); + + Random rnd(301); + std::string value = RandomString(&rnd, 2 * options.write_buffer_size); + for (int i = 0; i < 5 * kMaxFiles; i++) { + Put("key", value); + ASSERT_LE(TotalTableFiles(), kMaxFiles); + } +} + +// This is a static filter used for filtering +// kvs during the compaction process. +static int cfilter_count; +static std::string NEW_VALUE = "NewValue"; +static bool keep_filter(void* arg, int level, const Slice& key, + const Slice& value, Slice** new_value) { + assert(arg == nullptr); + cfilter_count++; + return false; +} +static bool delete_filter(void*argv, int level, const Slice& key, + const Slice& value, Slice** new_value) { + assert(argv == nullptr); + cfilter_count++; + return true; +} +static bool change_filter(void*argv, int level, const Slice& key, + const Slice& value, Slice** new_value) { + assert(argv == (void*)100); + assert(new_value != nullptr); + *new_value = new Slice(NEW_VALUE); + return false; +} + +TEST(DBTest, CompactionFilter) { + Options options = CurrentOptions(); + options.num_levels = 3; + options.max_mem_compaction_level = 0; + options.CompactionFilter = keep_filter; + Reopen(&options); + + // Write 100K+1 keys, these are written to a few files + // in L0. We do this so that the current snapshot points + // to the 100001 key.The compaction filter is not invoked + // on keys that are visible via a snapshot because we + // anyways cannot delete it. + const std::string value(10, 'x'); + for (int i = 0; i < 100001; i++) { + char key[100]; + snprintf(key, sizeof(key), "B%010d", i); + Put(key, value); + } + dbfull()->TEST_CompactMemTable(); + + // Push all files to the highest level L2. Verify that + // the compaction is each level invokes the filter for + // all the keys in that level. + cfilter_count = 0; + dbfull()->TEST_CompactRange(0, nullptr, nullptr); + ASSERT_EQ(cfilter_count, 100000); + cfilter_count = 0; + dbfull()->TEST_CompactRange(1, nullptr, nullptr); + ASSERT_EQ(cfilter_count, 100000); + + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + ASSERT_EQ(NumTableFilesAtLevel(1), 0); + ASSERT_NE(NumTableFilesAtLevel(2), 0); + cfilter_count = 0; + + // All the files are in the lowest level. + // Verify that all but the 100001st record + // has sequence number zero. The 100001st record + // is at the tip of this snapshot and cannot + // be zeroed out. + int count = 0; + int total = 0; + Iterator* iter = dbfull()->TEST_NewInternalIterator(); + iter->SeekToFirst(); + ASSERT_EQ(iter->status().ok(), true); + while (iter->Valid()) { + ParsedInternalKey ikey; + ikey.sequence = -1; + ASSERT_EQ(ParseInternalKey(iter->key(), &ikey), true); + total++; + if (ikey.sequence != 0) { + count++; + } + iter->Next(); + } + ASSERT_EQ(total, 100001); + ASSERT_EQ(count, 1); + delete iter; + + // overwrite all the 100K+1 keys once again. + for (int i = 0; i < 100001; i++) { + char key[100]; + snprintf(key, sizeof(key), "B%010d", i); + Put(key, value); + } + dbfull()->TEST_CompactMemTable(); + + // push all files to the highest level L2. This + // means that all keys should pass at least once + // via the compaction filter + cfilter_count = 0; + dbfull()->TEST_CompactRange(0, nullptr, nullptr); + ASSERT_EQ(cfilter_count, 100000); + cfilter_count = 0; + dbfull()->TEST_CompactRange(1, nullptr, nullptr); + ASSERT_EQ(cfilter_count, 100000); + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + ASSERT_EQ(NumTableFilesAtLevel(1), 0); + ASSERT_NE(NumTableFilesAtLevel(2), 0); + + // create a new database with the compaction + // filter in such a way that it deletes all keys + options.CompactionFilter = delete_filter; + options.create_if_missing = true; + DestroyAndReopen(&options); + + // write all the keys once again. + for (int i = 0; i < 100001; i++) { + char key[100]; + snprintf(key, sizeof(key), "B%010d", i); + Put(key, value); + } + dbfull()->TEST_CompactMemTable(); + ASSERT_NE(NumTableFilesAtLevel(0), 0); + ASSERT_EQ(NumTableFilesAtLevel(1), 0); + ASSERT_EQ(NumTableFilesAtLevel(2), 0); + + // Push all files to the highest level L2. This + // triggers the compaction filter to delete all keys, + // verify that at the end of the compaction process, + // nothing is left. + cfilter_count = 0; + dbfull()->TEST_CompactRange(0, nullptr, nullptr); + ASSERT_EQ(cfilter_count, 100000); + cfilter_count = 0; + dbfull()->TEST_CompactRange(1, nullptr, nullptr); + ASSERT_EQ(cfilter_count, 0); + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + ASSERT_EQ(NumTableFilesAtLevel(1), 0); + + // Scan the entire database to ensure that only the + // 100001th key is left in the db. The 100001th key + // is part of the default-most-current snapshot and + // cannot be deleted. + iter = db_->NewIterator(ReadOptions()); + iter->SeekToFirst(); + count = 0; + while (iter->Valid()) { + count++; + iter->Next(); + } + ASSERT_EQ(count, 1); + delete iter; + + // The sequence number of the remaining record + // is not zeroed out even though it is at the + // level Lmax because this record is at the tip + count = 0; + iter = dbfull()->TEST_NewInternalIterator(); + iter->SeekToFirst(); + ASSERT_EQ(iter->status().ok(), true); + while (iter->Valid()) { + ParsedInternalKey ikey; + ASSERT_EQ(ParseInternalKey(iter->key(), &ikey), true); + ASSERT_NE(ikey.sequence, 0); + count++; + iter->Next(); + } + ASSERT_EQ(count, 1); + delete iter; +} + +TEST(DBTest, CompactionFilterWithValueChange) { + Options options = CurrentOptions(); + options.num_levels = 3; + options.max_mem_compaction_level = 0; + options.compaction_filter_args = (void *)100; + options.CompactionFilter = change_filter; + Reopen(&options); + + // Write 100K+1 keys, these are written to a few files + // in L0. We do this so that the current snapshot points + // to the 100001 key.The compaction filter is not invoked + // on keys that are visible via a snapshot because we + // anyways cannot delete it. + const std::string value(10, 'x'); + for (int i = 0; i < 100001; i++) { + char key[100]; + snprintf(key, sizeof(key), "B%010d", i); + Put(key, value); + } + + // push all files to lower levels + dbfull()->TEST_CompactMemTable(); + dbfull()->TEST_CompactRange(0, nullptr, nullptr); + dbfull()->TEST_CompactRange(1, nullptr, nullptr); + + // re-write all data again + for (int i = 0; i < 100001; i++) { + char key[100]; + snprintf(key, sizeof(key), "B%010d", i); + Put(key, value); + } + + // push all files to lower levels. This should + // invoke the compaction filter for all 100000 keys. + dbfull()->TEST_CompactMemTable(); + dbfull()->TEST_CompactRange(0, nullptr, nullptr); + dbfull()->TEST_CompactRange(1, nullptr, nullptr); + + // verify that all keys now have the new value that + // was set by the compaction process. + for (int i = 0; i < 100000; i++) { + char key[100]; + snprintf(key, sizeof(key), "B%010d", i); + std::string newvalue = Get(key); + ASSERT_EQ(newvalue.compare(NEW_VALUE), 0); + } +} + +TEST(DBTest, SparseMerge) { + Options options = CurrentOptions(); + options.compression = kNoCompression; + Reopen(&options); + + FillLevels("A", "Z"); + + // Suppose there is: + // small amount of data with prefix A + // large amount of data with prefix B + // small amount of data with prefix C + // and that recent updates have made small changes to all three prefixes. + // Check that we do not do a compaction that merges all of B in one shot. + const std::string value(1000, 'x'); + Put("A", "va"); + // Write approximately 100MB of "B" values + for (int i = 0; i < 100000; i++) { + char key[100]; + snprintf(key, sizeof(key), "B%010d", i); + Put(key, value); + } + Put("C", "vc"); + dbfull()->TEST_CompactMemTable(); + dbfull()->TEST_CompactRange(0, nullptr, nullptr); + + // Make sparse update + Put("A", "va2"); + Put("B100", "bvalue2"); + Put("C", "vc2"); + dbfull()->TEST_CompactMemTable(); + + // Compactions should not cause us to create a situation where + // a file overlaps too much data at the next level. + ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576); + dbfull()->TEST_CompactRange(0, nullptr, nullptr); + ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576); + dbfull()->TEST_CompactRange(1, nullptr, nullptr); + ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576); +} + +static bool Between(uint64_t val, uint64_t low, uint64_t high) { + bool result = (val >= low) && (val <= high); + if (!result) { + fprintf(stderr, "Value %llu is not in range [%llu, %llu]\n", + (unsigned long long)(val), + (unsigned long long)(low), + (unsigned long long)(high)); + } + return result; +} + +TEST(DBTest, ApproximateSizes) { + do { + Options options = CurrentOptions(); + options.write_buffer_size = 100000000; // Large write buffer + options.compression = kNoCompression; + DestroyAndReopen(); + + ASSERT_TRUE(Between(Size("", "xyz"), 0, 0)); + Reopen(&options); + ASSERT_TRUE(Between(Size("", "xyz"), 0, 0)); + + // Write 8MB (80 values, each 100K) + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + const int N = 80; + static const int S1 = 100000; + static const int S2 = 105000; // Allow some expansion from metadata + Random rnd(301); + for (int i = 0; i < N; i++) { + ASSERT_OK(Put(Key(i), RandomString(&rnd, S1))); + } + + // 0 because GetApproximateSizes() does not account for memtable space + ASSERT_TRUE(Between(Size("", Key(50)), 0, 0)); + + // Check sizes across recovery by reopening a few times + for (int run = 0; run < 3; run++) { + Reopen(&options); + + for (int compact_start = 0; compact_start < N; compact_start += 10) { + for (int i = 0; i < N; i += 10) { + ASSERT_TRUE(Between(Size("", Key(i)), S1*i, S2*i)); + ASSERT_TRUE(Between(Size("", Key(i)+".suffix"), S1*(i+1), S2*(i+1))); + ASSERT_TRUE(Between(Size(Key(i), Key(i+10)), S1*10, S2*10)); + } + ASSERT_TRUE(Between(Size("", Key(50)), S1*50, S2*50)); + ASSERT_TRUE(Between(Size("", Key(50)+".suffix"), S1*50, S2*50)); + + std::string cstart_str = Key(compact_start); + std::string cend_str = Key(compact_start + 9); + Slice cstart = cstart_str; + Slice cend = cend_str; + dbfull()->TEST_CompactRange(0, &cstart, &cend); + } + + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + ASSERT_GT(NumTableFilesAtLevel(1), 0); + } + } while (ChangeOptions()); +} + +TEST(DBTest, ApproximateSizes_MixOfSmallAndLarge) { + do { + Options options = CurrentOptions(); + options.compression = kNoCompression; + Reopen(); + + Random rnd(301); + std::string big1 = RandomString(&rnd, 100000); + ASSERT_OK(Put(Key(0), RandomString(&rnd, 10000))); + ASSERT_OK(Put(Key(1), RandomString(&rnd, 10000))); + ASSERT_OK(Put(Key(2), big1)); + ASSERT_OK(Put(Key(3), RandomString(&rnd, 10000))); + ASSERT_OK(Put(Key(4), big1)); + ASSERT_OK(Put(Key(5), RandomString(&rnd, 10000))); + ASSERT_OK(Put(Key(6), RandomString(&rnd, 300000))); + ASSERT_OK(Put(Key(7), RandomString(&rnd, 10000))); + + // Check sizes across recovery by reopening a few times + for (int run = 0; run < 3; run++) { + Reopen(&options); + + ASSERT_TRUE(Between(Size("", Key(0)), 0, 0)); + ASSERT_TRUE(Between(Size("", Key(1)), 10000, 11000)); + ASSERT_TRUE(Between(Size("", Key(2)), 20000, 21000)); + ASSERT_TRUE(Between(Size("", Key(3)), 120000, 121000)); + ASSERT_TRUE(Between(Size("", Key(4)), 130000, 131000)); + ASSERT_TRUE(Between(Size("", Key(5)), 230000, 231000)); + ASSERT_TRUE(Between(Size("", Key(6)), 240000, 241000)); + ASSERT_TRUE(Between(Size("", Key(7)), 540000, 541000)); + ASSERT_TRUE(Between(Size("", Key(8)), 550000, 560000)); + + ASSERT_TRUE(Between(Size(Key(3), Key(5)), 110000, 111000)); + + dbfull()->TEST_CompactRange(0, nullptr, nullptr); + } + } while (ChangeOptions()); +} + +TEST(DBTest, IteratorPinsRef) { + Put("foo", "hello"); + + // Get iterator that will yield the current contents of the DB. + Iterator* iter = db_->NewIterator(ReadOptions()); + + // Write to force compactions + Put("foo", "newvalue1"); + for (int i = 0; i < 100; i++) { + ASSERT_OK(Put(Key(i), Key(i) + std::string(100000, 'v'))); // 100K values + } + Put("foo", "newvalue2"); + + iter->SeekToFirst(); + ASSERT_TRUE(iter->Valid()); + ASSERT_EQ("foo", iter->key().ToString()); + ASSERT_EQ("hello", iter->value().ToString()); + iter->Next(); + ASSERT_TRUE(!iter->Valid()); + delete iter; +} + +TEST(DBTest, Snapshot) { + do { + Put("foo", "v1"); + const Snapshot* s1 = db_->GetSnapshot(); + Put("foo", "v2"); + const Snapshot* s2 = db_->GetSnapshot(); + Put("foo", "v3"); + const Snapshot* s3 = db_->GetSnapshot(); + + Put("foo", "v4"); + ASSERT_EQ("v1", Get("foo", s1)); + ASSERT_EQ("v2", Get("foo", s2)); + ASSERT_EQ("v3", Get("foo", s3)); + ASSERT_EQ("v4", Get("foo")); + + db_->ReleaseSnapshot(s3); + ASSERT_EQ("v1", Get("foo", s1)); + ASSERT_EQ("v2", Get("foo", s2)); + ASSERT_EQ("v4", Get("foo")); + + db_->ReleaseSnapshot(s1); + ASSERT_EQ("v2", Get("foo", s2)); + ASSERT_EQ("v4", Get("foo")); + + db_->ReleaseSnapshot(s2); + ASSERT_EQ("v4", Get("foo")); + } while (ChangeOptions()); +} + +TEST(DBTest, HiddenValuesAreRemoved) { + do { + Random rnd(301); + FillLevels("a", "z"); + + std::string big = RandomString(&rnd, 50000); + Put("foo", big); + Put("pastfoo", "v"); + const Snapshot* snapshot = db_->GetSnapshot(); + Put("foo", "tiny"); + Put("pastfoo2", "v2"); // Advance sequence number one more + + ASSERT_OK(dbfull()->TEST_CompactMemTable()); + ASSERT_GT(NumTableFilesAtLevel(0), 0); + + ASSERT_EQ(big, Get("foo", snapshot)); + ASSERT_TRUE(Between(Size("", "pastfoo"), 50000, 60000)); + db_->ReleaseSnapshot(snapshot); + ASSERT_EQ(AllEntriesFor("foo"), "[ tiny, " + big + " ]"); + Slice x("x"); + dbfull()->TEST_CompactRange(0, nullptr, &x); + ASSERT_EQ(AllEntriesFor("foo"), "[ tiny ]"); + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + ASSERT_GE(NumTableFilesAtLevel(1), 1); + dbfull()->TEST_CompactRange(1, nullptr, &x); + ASSERT_EQ(AllEntriesFor("foo"), "[ tiny ]"); + + ASSERT_TRUE(Between(Size("", "pastfoo"), 0, 1000)); + } while (ChangeOptions()); +} + +TEST(DBTest, CompactBetweenSnapshots) { + do { + Random rnd(301); + FillLevels("a", "z"); + + Put("foo", "first"); + const Snapshot* snapshot1 = db_->GetSnapshot(); + Put("foo", "second"); + Put("foo", "third"); + Put("foo", "fourth"); + const Snapshot* snapshot2 = db_->GetSnapshot(); + Put("foo", "fifth"); + Put("foo", "sixth"); + + // All entries (including duplicates) exist + // before any compaction is triggered. + ASSERT_OK(dbfull()->TEST_CompactMemTable()); + ASSERT_EQ("sixth", Get("foo")); + ASSERT_EQ("fourth", Get("foo", snapshot2)); + ASSERT_EQ("first", Get("foo", snapshot1)); + ASSERT_EQ(AllEntriesFor("foo"), + "[ sixth, fifth, fourth, third, second, first ]"); + + // After a compaction, "second", "third" and "fifth" should + // be removed + FillLevels("a", "z"); + dbfull()->CompactRange(nullptr, nullptr); + ASSERT_EQ("sixth", Get("foo")); + ASSERT_EQ("fourth", Get("foo", snapshot2)); + ASSERT_EQ("first", Get("foo", snapshot1)); + ASSERT_EQ(AllEntriesFor("foo"), "[ sixth, fourth, first ]"); + + // after we release the snapshot1, only two values left + db_->ReleaseSnapshot(snapshot1); + FillLevels("a", "z"); + dbfull()->CompactRange(nullptr, nullptr); + + // We have only one valid snapshot snapshot2. Since snapshot1 is + // not valid anymore, "first" should be removed by a compaction. + ASSERT_EQ("sixth", Get("foo")); + ASSERT_EQ("fourth", Get("foo", snapshot2)); + ASSERT_EQ(AllEntriesFor("foo"), "[ sixth, fourth ]"); + + // after we release the snapshot2, only one value should be left + db_->ReleaseSnapshot(snapshot2); + FillLevels("a", "z"); + dbfull()->CompactRange(nullptr, nullptr); + ASSERT_EQ("sixth", Get("foo")); + ASSERT_EQ(AllEntriesFor("foo"), "[ sixth ]"); + + } while (ChangeOptions()); +} + +TEST(DBTest, DeletionMarkers1) { + Put("foo", "v1"); + ASSERT_OK(dbfull()->TEST_CompactMemTable()); + const int last = dbfull()->MaxMemCompactionLevel(); + ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo => v1 is now in last level + + // Place a table at level last-1 to prevent merging with preceding mutation + Put("a", "begin"); + Put("z", "end"); + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ(NumTableFilesAtLevel(last), 1); + ASSERT_EQ(NumTableFilesAtLevel(last-1), 1); + + Delete("foo"); + Put("foo", "v2"); + ASSERT_EQ(AllEntriesFor("foo"), "[ v2, DEL, v1 ]"); + ASSERT_OK(dbfull()->TEST_CompactMemTable()); // Moves to level last-2 + if (CurrentOptions().purge_redundant_kvs_while_flush) { + ASSERT_EQ(AllEntriesFor("foo"), "[ v2, v1 ]"); + } else { + ASSERT_EQ(AllEntriesFor("foo"), "[ v2, DEL, v1 ]"); + } + Slice z("z"); + dbfull()->TEST_CompactRange(last-2, nullptr, &z); + // DEL eliminated, but v1 remains because we aren't compacting that level + // (DEL can be eliminated because v2 hides v1). + ASSERT_EQ(AllEntriesFor("foo"), "[ v2, v1 ]"); + dbfull()->TEST_CompactRange(last-1, nullptr, nullptr); + // Merging last-1 w/ last, so we are the base level for "foo", so + // DEL is removed. (as is v1). + ASSERT_EQ(AllEntriesFor("foo"), "[ v2 ]"); +} + +TEST(DBTest, DeletionMarkers2) { + Put("foo", "v1"); + ASSERT_OK(dbfull()->TEST_CompactMemTable()); + const int last = dbfull()->MaxMemCompactionLevel(); + ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo => v1 is now in last level + + // Place a table at level last-1 to prevent merging with preceding mutation + Put("a", "begin"); + Put("z", "end"); + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ(NumTableFilesAtLevel(last), 1); + ASSERT_EQ(NumTableFilesAtLevel(last-1), 1); + + Delete("foo"); + ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]"); + ASSERT_OK(dbfull()->TEST_CompactMemTable()); // Moves to level last-2 + ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]"); + dbfull()->TEST_CompactRange(last-2, nullptr, nullptr); + // DEL kept: "last" file overlaps + ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]"); + dbfull()->TEST_CompactRange(last-1, nullptr, nullptr); + // Merging last-1 w/ last, so we are the base level for "foo", so + // DEL is removed. (as is v1). + ASSERT_EQ(AllEntriesFor("foo"), "[ ]"); +} + +TEST(DBTest, OverlapInLevel0) { + do { + int tmp = dbfull()->MaxMemCompactionLevel(); + ASSERT_EQ(tmp, 2) << "Fix test to match config"; + + // Fill levels 1 and 2 to disable the pushing of new memtables to levels > 0. + ASSERT_OK(Put("100", "v100")); + ASSERT_OK(Put("999", "v999")); + dbfull()->TEST_CompactMemTable(); + ASSERT_OK(Delete("100")); + ASSERT_OK(Delete("999")); + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ("0,1,1", FilesPerLevel()); + + // Make files spanning the following ranges in level-0: + // files[0] 200 .. 900 + // files[1] 300 .. 500 + // Note that files are sorted by smallest key. + ASSERT_OK(Put("300", "v300")); + ASSERT_OK(Put("500", "v500")); + dbfull()->TEST_CompactMemTable(); + ASSERT_OK(Put("200", "v200")); + ASSERT_OK(Put("600", "v600")); + ASSERT_OK(Put("900", "v900")); + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ("2,1,1", FilesPerLevel()); + + // Compact away the placeholder files we created initially + dbfull()->TEST_CompactRange(1, nullptr, nullptr); + dbfull()->TEST_CompactRange(2, nullptr, nullptr); + ASSERT_EQ("2", FilesPerLevel()); + + // Do a memtable compaction. Before bug-fix, the compaction would + // not detect the overlap with level-0 files and would incorrectly place + // the deletion in a deeper level. + ASSERT_OK(Delete("600")); + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ("3", FilesPerLevel()); + ASSERT_EQ("NOT_FOUND", Get("600")); + } while (ChangeOptions()); +} + +TEST(DBTest, L0_CompactionBug_Issue44_a) { + Reopen(); + ASSERT_OK(Put("b", "v")); + Reopen(); + ASSERT_OK(Delete("b")); + ASSERT_OK(Delete("a")); + Reopen(); + ASSERT_OK(Delete("a")); + Reopen(); + ASSERT_OK(Put("a", "v")); + Reopen(); + Reopen(); + ASSERT_EQ("(a->v)", Contents()); + env_->SleepForMicroseconds(1000000); // Wait for compaction to finish + ASSERT_EQ("(a->v)", Contents()); +} + +TEST(DBTest, L0_CompactionBug_Issue44_b) { + Reopen(); + Put("",""); + Reopen(); + Delete("e"); + Put("",""); + Reopen(); + Put("c", "cv"); + Reopen(); + Put("",""); + Reopen(); + Put("",""); + env_->SleepForMicroseconds(1000000); // Wait for compaction to finish + Reopen(); + Put("d","dv"); + Reopen(); + Put("",""); + Reopen(); + Delete("d"); + Delete("b"); + Reopen(); + ASSERT_EQ("(->)(c->cv)", Contents()); + env_->SleepForMicroseconds(1000000); // Wait for compaction to finish + ASSERT_EQ("(->)(c->cv)", Contents()); +} + +TEST(DBTest, ComparatorCheck) { + class NewComparator : public Comparator { + public: + virtual const char* Name() const { return "leveldb.NewComparator"; } + virtual int Compare(const Slice& a, const Slice& b) const { + return BytewiseComparator()->Compare(a, b); + } + virtual void FindShortestSeparator(std::string* s, const Slice& l) const { + BytewiseComparator()->FindShortestSeparator(s, l); + } + virtual void FindShortSuccessor(std::string* key) const { + BytewiseComparator()->FindShortSuccessor(key); + } + }; + NewComparator cmp; + Options new_options = CurrentOptions(); + new_options.comparator = &cmp; + Status s = TryReopen(&new_options); + ASSERT_TRUE(!s.ok()); + ASSERT_TRUE(s.ToString().find("comparator") != std::string::npos) + << s.ToString(); +} + +TEST(DBTest, CustomComparator) { + class NumberComparator : public Comparator { + public: + virtual const char* Name() const { return "test.NumberComparator"; } + virtual int Compare(const Slice& a, const Slice& b) const { + return ToNumber(a) - ToNumber(b); + } + virtual void FindShortestSeparator(std::string* s, const Slice& l) const { + ToNumber(*s); // Check format + ToNumber(l); // Check format + } + virtual void FindShortSuccessor(std::string* key) const { + ToNumber(*key); // Check format + } + private: + static int ToNumber(const Slice& x) { + // Check that there are no extra characters. + ASSERT_TRUE(x.size() >= 2 && x[0] == '[' && x[x.size()-1] == ']') + << EscapeString(x); + int val; + char ignored; + ASSERT_TRUE(sscanf(x.ToString().c_str(), "[%i]%c", &val, &ignored) == 1) + << EscapeString(x); + return val; + } + }; + NumberComparator cmp; + Options new_options = CurrentOptions(); + new_options.create_if_missing = true; + new_options.comparator = &cmp; + new_options.filter_policy = nullptr; // Cannot use bloom filters + new_options.write_buffer_size = 1000; // Compact more often + DestroyAndReopen(&new_options); + ASSERT_OK(Put("[10]", "ten")); + ASSERT_OK(Put("[0x14]", "twenty")); + for (int i = 0; i < 2; i++) { + ASSERT_EQ("ten", Get("[10]")); + ASSERT_EQ("ten", Get("[0xa]")); + ASSERT_EQ("twenty", Get("[20]")); + ASSERT_EQ("twenty", Get("[0x14]")); + ASSERT_EQ("NOT_FOUND", Get("[15]")); + ASSERT_EQ("NOT_FOUND", Get("[0xf]")); + Compact("[0]", "[9999]"); + } + + for (int run = 0; run < 2; run++) { + for (int i = 0; i < 1000; i++) { + char buf[100]; + snprintf(buf, sizeof(buf), "[%d]", i*10); + ASSERT_OK(Put(buf, buf)); + } + Compact("[0]", "[1000000]"); + } +} + +TEST(DBTest, ManualCompaction) { + ASSERT_EQ(dbfull()->MaxMemCompactionLevel(), 2) + << "Need to update this test to match kMaxMemCompactLevel"; + + MakeTables(3, "p", "q"); + ASSERT_EQ("1,1,1", FilesPerLevel()); + + // Compaction range falls before files + Compact("", "c"); + ASSERT_EQ("1,1,1", FilesPerLevel()); + + // Compaction range falls after files + Compact("r", "z"); + ASSERT_EQ("1,1,1", FilesPerLevel()); + + // Compaction range overlaps files + Compact("p1", "p9"); + ASSERT_EQ("0,0,1", FilesPerLevel()); + + // Populate a different range + MakeTables(3, "c", "e"); + ASSERT_EQ("1,1,2", FilesPerLevel()); + + // Compact just the new range + Compact("b", "f"); + ASSERT_EQ("0,0,2", FilesPerLevel()); + + // Compact all + MakeTables(1, "a", "z"); + ASSERT_EQ("0,1,2", FilesPerLevel()); + db_->CompactRange(nullptr, nullptr); + ASSERT_EQ("0,0,1", FilesPerLevel()); +} + +TEST(DBTest, DBOpen_Options) { + std::string dbname = test::TmpDir() + "/db_options_test"; + DestroyDB(dbname, Options()); + + // Does not exist, and create_if_missing == false: error + DB* db = nullptr; + Options opts; + opts.create_if_missing = false; + Status s = DB::Open(opts, dbname, &db); + ASSERT_TRUE(strstr(s.ToString().c_str(), "does not exist") != nullptr); + ASSERT_TRUE(db == nullptr); + + // Does not exist, and create_if_missing == true: OK + opts.create_if_missing = true; + s = DB::Open(opts, dbname, &db); + ASSERT_OK(s); + ASSERT_TRUE(db != nullptr); + + delete db; + db = nullptr; + + // Does exist, and error_if_exists == true: error + opts.create_if_missing = false; + opts.error_if_exists = true; + s = DB::Open(opts, dbname, &db); + ASSERT_TRUE(strstr(s.ToString().c_str(), "exists") != nullptr); + ASSERT_TRUE(db == nullptr); + + // Does exist, and error_if_exists == false: OK + opts.create_if_missing = true; + opts.error_if_exists = false; + s = DB::Open(opts, dbname, &db); + ASSERT_OK(s); + ASSERT_TRUE(db != nullptr); + + delete db; + db = nullptr; +} + +TEST(DBTest, DBOpen_Change_NumLevels) { + std::string dbname = test::TmpDir() + "/db_change_num_levels"; + DestroyDB(dbname, Options()); + Options opts; + Status s; + DB* db = nullptr; + opts.create_if_missing = true; + s = DB::Open(opts, dbname, &db); + ASSERT_OK(s); + ASSERT_TRUE(db != nullptr); + db->Put(WriteOptions(), "a", "123"); + db->Put(WriteOptions(), "b", "234"); + db->CompactRange(nullptr, nullptr); + delete db; + db = nullptr; + + opts.create_if_missing = false; + opts.num_levels = 2; + s = DB::Open(opts, dbname, &db); + ASSERT_TRUE(strstr(s.ToString().c_str(), "Corruption") != nullptr); + ASSERT_TRUE(db == nullptr); +} + +TEST(DBTest, DestroyDBMetaDatabase) { + std::string dbname = test::TmpDir() + "/db_meta"; + std::string metadbname = MetaDatabaseName(dbname, 0); + std::string metametadbname = MetaDatabaseName(metadbname, 0); + + // Destroy previous versions if they exist. Using the long way. + DestroyDB(metametadbname, Options()); + DestroyDB(metadbname, Options()); + DestroyDB(dbname, Options()); + + // Setup databases + Options opts; + opts.create_if_missing = true; + DB* db = nullptr; + ASSERT_OK(DB::Open(opts, dbname, &db)); + delete db; + db = nullptr; + ASSERT_OK(DB::Open(opts, metadbname, &db)); + delete db; + db = nullptr; + ASSERT_OK(DB::Open(opts, metametadbname, &db)); + delete db; + db = nullptr; + + // Delete databases + DestroyDB(dbname, Options()); + + // Check if deletion worked. + opts.create_if_missing = false; + ASSERT_TRUE(!DB::Open(opts, dbname, &db).ok()); + ASSERT_TRUE(!DB::Open(opts, metadbname, &db).ok()); + ASSERT_TRUE(!DB::Open(opts, metametadbname, &db).ok()); +} + + +// Check that number of files does not grow when we are out of space +TEST(DBTest, NoSpace) { + Options options = CurrentOptions(); + options.env = env_; + Reopen(&options); + + ASSERT_OK(Put("foo", "v1")); + ASSERT_EQ("v1", Get("foo")); + Compact("a", "z"); + const int num_files = CountFiles(); + env_->no_space_.Release_Store(env_); // Force out-of-space errors + env_->sleep_counter_.Reset(); + for (int i = 0; i < 5; i++) { + for (int level = 0; level < dbfull()->NumberLevels()-1; level++) { + dbfull()->TEST_CompactRange(level, nullptr, nullptr); + } + } + env_->no_space_.Release_Store(nullptr); + ASSERT_LT(CountFiles(), num_files + 3); + + // Check that compaction attempts slept after errors + ASSERT_GE(env_->sleep_counter_.Read(), 5); +} + +TEST(DBTest, NonWritableFileSystem) +{ + Options options = CurrentOptions(); + options.write_buffer_size = 1000; + options.env = env_; + Reopen(&options); + ASSERT_OK(Put("foo", "v1")); + env_->non_writable_.Release_Store(env_); // Force errors for new files + std::string big(100000, 'x'); + int errors = 0; + for (int i = 0; i < 20; i++) { + if (!Put("foo", big).ok()) { + errors++; + env_->SleepForMicroseconds(100000); + } + } + ASSERT_GT(errors, 0); + env_->non_writable_.Release_Store(nullptr); +} + +TEST(DBTest, ManifestWriteError) { + // Test for the following problem: + // (a) Compaction produces file F + // (b) Log record containing F is written to MANIFEST file, but Sync() fails + // (c) GC deletes F + // (d) After reopening DB, reads fail since deleted F is named in log record + + // We iterate twice. In the second iteration, everything is the + // same except the log record never makes it to the MANIFEST file. + for (int iter = 0; iter < 2; iter++) { + port::AtomicPointer* error_type = (iter == 0) + ? &env_->manifest_sync_error_ + : &env_->manifest_write_error_; + + // Insert foo=>bar mapping + Options options = CurrentOptions(); + options.env = env_; + options.create_if_missing = true; + options.error_if_exists = false; + DestroyAndReopen(&options); + ASSERT_OK(Put("foo", "bar")); + ASSERT_EQ("bar", Get("foo")); + + // Memtable compaction (will succeed) + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ("bar", Get("foo")); + const int last = dbfull()->MaxMemCompactionLevel(); + ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo=>bar is now in last level + + // Merging compaction (will fail) + error_type->Release_Store(env_); + dbfull()->TEST_CompactRange(last, nullptr, nullptr); // Should fail + ASSERT_EQ("bar", Get("foo")); + + // Recovery: should not lose data + error_type->Release_Store(nullptr); + Reopen(&options); + ASSERT_EQ("bar", Get("foo")); + } +} + +TEST(DBTest, FilesDeletedAfterCompaction) { + ASSERT_OK(Put("foo", "v2")); + Compact("a", "z"); + const int num_files = CountLiveFiles(); + for (int i = 0; i < 10; i++) { + ASSERT_OK(Put("foo", "v2")); + Compact("a", "z"); + } + ASSERT_EQ(CountLiveFiles(), num_files); +} + +TEST(DBTest, BloomFilter) { + env_->count_random_reads_ = true; + Options options = CurrentOptions(); + options.env = env_; + options.block_cache = NewLRUCache(0); // Prevent cache hits + options.filter_policy = NewBloomFilterPolicy(10); + Reopen(&options); + + // Populate multiple layers + const int N = 10000; + for (int i = 0; i < N; i++) { + ASSERT_OK(Put(Key(i), Key(i))); + } + Compact("a", "z"); + for (int i = 0; i < N; i += 100) { + ASSERT_OK(Put(Key(i), Key(i))); + } + dbfull()->TEST_CompactMemTable(); + + // Prevent auto compactions triggered by seeks + env_->delay_sstable_sync_.Release_Store(env_); + + // Lookup present keys. Should rarely read from small sstable. + env_->random_read_counter_.Reset(); + for (int i = 0; i < N; i++) { + ASSERT_EQ(Key(i), Get(Key(i))); + } + int reads = env_->random_read_counter_.Read(); + fprintf(stderr, "%d present => %d reads\n", N, reads); + ASSERT_GE(reads, N); + ASSERT_LE(reads, N + 2*N/100); + + // Lookup present keys. Should rarely read from either sstable. + env_->random_read_counter_.Reset(); + for (int i = 0; i < N; i++) { + ASSERT_EQ("NOT_FOUND", Get(Key(i) + ".missing")); + } + reads = env_->random_read_counter_.Read(); + fprintf(stderr, "%d missing => %d reads\n", N, reads); + ASSERT_LE(reads, 3*N/100); + + env_->delay_sstable_sync_.Release_Store(nullptr); + Close(); + delete options.filter_policy; +} + +TEST(DBTest, SnapshotFiles) { + Options options = CurrentOptions(); + options.write_buffer_size = 100000000; // Large write buffer + Reopen(&options); + + Random rnd(301); + + // Write 8MB (80 values, each 100K) + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + std::vector values; + for (int i = 0; i < 80; i++) { + values.push_back(RandomString(&rnd, 100000)); + ASSERT_OK(Put(Key(i), values[i])); + } + + // assert that nothing makes it to disk yet. + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + + // get a file snapshot + uint64_t manifest_number = 0; + uint64_t manifest_size = 0; + std::vector files; + dbfull()->DisableFileDeletions(); + dbfull()->GetLiveFiles(files, &manifest_size); + + // CURRENT, MANIFEST, *.sst files + ASSERT_EQ(files.size(), 3U); + + uint64_t number = 0; + FileType type; + + // copy these files to a new snapshot directory + std::string snapdir = dbname_ + ".snapdir/"; + std::string mkdir = "mkdir -p " + snapdir; + ASSERT_EQ(system(mkdir.c_str()), 0); + + for (unsigned int i = 0; i < files.size(); i++) { + std::string src = dbname_ + "/" + files[i]; + std::string dest = snapdir + "/" + files[i]; + + uint64_t size; + ASSERT_OK(env_->GetFileSize(src, &size)); + + // record the number and the size of the + // latest manifest file + if (ParseFileName(files[i].substr(1), &number, &type)) { + if (type == kDescriptorFile) { + if (number > manifest_number) { + manifest_number = number; + ASSERT_GE(size, manifest_size); + size = manifest_size; // copy only valid MANIFEST data + } + } + } + unique_ptr srcfile; + ASSERT_OK(env_->NewSequentialFile(src, &srcfile)); + unique_ptr destfile; + ASSERT_OK(env_->NewWritableFile(dest, &destfile)); + + char buffer[4096]; + Slice slice; + while (size > 0) { + uint64_t one = std::min(sizeof(buffer), size); + ASSERT_OK(srcfile->Read(one, &slice, buffer)); + ASSERT_OK(destfile->Append(slice)); + size -= slice.size(); + } + ASSERT_OK(destfile->Close()); + } + + // release file snapshot + dbfull()->DisableFileDeletions(); + + // overwrite one key, this key should not appear in the snapshot + std::vector extras; + for (unsigned int i = 0; i < 1; i++) { + extras.push_back(RandomString(&rnd, 100000)); + ASSERT_OK(Put(Key(i), extras[i])); + } + + // verify that data in the snapshot are correct + Options opts; + DB* snapdb; + opts.create_if_missing = false; + Status stat = DB::Open(opts, snapdir, &snapdb); + ASSERT_TRUE(stat.ok()); + + ReadOptions roptions; + std::string val; + for (unsigned int i = 0; i < 80; i++) { + stat = snapdb->Get(roptions, Key(i), &val); + ASSERT_EQ(values[i].compare(val), 0); + } + delete snapdb; + + // look at the new live files after we added an 'extra' key + // and after we took the first snapshot. + uint64_t new_manifest_number = 0; + uint64_t new_manifest_size = 0; + std::vector newfiles; + dbfull()->DisableFileDeletions(); + dbfull()->GetLiveFiles(newfiles, &new_manifest_size); + + // find the new manifest file. assert that this manifest file is + // the same one as in the previous snapshot. But its size should be + // larger because we added an extra key after taking the + // previous shapshot. + for (unsigned int i = 0; i < newfiles.size(); i++) { + std::string src = dbname_ + "/" + newfiles[i]; + // record the lognumber and the size of the + // latest manifest file + if (ParseFileName(newfiles[i].substr(1), &number, &type)) { + if (type == kDescriptorFile) { + if (number > new_manifest_number) { + uint64_t size; + new_manifest_number = number; + ASSERT_OK(env_->GetFileSize(src, &size)); + ASSERT_GE(size, new_manifest_size); + } + } + } + } + ASSERT_EQ(manifest_number, new_manifest_number); + ASSERT_GT(new_manifest_size, manifest_size); + + // release file snapshot + dbfull()->DisableFileDeletions(); +} + +TEST(DBTest, CompactOnFlush) { + Options options = CurrentOptions(); + options.purge_redundant_kvs_while_flush = true; + options.disable_auto_compactions = true; + Reopen(&options); + + Put("foo", "v1"); + ASSERT_OK(dbfull()->TEST_CompactMemTable()); + ASSERT_EQ(AllEntriesFor("foo"), "[ v1 ]"); + + // Write two new keys + Put("a", "begin"); + Put("z", "end"); + dbfull()->TEST_CompactMemTable(); + + // Case1: Delete followed by a put + Delete("foo"); + Put("foo", "v2"); + ASSERT_EQ(AllEntriesFor("foo"), "[ v2, DEL, v1 ]"); + + // After the current memtable is flushed, the DEL should + // have been removed + ASSERT_OK(dbfull()->TEST_CompactMemTable()); + ASSERT_EQ(AllEntriesFor("foo"), "[ v2, v1 ]"); + + dbfull()->CompactRange(nullptr, nullptr); + ASSERT_EQ(AllEntriesFor("foo"), "[ v2 ]"); + + // Case 2: Delete followed by another delete + Delete("foo"); + Delete("foo"); + ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, DEL, v2 ]"); + ASSERT_OK(dbfull()->TEST_CompactMemTable()); + ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v2 ]"); + dbfull()->CompactRange(nullptr, nullptr); + ASSERT_EQ(AllEntriesFor("foo"), "[ ]"); + + // Case 3: Put followed by a delete + Put("foo", "v3"); + Delete("foo"); + ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v3 ]"); + ASSERT_OK(dbfull()->TEST_CompactMemTable()); + ASSERT_EQ(AllEntriesFor("foo"), "[ DEL ]"); + dbfull()->CompactRange(nullptr, nullptr); + ASSERT_EQ(AllEntriesFor("foo"), "[ ]"); + + // Case 4: Put followed by another Put + Put("foo", "v4"); + Put("foo", "v5"); + ASSERT_EQ(AllEntriesFor("foo"), "[ v5, v4 ]"); + ASSERT_OK(dbfull()->TEST_CompactMemTable()); + ASSERT_EQ(AllEntriesFor("foo"), "[ v5 ]"); + dbfull()->CompactRange(nullptr, nullptr); + ASSERT_EQ(AllEntriesFor("foo"), "[ v5 ]"); + + // clear database + Delete("foo"); + dbfull()->CompactRange(nullptr, nullptr); + ASSERT_EQ(AllEntriesFor("foo"), "[ ]"); + + // Case 5: Put followed by snapshot followed by another Put + // Both puts should remain. + Put("foo", "v6"); + const Snapshot* snapshot = db_->GetSnapshot(); + Put("foo", "v7"); + ASSERT_OK(dbfull()->TEST_CompactMemTable()); + ASSERT_EQ(AllEntriesFor("foo"), "[ v7, v6 ]"); + db_->ReleaseSnapshot(snapshot); + + // clear database + Delete("foo"); + dbfull()->CompactRange(nullptr, nullptr); + ASSERT_EQ(AllEntriesFor("foo"), "[ ]"); + + // Case 5: snapshot followed by a put followed by another Put + // Only the last put should remain. + const Snapshot* snapshot1 = db_->GetSnapshot(); + Put("foo", "v8"); + Put("foo", "v9"); + ASSERT_OK(dbfull()->TEST_CompactMemTable()); + ASSERT_EQ(AllEntriesFor("foo"), "[ v9 ]"); + db_->ReleaseSnapshot(snapshot1); +} + +void ListLogFiles(Env* env, + const std::string& path, + std::vector* logFiles) { + std::vector files; + env->GetChildren(path, &files); + uint64_t number; + FileType type; + for (size_t i = 0; i < files.size(); ++i) { + if (ParseFileName(files[i], &number, &type)) { + if (type == kLogFile) { + logFiles->push_back(number); + } + } + } +} + +TEST(DBTest, WALArchival) { + std::string value(1024, '1'); + Options options = CurrentOptions(); + options.create_if_missing = true; + options.WAL_ttl_seconds = 1000; + DestroyAndReopen(&options); + + + // TEST : Create DB with a ttl. + // Put some keys. Count the log files present in the DB just after insert. + // Re-open db. Causes deletion/archival to take place. + // Assert that the files moved under "/archive". + + std::string archiveDir = ArchivalDirectory(dbname_); + + for (int i = 0; i < 10; ++i) { + + for (int j = 0; j < 10; ++j) { + ASSERT_OK(Put(Key(10*i+j), value)); + } + + std::vector logFiles; + ListLogFiles(env_, dbname_, &logFiles); + + options.create_if_missing = false; + Reopen(&options); + + std::vector logs; + ListLogFiles(env_, archiveDir, &logs); + std::set archivedFiles(logs.begin(), logs.end()); + + for (std::vector::iterator it = logFiles.begin(); + it != logFiles.end(); + ++it) { + ASSERT_TRUE(archivedFiles.find(*it) != archivedFiles.end()); + } + } + + // REOPEN database with 0 TTL. all files should have been deleted. + std::vector logFiles; + ListLogFiles(env_, archiveDir, &logFiles); + ASSERT_TRUE(logFiles.size() > 0); + options.WAL_ttl_seconds = 1; + env_->SleepForMicroseconds(2*1000*1000); + Reopen(&options); + + logFiles.clear(); + ListLogFiles(env_, archiveDir, &logFiles); + ASSERT_TRUE(logFiles.size() == 0); + +} + +TEST(DBTest, TransactionLogIterator) { + std::string value(1024, '1'); + Options options = CurrentOptions(); + options.create_if_missing = true; + options.WAL_ttl_seconds = 1000; + DestroyAndReopen(&options); + Put("key1", value); + Put("key2", value); + Put("key2", value); + ASSERT_EQ(dbfull()->GetLatestSequenceNumber(), 3U); + { + unique_ptr iter; + Status status = dbfull()->GetUpdatesSince(0, &iter); + ASSERT_TRUE(status.ok()); + ASSERT_TRUE(iter->Valid()); + int i = 0; + SequenceNumber lastSequence = 0; + while (iter->Valid()) { + BatchResult res = iter->GetBatch(); + ASSERT_TRUE(res.sequence > lastSequence); + ++i; + lastSequence = res.sequence; + ASSERT_TRUE(iter->status().ok()); + iter->Next(); + } + ASSERT_EQ(i, 3); + } + Reopen(&options); + { + Put("key4", value); + Put("key5", value); + Put("key6", value); + } + { + unique_ptr iter; + Status status = dbfull()->GetUpdatesSince(0, &iter); + ASSERT_TRUE(status.ok()); + ASSERT_TRUE(iter->Valid()); + int i = 0; + SequenceNumber lastSequence = 0; + while (iter->Valid()) { + BatchResult res = iter->GetBatch(); + ASSERT_TRUE(res.sequence > lastSequence); + lastSequence = res.sequence; + ASSERT_TRUE(iter->status().ok()); + iter->Next(); + ++i; + } + ASSERT_EQ(i, 6); + } +} + +TEST(DBTest, ReadCompaction) { + std::string value(4096, '4'); // a string of size 4K + { + Options options = CurrentOptions(); + options.create_if_missing = true; + options.max_open_files = 20; // only 10 file in file-cache + options.target_file_size_base = 512; + options.write_buffer_size = 64 * 1024; + options.filter_policy = nullptr; + options.block_size = 4096; + options.block_cache = NewLRUCache(0); // Prevent cache hits + + Reopen(&options); + + // Write 8MB (2000 values, each 4K) + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + std::vector values; + for (int i = 0; i < 2000; i++) { + ASSERT_OK(Put(Key(i), value)); + } + + // clear level 0 and 1 if necessary. + dbfull()->TEST_CompactMemTable(); + dbfull()->TEST_CompactRange(0, nullptr, nullptr); + dbfull()->TEST_CompactRange(1, nullptr, nullptr); + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + ASSERT_EQ(NumTableFilesAtLevel(1), 0); + + // write some new keys into level 0 + for (int i = 0; i < 2000; i = i + 16) { + ASSERT_OK(Put(Key(i), value)); + } + dbfull()->Flush(FlushOptions()); + + // Wait for any write compaction to finish + dbfull()->TEST_WaitForCompact(); + + // remember number of files in each level + int l1 = NumTableFilesAtLevel(0); + int l2 = NumTableFilesAtLevel(1); + int l3 = NumTableFilesAtLevel(3); + ASSERT_NE(NumTableFilesAtLevel(0), 0); + ASSERT_NE(NumTableFilesAtLevel(1), 0); + ASSERT_NE(NumTableFilesAtLevel(2), 0); + + // read a bunch of times, trigger read compaction + for (int j = 0; j < 100; j++) { + for (int i = 0; i < 2000; i++) { + Get(Key(i)); + } + } + // wait for read compaction to finish + env_->SleepForMicroseconds(1000000); + + // verify that the number of files have decreased + // in some level, indicating that there was a compaction + ASSERT_TRUE(NumTableFilesAtLevel(0) < l1 || + NumTableFilesAtLevel(1) < l2 || + NumTableFilesAtLevel(2) < l3); + } +} + +// Multi-threaded test: +namespace { + +static const int kNumThreads = 4; +static const int kTestSeconds = 10; +static const int kNumKeys = 1000; + +struct MTState { + DBTest* test; + port::AtomicPointer stop; + port::AtomicPointer counter[kNumThreads]; + port::AtomicPointer thread_done[kNumThreads]; +}; + +struct MTThread { + MTState* state; + int id; +}; + +static void MTThreadBody(void* arg) { + MTThread* t = reinterpret_cast(arg); + int id = t->id; + DB* db = t->state->test->db_; + uintptr_t counter = 0; + fprintf(stderr, "... starting thread %d\n", id); + Random rnd(1000 + id); + std::string value; + char valbuf[1500]; + while (t->state->stop.Acquire_Load() == nullptr) { + t->state->counter[id].Release_Store(reinterpret_cast(counter)); + + int key = rnd.Uniform(kNumKeys); + char keybuf[20]; + snprintf(keybuf, sizeof(keybuf), "%016d", key); + + if (rnd.OneIn(2)) { + // Write values of the form . + // We add some padding for force compactions. + snprintf(valbuf, sizeof(valbuf), "%d.%d.%-1000d", + key, id, static_cast(counter)); + ASSERT_OK(db->Put(WriteOptions(), Slice(keybuf), Slice(valbuf))); + } else { + // Read a value and verify that it matches the pattern written above. + Status s = db->Get(ReadOptions(), Slice(keybuf), &value); + if (s.IsNotFound()) { + // Key has not yet been written + } else { + // Check that the writer thread counter is >= the counter in the value + ASSERT_OK(s); + int k, w, c; + ASSERT_EQ(3, sscanf(value.c_str(), "%d.%d.%d", &k, &w, &c)) << value; + ASSERT_EQ(k, key); + ASSERT_GE(w, 0); + ASSERT_LT(w, kNumThreads); + ASSERT_LE((unsigned int)c, reinterpret_cast( + t->state->counter[w].Acquire_Load())); + } + } + counter++; + } + t->state->thread_done[id].Release_Store(t); + fprintf(stderr, "... stopping thread %d after %d ops\n", id, int(counter)); +} + +} // namespace + +TEST(DBTest, MultiThreaded) { + do { + // Initialize state + MTState mt; + mt.test = this; + mt.stop.Release_Store(0); + for (int id = 0; id < kNumThreads; id++) { + mt.counter[id].Release_Store(0); + mt.thread_done[id].Release_Store(0); + } + + // Start threads + MTThread thread[kNumThreads]; + for (int id = 0; id < kNumThreads; id++) { + thread[id].state = &mt; + thread[id].id = id; + env_->StartThread(MTThreadBody, &thread[id]); + } + + // Let them run for a while + env_->SleepForMicroseconds(kTestSeconds * 1000000); + + // Stop the threads and wait for them to finish + mt.stop.Release_Store(&mt); + for (int id = 0; id < kNumThreads; id++) { + while (mt.thread_done[id].Acquire_Load() == nullptr) { + env_->SleepForMicroseconds(100000); + } + } + } while (ChangeOptions()); +} + +namespace { +typedef std::map KVMap; +} + +class ModelDB: public DB { + public: + class ModelSnapshot : public Snapshot { + public: + KVMap map_; + }; + + explicit ModelDB(const Options& options): options_(options) { } + virtual Status Put(const WriteOptions& o, const Slice& k, const Slice& v) { + return DB::Put(o, k, v); + } + virtual Status Delete(const WriteOptions& o, const Slice& key) { + return DB::Delete(o, key); + } + virtual Status Get(const ReadOptions& options, + const Slice& key, std::string* value) { + assert(false); // Not implemented + return Status::NotFound(key); + } + virtual Iterator* NewIterator(const ReadOptions& options) { + if (options.snapshot == nullptr) { + KVMap* saved = new KVMap; + *saved = map_; + return new ModelIter(saved, true); + } else { + const KVMap* snapshot_state = + &(reinterpret_cast(options.snapshot)->map_); + return new ModelIter(snapshot_state, false); + } + } + virtual const Snapshot* GetSnapshot() { + ModelSnapshot* snapshot = new ModelSnapshot; + snapshot->map_ = map_; + return snapshot; + } + + virtual void ReleaseSnapshot(const Snapshot* snapshot) { + delete reinterpret_cast(snapshot); + } + virtual Status Write(const WriteOptions& options, WriteBatch* batch) { + class Handler : public WriteBatch::Handler { + public: + KVMap* map_; + virtual void Put(const Slice& key, const Slice& value) { + (*map_)[key.ToString()] = value.ToString(); + } + virtual void Delete(const Slice& key) { + map_->erase(key.ToString()); + } + }; + Handler handler; + handler.map_ = &map_; + return batch->Iterate(&handler); + } + + virtual bool GetProperty(const Slice& property, std::string* value) { + return false; + } + virtual void GetApproximateSizes(const Range* r, int n, uint64_t* sizes) { + for (int i = 0; i < n; i++) { + sizes[i] = 0; + } + } + virtual void CompactRange(const Slice* start, const Slice* end) { + } + + virtual int NumberLevels() + { + return 1; + } + + virtual int MaxMemCompactionLevel() + { + return 1; + } + + virtual int Level0StopWriteTrigger() + { + return -1; + } + + virtual Status Flush(const leveldb::FlushOptions& options) { + Status ret; + return ret; + } + + virtual Status DisableFileDeletions() { + return Status::OK(); + } + virtual Status EnableFileDeletions() { + return Status::OK(); + } + virtual Status GetLiveFiles(std::vector&, uint64_t* size) { + return Status::OK(); + } + + virtual SequenceNumber GetLatestSequenceNumber() { + return 0; + } + virtual Status GetUpdatesSince(leveldb::SequenceNumber, + unique_ptr*) { + return Status::NotSupported("Not supported in Model DB"); + } + + private: + class ModelIter: public Iterator { + public: + ModelIter(const KVMap* map, bool owned) + : map_(map), owned_(owned), iter_(map_->end()) { + } + ~ModelIter() { + if (owned_) delete map_; + } + virtual bool Valid() const { return iter_ != map_->end(); } + virtual void SeekToFirst() { iter_ = map_->begin(); } + virtual void SeekToLast() { + if (map_->empty()) { + iter_ = map_->end(); + } else { + iter_ = map_->find(map_->rbegin()->first); + } + } + virtual void Seek(const Slice& k) { + iter_ = map_->lower_bound(k.ToString()); + } + virtual void Next() { ++iter_; } + virtual void Prev() { --iter_; } + virtual Slice key() const { return iter_->first; } + virtual Slice value() const { return iter_->second; } + virtual Status status() const { return Status::OK(); } + private: + const KVMap* const map_; + const bool owned_; // Do we own map_ + KVMap::const_iterator iter_; + }; + const Options options_; + KVMap map_; +}; + +static std::string RandomKey(Random* rnd) { + int len = (rnd->OneIn(3) + ? 1 // Short sometimes to encourage collisions + : (rnd->OneIn(100) ? rnd->Skewed(10) : rnd->Uniform(10))); + return test::RandomKey(rnd, len); +} + +static bool CompareIterators(int step, + DB* model, + DB* db, + const Snapshot* model_snap, + const Snapshot* db_snap) { + ReadOptions options; + options.snapshot = model_snap; + Iterator* miter = model->NewIterator(options); + options.snapshot = db_snap; + Iterator* dbiter = db->NewIterator(options); + bool ok = true; + int count = 0; + for (miter->SeekToFirst(), dbiter->SeekToFirst(); + ok && miter->Valid() && dbiter->Valid(); + miter->Next(), dbiter->Next()) { + count++; + if (miter->key().compare(dbiter->key()) != 0) { + fprintf(stderr, "step %d: Key mismatch: '%s' vs. '%s'\n", + step, + EscapeString(miter->key()).c_str(), + EscapeString(dbiter->key()).c_str()); + ok = false; + break; + } + + if (miter->value().compare(dbiter->value()) != 0) { + fprintf(stderr, "step %d: Value mismatch for key '%s': '%s' vs. '%s'\n", + step, + EscapeString(miter->key()).c_str(), + EscapeString(miter->value()).c_str(), + EscapeString(miter->value()).c_str()); + ok = false; + } + } + + if (ok) { + if (miter->Valid() != dbiter->Valid()) { + fprintf(stderr, "step %d: Mismatch at end of iterators: %d vs. %d\n", + step, miter->Valid(), dbiter->Valid()); + ok = false; + } + } + delete miter; + delete dbiter; + return ok; +} + +TEST(DBTest, Randomized) { + Random rnd(test::RandomSeed()); + do { + ModelDB model(CurrentOptions()); + const int N = 10000; + const Snapshot* model_snap = nullptr; + const Snapshot* db_snap = nullptr; + std::string k, v; + for (int step = 0; step < N; step++) { + // TODO(sanjay): Test Get() works + int p = rnd.Uniform(100); + if (p < 45) { // Put + k = RandomKey(&rnd); + v = RandomString(&rnd, + rnd.OneIn(20) + ? 100 + rnd.Uniform(100) + : rnd.Uniform(8)); + ASSERT_OK(model.Put(WriteOptions(), k, v)); + ASSERT_OK(db_->Put(WriteOptions(), k, v)); + + } else if (p < 90) { // Delete + k = RandomKey(&rnd); + ASSERT_OK(model.Delete(WriteOptions(), k)); + ASSERT_OK(db_->Delete(WriteOptions(), k)); + + + } else { // Multi-element batch + WriteBatch b; + const int num = rnd.Uniform(8); + for (int i = 0; i < num; i++) { + if (i == 0 || !rnd.OneIn(10)) { + k = RandomKey(&rnd); + } else { + // Periodically re-use the same key from the previous iter, so + // we have multiple entries in the write batch for the same key + } + if (rnd.OneIn(2)) { + v = RandomString(&rnd, rnd.Uniform(10)); + b.Put(k, v); + } else { + b.Delete(k); + } + } + ASSERT_OK(model.Write(WriteOptions(), &b)); + ASSERT_OK(db_->Write(WriteOptions(), &b)); + } + + if ((step % 100) == 0) { + ASSERT_TRUE(CompareIterators(step, &model, db_, nullptr, nullptr)); + ASSERT_TRUE(CompareIterators(step, &model, db_, model_snap, db_snap)); + // Save a snapshot from each DB this time that we'll use next + // time we compare things, to make sure the current state is + // preserved with the snapshot + if (model_snap != nullptr) model.ReleaseSnapshot(model_snap); + if (db_snap != nullptr) db_->ReleaseSnapshot(db_snap); + + Reopen(); + ASSERT_TRUE(CompareIterators(step, &model, db_, nullptr, nullptr)); + + model_snap = model.GetSnapshot(); + db_snap = db_->GetSnapshot(); + } + } + if (model_snap != nullptr) model.ReleaseSnapshot(model_snap); + if (db_snap != nullptr) db_->ReleaseSnapshot(db_snap); + } while (ChangeOptions()); +} + +std::string MakeKey(unsigned int num) { + char buf[30]; + snprintf(buf, sizeof(buf), "%016u", num); + return std::string(buf); +} + +void BM_LogAndApply(int iters, int num_base_files) { + std::string dbname = test::TmpDir() + "/leveldb_test_benchmark"; + DestroyDB(dbname, Options()); + + DB* db = nullptr; + Options opts; + opts.create_if_missing = true; + Status s = DB::Open(opts, dbname, &db); + ASSERT_OK(s); + ASSERT_TRUE(db != nullptr); + + delete db; + db = nullptr; + + Env* env = Env::Default(); + + port::Mutex mu; + MutexLock l(&mu); + + InternalKeyComparator cmp(BytewiseComparator()); + Options options; + VersionSet vset(dbname, &options, nullptr, &cmp); + ASSERT_OK(vset.Recover()); + VersionEdit vbase(vset.NumberLevels()); + uint64_t fnum = 1; + for (int i = 0; i < num_base_files; i++) { + InternalKey start(MakeKey(2*fnum), 1, kTypeValue); + InternalKey limit(MakeKey(2*fnum+1), 1, kTypeDeletion); + vbase.AddFile(2, fnum++, 1 /* file size */, start, limit); + } + ASSERT_OK(vset.LogAndApply(&vbase, &mu)); + + uint64_t start_micros = env->NowMicros(); + + for (int i = 0; i < iters; i++) { + VersionEdit vedit(vset.NumberLevels()); + vedit.DeleteFile(2, fnum); + InternalKey start(MakeKey(2*fnum), 1, kTypeValue); + InternalKey limit(MakeKey(2*fnum+1), 1, kTypeDeletion); + vedit.AddFile(2, fnum++, 1 /* file size */, start, limit); + vset.LogAndApply(&vedit, &mu); + } + uint64_t stop_micros = env->NowMicros(); + unsigned int us = stop_micros - start_micros; + char buf[16]; + snprintf(buf, sizeof(buf), "%d", num_base_files); + fprintf(stderr, + "BM_LogAndApply/%-6s %8d iters : %9u us (%7.0f us / iter)\n", + buf, iters, us, ((float)us) / iters); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + if (argc > 1 && std::string(argv[1]) == "--benchmark") { + leveldb::BM_LogAndApply(1000, 1); + leveldb::BM_LogAndApply(1000, 100); + leveldb::BM_LogAndApply(1000, 10000); + leveldb::BM_LogAndApply(100, 100000); + return 0; + } + + return leveldb::test::RunAllTests(); +} diff --git a/db/dbformat.cc b/db/dbformat.cc new file mode 100644 index 00000000..7b7336ab --- /dev/null +++ b/db/dbformat.cc @@ -0,0 +1,140 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include "db/dbformat.h" +#include "port/port.h" +#include "util/coding.h" + +namespace leveldb { + +static uint64_t PackSequenceAndType(uint64_t seq, ValueType t) { + assert(seq <= kMaxSequenceNumber); + assert(t <= kValueTypeForSeek); + return (seq << 8) | t; +} + +void AppendInternalKey(std::string* result, const ParsedInternalKey& key) { + result->append(key.user_key.data(), key.user_key.size()); + PutFixed64(result, PackSequenceAndType(key.sequence, key.type)); +} + +std::string ParsedInternalKey::DebugString(bool hex) const { + char buf[50]; + snprintf(buf, sizeof(buf), "' @ %llu : %d", + (unsigned long long) sequence, + int(type)); + std::string result = "'"; + result += user_key.ToString(hex); + result += buf; + return result; +} + +std::string InternalKey::DebugString(bool hex) const { + std::string result; + ParsedInternalKey parsed; + if (ParseInternalKey(rep_, &parsed)) { + result = parsed.DebugString(hex); + } else { + result = "(bad)"; + result.append(EscapeString(rep_)); + } + return result; +} + +const char* InternalKeyComparator::Name() const { + return "leveldb.InternalKeyComparator"; +} + +int InternalKeyComparator::Compare(const Slice& akey, const Slice& bkey) const { + // Order by: + // increasing user key (according to user-supplied comparator) + // decreasing sequence number + // decreasing type (though sequence# should be enough to disambiguate) + int r = user_comparator_->Compare(ExtractUserKey(akey), ExtractUserKey(bkey)); + if (r == 0) { + const uint64_t anum = DecodeFixed64(akey.data() + akey.size() - 8); + const uint64_t bnum = DecodeFixed64(bkey.data() + bkey.size() - 8); + if (anum > bnum) { + r = -1; + } else if (anum < bnum) { + r = +1; + } + } + return r; +} + +void InternalKeyComparator::FindShortestSeparator( + std::string* start, + const Slice& limit) const { + // Attempt to shorten the user portion of the key + Slice user_start = ExtractUserKey(*start); + Slice user_limit = ExtractUserKey(limit); + std::string tmp(user_start.data(), user_start.size()); + user_comparator_->FindShortestSeparator(&tmp, user_limit); + if (tmp.size() < user_start.size() && + user_comparator_->Compare(user_start, tmp) < 0) { + // User key has become shorter physically, but larger logically. + // Tack on the earliest possible number to the shortened user key. + PutFixed64(&tmp, PackSequenceAndType(kMaxSequenceNumber,kValueTypeForSeek)); + assert(this->Compare(*start, tmp) < 0); + assert(this->Compare(tmp, limit) < 0); + start->swap(tmp); + } +} + +void InternalKeyComparator::FindShortSuccessor(std::string* key) const { + Slice user_key = ExtractUserKey(*key); + std::string tmp(user_key.data(), user_key.size()); + user_comparator_->FindShortSuccessor(&tmp); + if (tmp.size() < user_key.size() && + user_comparator_->Compare(user_key, tmp) < 0) { + // User key has become shorter physically, but larger logically. + // Tack on the earliest possible number to the shortened user key. + PutFixed64(&tmp, PackSequenceAndType(kMaxSequenceNumber,kValueTypeForSeek)); + assert(this->Compare(*key, tmp) < 0); + key->swap(tmp); + } +} + +const char* InternalFilterPolicy::Name() const { + return user_policy_->Name(); +} + +void InternalFilterPolicy::CreateFilter(const Slice* keys, int n, + std::string* dst) const { + // We rely on the fact that the code in table.cc does not mind us + // adjusting keys[]. + Slice* mkey = const_cast(keys); + for (int i = 0; i < n; i++) { + mkey[i] = ExtractUserKey(keys[i]); + // TODO(sanjay): Suppress dups? + } + user_policy_->CreateFilter(keys, n, dst); +} + +bool InternalFilterPolicy::KeyMayMatch(const Slice& key, const Slice& f) const { + return user_policy_->KeyMayMatch(ExtractUserKey(key), f); +} + +LookupKey::LookupKey(const Slice& user_key, SequenceNumber s) { + size_t usize = user_key.size(); + size_t needed = usize + 13; // A conservative estimate + char* dst; + if (needed <= sizeof(space_)) { + dst = space_; + } else { + dst = new char[needed]; + } + start_ = dst; + dst = EncodeVarint32(dst, usize + 8); + kstart_ = dst; + memcpy(dst, user_key.data(), usize); + dst += usize; + EncodeFixed64(dst, PackSequenceAndType(s, kValueTypeForSeek)); + dst += 8; + end_ = dst; +} + +} // namespace leveldb diff --git a/db/dbformat.h b/db/dbformat.h new file mode 100644 index 00000000..fb8525b0 --- /dev/null +++ b/db/dbformat.h @@ -0,0 +1,212 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_FORMAT_H_ +#define STORAGE_LEVELDB_DB_FORMAT_H_ + +#include +#include "leveldb/comparator.h" +#include "leveldb/db.h" +#include "leveldb/filter_policy.h" +#include "leveldb/slice.h" +#include "leveldb/table_builder.h" +#include "leveldb/types.h" +#include "util/coding.h" +#include "util/logging.h" + +namespace leveldb { + +class InternalKey; + +// Value types encoded as the last component of internal keys. +// DO NOT CHANGE THESE ENUM VALUES: they are embedded in the on-disk +// data structures. +enum ValueType { + kTypeDeletion = 0x0, + kTypeValue = 0x1 +}; +// kValueTypeForSeek defines the ValueType that should be passed when +// constructing a ParsedInternalKey object for seeking to a particular +// sequence number (since we sort sequence numbers in decreasing order +// and the value type is embedded as the low 8 bits in the sequence +// number in internal keys, we need to use the highest-numbered +// ValueType, not the lowest). +static const ValueType kValueTypeForSeek = kTypeValue; + +// We leave eight bits empty at the bottom so a type and sequence# +// can be packed together into 64-bits. +static const SequenceNumber kMaxSequenceNumber = + ((0x1ull << 56) - 1); + +struct ParsedInternalKey { + Slice user_key; + SequenceNumber sequence; + ValueType type; + + ParsedInternalKey() { } // Intentionally left uninitialized (for speed) + ParsedInternalKey(const Slice& u, const SequenceNumber& seq, ValueType t) + : user_key(u), sequence(seq), type(t) { } + std::string DebugString(bool hex = false) const; +}; + +// Return the length of the encoding of "key". +inline size_t InternalKeyEncodingLength(const ParsedInternalKey& key) { + return key.user_key.size() + 8; +} + +// Append the serialization of "key" to *result. +extern void AppendInternalKey(std::string* result, + const ParsedInternalKey& key); + +// Attempt to parse an internal key from "internal_key". On success, +// stores the parsed data in "*result", and returns true. +// +// On error, returns false, leaves "*result" in an undefined state. +extern bool ParseInternalKey(const Slice& internal_key, + ParsedInternalKey* result); + +// Returns the user key portion of an internal key. +inline Slice ExtractUserKey(const Slice& internal_key) { + assert(internal_key.size() >= 8); + return Slice(internal_key.data(), internal_key.size() - 8); +} + +inline ValueType ExtractValueType(const Slice& internal_key) { + assert(internal_key.size() >= 8); + const size_t n = internal_key.size(); + uint64_t num = DecodeFixed64(internal_key.data() + n - 8); + unsigned char c = num & 0xff; + return static_cast(c); +} + +// A comparator for internal keys that uses a specified comparator for +// the user key portion and breaks ties by decreasing sequence number. +class InternalKeyComparator : public Comparator { + private: + const Comparator* user_comparator_; + public: + explicit InternalKeyComparator(const Comparator* c) : user_comparator_(c) { } + virtual const char* Name() const; + virtual int Compare(const Slice& a, const Slice& b) const; + virtual void FindShortestSeparator( + std::string* start, + const Slice& limit) const; + virtual void FindShortSuccessor(std::string* key) const; + + const Comparator* user_comparator() const { return user_comparator_; } + + int Compare(const InternalKey& a, const InternalKey& b) const; +}; + +// Filter policy wrapper that converts from internal keys to user keys +class InternalFilterPolicy : public FilterPolicy { + private: + const FilterPolicy* const user_policy_; + public: + explicit InternalFilterPolicy(const FilterPolicy* p) : user_policy_(p) { } + virtual const char* Name() const; + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const; + virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const; +}; + +// Modules in this directory should keep internal keys wrapped inside +// the following class instead of plain strings so that we do not +// incorrectly use string comparisons instead of an InternalKeyComparator. +class InternalKey { + private: + std::string rep_; + public: + InternalKey() { } // Leave rep_ as empty to indicate it is invalid + InternalKey(const Slice& user_key, SequenceNumber s, ValueType t) { + AppendInternalKey(&rep_, ParsedInternalKey(user_key, s, t)); + } + + void DecodeFrom(const Slice& s) { rep_.assign(s.data(), s.size()); } + Slice Encode() const { + assert(!rep_.empty()); + return rep_; + } + + Slice user_key() const { return ExtractUserKey(rep_); } + + void SetFrom(const ParsedInternalKey& p) { + rep_.clear(); + AppendInternalKey(&rep_, p); + } + + void Clear() { rep_.clear(); } + + std::string DebugString(bool hex = false) const; +}; + +inline int InternalKeyComparator::Compare( + const InternalKey& a, const InternalKey& b) const { + return Compare(a.Encode(), b.Encode()); +} + +inline bool ParseInternalKey(const Slice& internal_key, + ParsedInternalKey* result) { + const size_t n = internal_key.size(); + if (n < 8) return false; + uint64_t num = DecodeFixed64(internal_key.data() + n - 8); + unsigned char c = num & 0xff; + result->sequence = num >> 8; + result->type = static_cast(c); + result->user_key = Slice(internal_key.data(), n - 8); + return (c <= static_cast(kTypeValue)); +} + +// Update the sequence number in the internal key +inline void UpdateInternalKey(char* internal_key, + const size_t internal_key_size, + uint64_t seq, ValueType t) { + assert(internal_key_size >= 8); + char* seqtype = internal_key + internal_key_size - 8; + uint64_t newval = (seq << 8) | t; + EncodeFixed64(seqtype, newval); +} + +// A helper class useful for DBImpl::Get() +class LookupKey { + public: + // Initialize *this for looking up user_key at a snapshot with + // the specified sequence number. + LookupKey(const Slice& user_key, SequenceNumber sequence); + + ~LookupKey(); + + // Return a key suitable for lookup in a MemTable. + Slice memtable_key() const { return Slice(start_, end_ - start_); } + + // Return an internal key (suitable for passing to an internal iterator) + Slice internal_key() const { return Slice(kstart_, end_ - kstart_); } + + // Return the user key + Slice user_key() const { return Slice(kstart_, end_ - kstart_ - 8); } + + private: + // We construct a char array of the form: + // klength varint32 <-- start_ + // userkey char[klength] <-- kstart_ + // tag uint64 + // <-- end_ + // The array is a suitable MemTable key. + // The suffix starting with "userkey" can be used as an InternalKey. + const char* start_; + const char* kstart_; + const char* end_; + char space_[200]; // Avoid allocation for short keys + + // No copying allowed + LookupKey(const LookupKey&); + void operator=(const LookupKey&); +}; + +inline LookupKey::~LookupKey() { + if (start_ != space_) delete[] start_; +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_FORMAT_H_ diff --git a/db/dbformat_test.cc b/db/dbformat_test.cc new file mode 100644 index 00000000..83094544 --- /dev/null +++ b/db/dbformat_test.cc @@ -0,0 +1,112 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/dbformat.h" +#include "util/logging.h" +#include "util/testharness.h" + +namespace leveldb { + +static std::string IKey(const std::string& user_key, + uint64_t seq, + ValueType vt) { + std::string encoded; + AppendInternalKey(&encoded, ParsedInternalKey(user_key, seq, vt)); + return encoded; +} + +static std::string Shorten(const std::string& s, const std::string& l) { + std::string result = s; + InternalKeyComparator(BytewiseComparator()).FindShortestSeparator(&result, l); + return result; +} + +static std::string ShortSuccessor(const std::string& s) { + std::string result = s; + InternalKeyComparator(BytewiseComparator()).FindShortSuccessor(&result); + return result; +} + +static void TestKey(const std::string& key, + uint64_t seq, + ValueType vt) { + std::string encoded = IKey(key, seq, vt); + + Slice in(encoded); + ParsedInternalKey decoded("", 0, kTypeValue); + + ASSERT_TRUE(ParseInternalKey(in, &decoded)); + ASSERT_EQ(key, decoded.user_key.ToString()); + ASSERT_EQ(seq, decoded.sequence); + ASSERT_EQ(vt, decoded.type); + + ASSERT_TRUE(!ParseInternalKey(Slice("bar"), &decoded)); +} + +class FormatTest { }; + +TEST(FormatTest, InternalKey_EncodeDecode) { + const char* keys[] = { "", "k", "hello", "longggggggggggggggggggggg" }; + const uint64_t seq[] = { + 1, 2, 3, + (1ull << 8) - 1, 1ull << 8, (1ull << 8) + 1, + (1ull << 16) - 1, 1ull << 16, (1ull << 16) + 1, + (1ull << 32) - 1, 1ull << 32, (1ull << 32) + 1 + }; + for (unsigned int k = 0; k < sizeof(keys) / sizeof(keys[0]); k++) { + for (unsigned int s = 0; s < sizeof(seq) / sizeof(seq[0]); s++) { + TestKey(keys[k], seq[s], kTypeValue); + TestKey("hello", 1, kTypeDeletion); + } + } +} + +TEST(FormatTest, InternalKeyShortSeparator) { + // When user keys are same + ASSERT_EQ(IKey("foo", 100, kTypeValue), + Shorten(IKey("foo", 100, kTypeValue), + IKey("foo", 99, kTypeValue))); + ASSERT_EQ(IKey("foo", 100, kTypeValue), + Shorten(IKey("foo", 100, kTypeValue), + IKey("foo", 101, kTypeValue))); + ASSERT_EQ(IKey("foo", 100, kTypeValue), + Shorten(IKey("foo", 100, kTypeValue), + IKey("foo", 100, kTypeValue))); + ASSERT_EQ(IKey("foo", 100, kTypeValue), + Shorten(IKey("foo", 100, kTypeValue), + IKey("foo", 100, kTypeDeletion))); + + // When user keys are misordered + ASSERT_EQ(IKey("foo", 100, kTypeValue), + Shorten(IKey("foo", 100, kTypeValue), + IKey("bar", 99, kTypeValue))); + + // When user keys are different, but correctly ordered + ASSERT_EQ(IKey("g", kMaxSequenceNumber, kValueTypeForSeek), + Shorten(IKey("foo", 100, kTypeValue), + IKey("hello", 200, kTypeValue))); + + // When start user key is prefix of limit user key + ASSERT_EQ(IKey("foo", 100, kTypeValue), + Shorten(IKey("foo", 100, kTypeValue), + IKey("foobar", 200, kTypeValue))); + + // When limit user key is prefix of start user key + ASSERT_EQ(IKey("foobar", 100, kTypeValue), + Shorten(IKey("foobar", 100, kTypeValue), + IKey("foo", 200, kTypeValue))); +} + +TEST(FormatTest, InternalKeyShortestSuccessor) { + ASSERT_EQ(IKey("g", kMaxSequenceNumber, kValueTypeForSeek), + ShortSuccessor(IKey("foo", 100, kTypeValue))); + ASSERT_EQ(IKey("\xff\xff", 100, kTypeValue), + ShortSuccessor(IKey("\xff\xff", 100, kTypeValue))); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/db/filename.cc b/db/filename.cc new file mode 100644 index 00000000..81a14215 --- /dev/null +++ b/db/filename.cc @@ -0,0 +1,217 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/filename.h" + +#include +#include +#include "db/dbformat.h" +#include "leveldb/env.h" +#include "util/logging.h" + +namespace leveldb { + +// Given a path, flatten the path name by replacing all chars not in +// {[0-9,a-z,A-Z,-,_,.]} with _. And append '\0' at the end. +// Return the number of chars stored in dest not including the trailing '\0'. +static int FlattenPath(const std::string& path, char* dest, int len) { + int write_idx = 0; + int i = 0; + int src_len = path.size(); + + while (i < src_len && write_idx < len - 1) { + if ((path[i] >= 'a' && path[i] <= 'z') || + (path[i] >= '0' && path[i] <= '9') || + (path[i] >= 'A' && path[i] <= 'Z') || + path[i] == '-' || + path[i] == '.' || + path[i] == '_'){ + dest[write_idx++] = path[i]; + } else { + if (i > 0) + dest[write_idx++] = '_'; + } + i++; + } + + dest[write_idx] = '\0'; + return write_idx; +} + +// A utility routine: write "data" to the named file and Sync() it. +extern Status WriteStringToFileSync(Env* env, const Slice& data, + const std::string& fname); + +static std::string MakeFileName(const std::string& name, uint64_t number, + const char* suffix) { + char buf[100]; + snprintf(buf, sizeof(buf), "/%06llu.%s", + static_cast(number), + suffix); + return name + buf; +} + +std::string LogFileName(const std::string& name, uint64_t number) { + assert(number > 0); + return MakeFileName(name, number, "log"); +} + +std::string ArchivalDirectory(const std::string& dbname) { + return dbname + "/" + ARCHIVAL_DIR; +} +std::string ArchivedLogFileName(const std::string& name, uint64_t number) { + assert(number > 0); + return MakeFileName(name + "/archive", number, "log"); +} + +std::string TableFileName(const std::string& name, uint64_t number) { + assert(number > 0); + return MakeFileName(name, number, "sst"); +} + +std::string DescriptorFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + char buf[100]; + snprintf(buf, sizeof(buf), "/MANIFEST-%06llu", + static_cast(number)); + return dbname + buf; +} + +std::string CurrentFileName(const std::string& dbname) { + return dbname + "/CURRENT"; +} + +std::string LockFileName(const std::string& dbname) { + return dbname + "/LOCK"; +} + +std::string TempFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + return MakeFileName(dbname, number, "dbtmp"); +} + +std::string InfoLogFileName(const std::string& dbname, + const std::string& db_path, const std::string& log_dir) { + if (log_dir.empty()) + return dbname + "/LOG"; + + char flatten_db_path[256]; + FlattenPath(db_path, flatten_db_path, 256); + return log_dir + "/" + flatten_db_path + "_LOG"; +} + +// Return the name of the old info log file for "dbname". +std::string OldInfoLogFileName(const std::string& dbname, uint64_t ts, + const std::string& db_path, const std::string& log_dir) { + char buf[50]; + snprintf(buf, sizeof(buf), "%llu", static_cast(ts)); + + if (log_dir.empty()) + return dbname + "/LOG.old." + buf; + + char flatten_db_path[256]; + FlattenPath(db_path, flatten_db_path, 256); + return log_dir + "/" + flatten_db_path + "_LOG.old." + buf; +} + +std::string MetaDatabaseName(const std::string& dbname, uint64_t number) { + char buf[100]; + snprintf(buf, sizeof(buf), "/METADB-%llu", + static_cast(number)); + return dbname + buf; +} + +// Owned filenames have the form: +// dbname/CURRENT +// dbname/LOCK +// dbname/LOG +// dbname/LOG.old.[0-9]+ +// dbname/MANIFEST-[0-9]+ +// dbname/[0-9]+.(log|sst) +// dbname/METADB-[0-9]+ +bool ParseFileName(const std::string& fname, + uint64_t* number, + FileType* type) { + Slice rest(fname); + if (rest == "CURRENT") { + *number = 0; + *type = kCurrentFile; + } else if (rest == "LOCK") { + *number = 0; + *type = kDBLockFile; + } else if (rest == "LOG" || rest == "LOG.old") { + *number = 0; + *type = kInfoLogFile; + } else if (rest.starts_with("LOG.old.")) { + uint64_t ts_suffix; + // sizeof also counts the trailing '\0'. + rest.remove_prefix(sizeof("LOG.old.") - 1); + if (!ConsumeDecimalNumber(&rest, &ts_suffix)) { + return false; + } + *number = ts_suffix; + *type = kInfoLogFile; + } else if (rest.starts_with("MANIFEST-")) { + rest.remove_prefix(strlen("MANIFEST-")); + uint64_t num; + if (!ConsumeDecimalNumber(&rest, &num)) { + return false; + } + if (!rest.empty()) { + return false; + } + *type = kDescriptorFile; + *number = num; + } else if (rest.starts_with("METADB-")) { + rest.remove_prefix(strlen("METADB-")); + uint64_t num; + if (!ConsumeDecimalNumber(&rest, &num)) { + return false; + } + if (!rest.empty()) { + return false; + } + *type = kMetaDatabase; + *number = num; + } else { + // Avoid strtoull() to keep filename format independent of the + // current locale + uint64_t num; + if (!ConsumeDecimalNumber(&rest, &num)) { + return false; + } + Slice suffix = rest; + if (suffix == Slice(".log")) { + *type = kLogFile; + } else if (suffix == Slice(".sst")) { + *type = kTableFile; + } else if (suffix == Slice(".dbtmp")) { + *type = kTempFile; + } else { + return false; + } + *number = num; + } + return true; +} + +Status SetCurrentFile(Env* env, const std::string& dbname, + uint64_t descriptor_number) { + // Remove leading "dbname/" and add newline to manifest file name + std::string manifest = DescriptorFileName(dbname, descriptor_number); + Slice contents = manifest; + assert(contents.starts_with(dbname + "/")); + contents.remove_prefix(dbname.size() + 1); + std::string tmp = TempFileName(dbname, descriptor_number); + Status s = WriteStringToFileSync(env, contents.ToString() + "\n", tmp); + if (s.ok()) { + s = env->RenameFile(tmp, CurrentFileName(dbname)); + } + if (!s.ok()) { + env->DeleteFile(tmp); + } + return s; +} + +} // namespace leveldb diff --git a/db/filename.h b/db/filename.h new file mode 100644 index 00000000..53a15a5f --- /dev/null +++ b/db/filename.h @@ -0,0 +1,97 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// File names used by DB code + +#ifndef STORAGE_LEVELDB_DB_FILENAME_H_ +#define STORAGE_LEVELDB_DB_FILENAME_H_ + +#include +#include +#include "leveldb/slice.h" +#include "leveldb/status.h" +#include "port/port.h" + +namespace leveldb { + +class Env; + +enum FileType { + kLogFile, + kDBLockFile, + kTableFile, + kDescriptorFile, + kCurrentFile, + kTempFile, + kInfoLogFile, // Either the current one, or an old one + kMetaDatabase +}; + +// Return the name of the log file with the specified number +// in the db named by "dbname". The result will be prefixed with +// "dbname". +extern std::string LogFileName(const std::string& dbname, uint64_t number); + +static const std::string ARCHIVAL_DIR = "archive"; + +extern std::string ArchivalDirectory(const std::string& dbname); + +// Return the name of the archived log file with the specified number +// in the db named by "dbname". The result will be prefixed with "dbname". +extern std::string ArchivedLogFileName(const std::string& dbname, + uint64_t num); + +// Return the name of the sstable with the specified number +// in the db named by "dbname". The result will be prefixed with +// "dbname". +extern std::string TableFileName(const std::string& dbname, uint64_t number); + +// Return the name of the descriptor file for the db named by +// "dbname" and the specified incarnation number. The result will be +// prefixed with "dbname". +extern std::string DescriptorFileName(const std::string& dbname, + uint64_t number); + +// Return the name of the current file. This file contains the name +// of the current manifest file. The result will be prefixed with +// "dbname". +extern std::string CurrentFileName(const std::string& dbname); + +// Return the name of the lock file for the db named by +// "dbname". The result will be prefixed with "dbname". +extern std::string LockFileName(const std::string& dbname); + +// Return the name of a temporary file owned by the db named "dbname". +// The result will be prefixed with "dbname". +extern std::string TempFileName(const std::string& dbname, uint64_t number); + +// Return the name of the info log file for "dbname". +extern std::string InfoLogFileName(const std::string& dbname, + const std::string& db_path="", const std::string& log_dir=""); + +// Return the name of the old info log file for "dbname". +extern std::string OldInfoLogFileName(const std::string& dbname, uint64_t ts, + const std::string& db_path="", const std::string& log_dir=""); + +// Return the name to use for a metadatabase. The result will be prefixed with +// "dbname". +extern std::string MetaDatabaseName(const std::string& dbname, + uint64_t number); + +// If filename is a leveldb file, store the type of the file in *type. +// The number encoded in the filename is stored in *number. If the +// filename was successfully parsed, returns true. Else return false. +extern bool ParseFileName(const std::string& filename, + uint64_t* number, + FileType* type); + +// Make the CURRENT file point to the descriptor file with the +// specified number. +extern Status SetCurrentFile(Env* env, const std::string& dbname, + uint64_t descriptor_number); + + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_FILENAME_H_ diff --git a/db/filename_test.cc b/db/filename_test.cc new file mode 100644 index 00000000..a1b2aa5e --- /dev/null +++ b/db/filename_test.cc @@ -0,0 +1,135 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/filename.h" + +#include "db/dbformat.h" +#include "port/port.h" +#include "util/logging.h" +#include "util/testharness.h" + +namespace leveldb { + +class FileNameTest { }; + +TEST(FileNameTest, Parse) { + Slice db; + FileType type; + uint64_t number; + + // Successful parses + static struct { + const char* fname; + uint64_t number; + FileType type; + } cases[] = { + { "100.log", 100, kLogFile }, + { "0.log", 0, kLogFile }, + { "0.sst", 0, kTableFile }, + { "CURRENT", 0, kCurrentFile }, + { "LOCK", 0, kDBLockFile }, + { "MANIFEST-2", 2, kDescriptorFile }, + { "MANIFEST-7", 7, kDescriptorFile }, + { "METADB-2", 2, kMetaDatabase }, + { "METADB-7", 7, kMetaDatabase }, + { "LOG", 0, kInfoLogFile }, + { "LOG.old", 0, kInfoLogFile }, + { "18446744073709551615.log", 18446744073709551615ull, kLogFile }, + }; + for (unsigned int i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { + std::string f = cases[i].fname; + ASSERT_TRUE(ParseFileName(f, &number, &type)) << f; + ASSERT_EQ(cases[i].type, type) << f; + ASSERT_EQ(cases[i].number, number) << f; + } + + // Errors + static const char* errors[] = { + "", + "foo", + "foo-dx-100.log", + ".log", + "", + "manifest", + "CURREN", + "CURRENTX", + "MANIFES", + "MANIFEST", + "MANIFEST-", + "XMANIFEST-3", + "MANIFEST-3x", + "META", + "METADB", + "METADB-", + "XMETADB-3", + "METADB-3x", + "LOC", + "LOCKx", + "LO", + "LOGx", + "18446744073709551616.log", + "184467440737095516150.log", + "100", + "100.", + "100.lop" + }; + for (unsigned int i = 0; i < sizeof(errors) / sizeof(errors[0]); i++) { + std::string f = errors[i]; + ASSERT_TRUE(!ParseFileName(f, &number, &type)) << f; + }; +} + +TEST(FileNameTest, Construction) { + uint64_t number; + FileType type; + std::string fname; + + fname = CurrentFileName("foo"); + ASSERT_EQ("foo/", std::string(fname.data(), 4)); + ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); + ASSERT_EQ(0U, number); + ASSERT_EQ(kCurrentFile, type); + + fname = LockFileName("foo"); + ASSERT_EQ("foo/", std::string(fname.data(), 4)); + ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); + ASSERT_EQ(0U, number); + ASSERT_EQ(kDBLockFile, type); + + fname = LogFileName("foo", 192); + ASSERT_EQ("foo/", std::string(fname.data(), 4)); + ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); + ASSERT_EQ(192U, number); + ASSERT_EQ(kLogFile, type); + + fname = TableFileName("bar", 200); + ASSERT_EQ("bar/", std::string(fname.data(), 4)); + ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); + ASSERT_EQ(200U, number); + ASSERT_EQ(kTableFile, type); + + fname = DescriptorFileName("bar", 100); + ASSERT_EQ("bar/", std::string(fname.data(), 4)); + ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); + ASSERT_EQ(100U, number); + ASSERT_EQ(kDescriptorFile, type); + + fname = TempFileName("tmp", 999); + ASSERT_EQ("tmp/", std::string(fname.data(), 4)); + ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); + ASSERT_EQ(999U, number); + ASSERT_EQ(kTempFile, type); + + fname = MetaDatabaseName("met", 100); + ASSERT_EQ("met/", std::string(fname.data(), 4)); + ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); + ASSERT_EQ(100U, number); + ASSERT_EQ(kMetaDatabase, type); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/db/log_file.h b/db/log_file.h new file mode 100644 index 00000000..da7808e6 --- /dev/null +++ b/db/log_file.h @@ -0,0 +1,48 @@ +// Copyright 2008-present Facebook. All Rights Reserved. + +#ifndef STORAGE_LEVELDB_DB_LOG_FILE_H_ +#define STORAGE_LEVELDB_DB_LOG_FILE_H_ + +namespace leveldb { + +enum WalFileType { + kArchivedLogFile = 0, + kAliveLogFile = 1 +} ; + +class LogFile { + + public: + uint64_t logNumber; + WalFileType type; + + LogFile(uint64_t logNum,WalFileType logType) : + logNumber(logNum), + type(logType) {} + + LogFile(const LogFile& that) { + logNumber = that.logNumber; + type = that.type; + } + + bool operator < (const LogFile& that) const { + return logNumber < that.logNumber; + } + + std::string ToString() const { + char response[100]; + const char* typeOfLog; + if (type == kAliveLogFile) { + typeOfLog = "Alive Log"; + } else { + typeOfLog = "Archived Log"; + } + sprintf(response, + "LogNumber : %ld LogType : %s", + logNumber, + typeOfLog); + return std::string(response); + } +}; +} // namespace leveldb +#endif // STORAGE_LEVELDB_DB_LOG_FILE_H_ diff --git a/db/log_format.h b/db/log_format.h new file mode 100644 index 00000000..2690cb97 --- /dev/null +++ b/db/log_format.h @@ -0,0 +1,35 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Log format information shared by reader and writer. +// See ../doc/log_format.txt for more detail. + +#ifndef STORAGE_LEVELDB_DB_LOG_FORMAT_H_ +#define STORAGE_LEVELDB_DB_LOG_FORMAT_H_ + +namespace leveldb { +namespace log { + +enum RecordType { + // Zero is reserved for preallocated files + kZeroType = 0, + + kFullType = 1, + + // For fragments + kFirstType = 2, + kMiddleType = 3, + kLastType = 4 +}; +static const int kMaxRecordType = kLastType; + +static const int kBlockSize = 32768; + +// Header is checksum (4 bytes), type (1 byte), length (2 bytes). +static const int kHeaderSize = 4 + 1 + 2; + +} // namespace log +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_LOG_FORMAT_H_ diff --git a/db/log_reader.cc b/db/log_reader.cc new file mode 100644 index 00000000..250470a1 --- /dev/null +++ b/db/log_reader.cc @@ -0,0 +1,259 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/log_reader.h" + +#include +#include "leveldb/env.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { +namespace log { + +Reader::Reporter::~Reporter() { +} + +Reader::Reader(unique_ptr&& file, Reporter* reporter, + bool checksum, uint64_t initial_offset) + : file_(std::move(file)), + reporter_(reporter), + checksum_(checksum), + backing_store_(new char[kBlockSize]), + buffer_(), + eof_(false), + last_record_offset_(0), + end_of_buffer_offset_(0), + initial_offset_(initial_offset) { +} + +Reader::~Reader() { + delete[] backing_store_; +} + +bool Reader::SkipToInitialBlock() { + size_t offset_in_block = initial_offset_ % kBlockSize; + uint64_t block_start_location = initial_offset_ - offset_in_block; + + // Don't search a block if we'd be in the trailer + if (offset_in_block > kBlockSize - 6) { + offset_in_block = 0; + block_start_location += kBlockSize; + } + + end_of_buffer_offset_ = block_start_location; + + // Skip to start of first block that can contain the initial record + if (block_start_location > 0) { + Status skip_status = file_->Skip(block_start_location); + if (!skip_status.ok()) { + ReportDrop(block_start_location, skip_status); + return false; + } + } + + return true; +} + +bool Reader::ReadRecord(Slice* record, std::string* scratch) { + if (last_record_offset_ < initial_offset_) { + if (!SkipToInitialBlock()) { + return false; + } + } + + scratch->clear(); + record->clear(); + bool in_fragmented_record = false; + // Record offset of the logical record that we're reading + // 0 is a dummy value to make compilers happy + uint64_t prospective_record_offset = 0; + + Slice fragment; + while (true) { + uint64_t physical_record_offset = end_of_buffer_offset_ - buffer_.size(); + const unsigned int record_type = ReadPhysicalRecord(&fragment); + switch (record_type) { + case kFullType: + if (in_fragmented_record) { + // Handle bug in earlier versions of log::Writer where + // it could emit an empty kFirstType record at the tail end + // of a block followed by a kFullType or kFirstType record + // at the beginning of the next block. + if (scratch->empty()) { + in_fragmented_record = false; + } else { + ReportCorruption(scratch->size(), "partial record without end(1)"); + } + } + prospective_record_offset = physical_record_offset; + scratch->clear(); + *record = fragment; + last_record_offset_ = prospective_record_offset; + return true; + + case kFirstType: + if (in_fragmented_record) { + // Handle bug in earlier versions of log::Writer where + // it could emit an empty kFirstType record at the tail end + // of a block followed by a kFullType or kFirstType record + // at the beginning of the next block. + if (scratch->empty()) { + in_fragmented_record = false; + } else { + ReportCorruption(scratch->size(), "partial record without end(2)"); + } + } + prospective_record_offset = physical_record_offset; + scratch->assign(fragment.data(), fragment.size()); + in_fragmented_record = true; + break; + + case kMiddleType: + if (!in_fragmented_record) { + ReportCorruption(fragment.size(), + "missing start of fragmented record(1)"); + } else { + scratch->append(fragment.data(), fragment.size()); + } + break; + + case kLastType: + if (!in_fragmented_record) { + ReportCorruption(fragment.size(), + "missing start of fragmented record(2)"); + } else { + scratch->append(fragment.data(), fragment.size()); + *record = Slice(*scratch); + last_record_offset_ = prospective_record_offset; + return true; + } + break; + + case kEof: + if (in_fragmented_record) { + ReportCorruption(scratch->size(), "partial record without end(3)"); + scratch->clear(); + } + return false; + + case kBadRecord: + if (in_fragmented_record) { + ReportCorruption(scratch->size(), "error in middle of record"); + in_fragmented_record = false; + scratch->clear(); + } + break; + + default: { + char buf[40]; + snprintf(buf, sizeof(buf), "unknown record type %u", record_type); + ReportCorruption( + (fragment.size() + (in_fragmented_record ? scratch->size() : 0)), + buf); + in_fragmented_record = false; + scratch->clear(); + break; + } + } + } + return false; +} + +uint64_t Reader::LastRecordOffset() { + return last_record_offset_; +} + +void Reader::ReportCorruption(size_t bytes, const char* reason) { + ReportDrop(bytes, Status::Corruption(reason)); +} + +void Reader::ReportDrop(size_t bytes, const Status& reason) { + if (reporter_ != nullptr && + end_of_buffer_offset_ - buffer_.size() - bytes >= initial_offset_) { + reporter_->Corruption(bytes, reason); + } +} + +unsigned int Reader::ReadPhysicalRecord(Slice* result) { + while (true) { + if (buffer_.size() < (size_t)kHeaderSize) { + if (!eof_) { + // Last read was a full read, so this is a trailer to skip + buffer_.clear(); + Status status = file_->Read(kBlockSize, &buffer_, backing_store_); + end_of_buffer_offset_ += buffer_.size(); + if (!status.ok()) { + buffer_.clear(); + ReportDrop(kBlockSize, status); + eof_ = true; + return kEof; + } else if (buffer_.size() < (size_t)kBlockSize) { + eof_ = true; + } + continue; + } else if (buffer_.size() == 0) { + // End of file + return kEof; + } else { + size_t drop_size = buffer_.size(); + buffer_.clear(); + ReportCorruption(drop_size, "truncated record at end of file"); + return kEof; + } + } + + // Parse the header + const char* header = buffer_.data(); + const uint32_t a = static_cast(header[4]) & 0xff; + const uint32_t b = static_cast(header[5]) & 0xff; + const unsigned int type = header[6]; + const uint32_t length = a | (b << 8); + if (kHeaderSize + length > buffer_.size()) { + size_t drop_size = buffer_.size(); + buffer_.clear(); + ReportCorruption(drop_size, "bad record length"); + return kBadRecord; + } + + if (type == kZeroType && length == 0) { + // Skip zero length record without reporting any drops since + // such records are produced by the mmap based writing code in + // env_posix.cc that preallocates file regions. + buffer_.clear(); + return kBadRecord; + } + + // Check crc + if (checksum_) { + uint32_t expected_crc = crc32c::Unmask(DecodeFixed32(header)); + uint32_t actual_crc = crc32c::Value(header + 6, 1 + length); + if (actual_crc != expected_crc) { + // Drop the rest of the buffer since "length" itself may have + // been corrupted and if we trust it, we could find some + // fragment of a real log record that just happens to look + // like a valid log record. + size_t drop_size = buffer_.size(); + buffer_.clear(); + ReportCorruption(drop_size, "checksum mismatch"); + return kBadRecord; + } + } + + buffer_.remove_prefix(kHeaderSize + length); + + // Skip physical record that started before initial_offset_ + if (end_of_buffer_offset_ - buffer_.size() - kHeaderSize - length < + initial_offset_) { + result->clear(); + return kBadRecord; + } + + *result = Slice(header + kHeaderSize, length); + return type; + } +} + +} // namespace log +} // namespace leveldb diff --git a/db/log_reader.h b/db/log_reader.h new file mode 100644 index 00000000..77ed5796 --- /dev/null +++ b/db/log_reader.h @@ -0,0 +1,112 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_LOG_READER_H_ +#define STORAGE_LEVELDB_DB_LOG_READER_H_ + +#include +#include + +#include "db/log_format.h" +#include "leveldb/slice.h" +#include "leveldb/status.h" + +namespace leveldb { + +class SequentialFile; +using std::unique_ptr; + +namespace log { + +class Reader { + public: + // Interface for reporting errors. + class Reporter { + public: + virtual ~Reporter(); + + // Some corruption was detected. "size" is the approximate number + // of bytes dropped due to the corruption. + virtual void Corruption(size_t bytes, const Status& status) = 0; + }; + + // Create a reader that will return log records from "*file". + // "*file" must remain live while this Reader is in use. + // + // If "reporter" is non-nullptr, it is notified whenever some data is + // dropped due to a detected corruption. "*reporter" must remain + // live while this Reader is in use. + // + // If "checksum" is true, verify checksums if available. + // + // The Reader will start reading at the first record located at physical + // position >= initial_offset within the file. + Reader(unique_ptr&& file, Reporter* reporter, + bool checksum, uint64_t initial_offset); + + ~Reader(); + + // Read the next record into *record. Returns true if read + // successfully, false if we hit end of the input. May use + // "*scratch" as temporary storage. The contents filled in *record + // will only be valid until the next mutating operation on this + // reader or the next mutation to *scratch. + bool ReadRecord(Slice* record, std::string* scratch); + + // Returns the physical offset of the last record returned by ReadRecord. + // + // Undefined before the first call to ReadRecord. + uint64_t LastRecordOffset(); + + SequentialFile* file() { return file_.get(); } + + private: + const unique_ptr file_; + Reporter* const reporter_; + bool const checksum_; + char* const backing_store_; + Slice buffer_; + bool eof_; // Last Read() indicated EOF by returning < kBlockSize + + // Offset of the last record returned by ReadRecord. + uint64_t last_record_offset_; + // Offset of the first location past the end of buffer_. + uint64_t end_of_buffer_offset_; + + // Offset at which to start looking for the first record to return + uint64_t const initial_offset_; + + // Extend record types with the following special values + enum { + kEof = kMaxRecordType + 1, + // Returned whenever we find an invalid physical record. + // Currently there are three situations in which this happens: + // * The record has an invalid CRC (ReadPhysicalRecord reports a drop) + // * The record is a 0-length record (No drop is reported) + // * The record is below constructor's initial_offset (No drop is reported) + kBadRecord = kMaxRecordType + 2 + }; + + // Skips all blocks that are completely before "initial_offset_". + // + // Returns true on success. Handles reporting. + bool SkipToInitialBlock(); + + // Return type, or one of the preceding special values + unsigned int ReadPhysicalRecord(Slice* result); + + // Reports dropped bytes to the reporter. + // buffer_ must be updated to remove the dropped bytes prior to invocation. + void ReportCorruption(size_t bytes, const char* reason); + void ReportDrop(size_t bytes, const Status& reason); + + // No copying allowed + Reader(const Reader&); + void operator=(const Reader&); +}; + +} // namespace log +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_LOG_READER_H_ diff --git a/db/log_test.cc b/db/log_test.cc new file mode 100644 index 00000000..1840090b --- /dev/null +++ b/db/log_test.cc @@ -0,0 +1,523 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "leveldb/env.h" +#include "util/coding.h" +#include "util/crc32c.h" +#include "util/random.h" +#include "util/testharness.h" + +namespace leveldb { +namespace log { + +// Construct a string of the specified length made out of the supplied +// partial string. +static std::string BigString(const std::string& partial_string, size_t n) { + std::string result; + while (result.size() < n) { + result.append(partial_string); + } + result.resize(n); + return result; +} + +// Construct a string from a number +static std::string NumberString(int n) { + char buf[50]; + snprintf(buf, sizeof(buf), "%d.", n); + return std::string(buf); +} + +// Return a skewed potentially long string +static std::string RandomSkewedString(int i, Random* rnd) { + return BigString(NumberString(i), rnd->Skewed(17)); +} + +class LogTest { + private: + class StringDest : public WritableFile { + public: + std::string contents_; + + virtual Status Close() { return Status::OK(); } + virtual Status Flush() { return Status::OK(); } + virtual Status Sync() { return Status::OK(); } + virtual Status Append(const Slice& slice) { + contents_.append(slice.data(), slice.size()); + return Status::OK(); + } + }; + + class StringSource : public SequentialFile { + public: + Slice contents_; + bool force_error_; + bool returned_partial_; + StringSource() : force_error_(false), returned_partial_(false) { } + + virtual Status Read(size_t n, Slice* result, char* scratch) { + ASSERT_TRUE(!returned_partial_) << "must not Read() after eof/error"; + + if (force_error_) { + force_error_ = false; + returned_partial_ = true; + return Status::Corruption("read error"); + } + + if (contents_.size() < n) { + n = contents_.size(); + returned_partial_ = true; + } + *result = Slice(contents_.data(), n); + contents_.remove_prefix(n); + return Status::OK(); + } + + virtual Status Skip(uint64_t n) { + if (n > contents_.size()) { + contents_.clear(); + return Status::NotFound("in-memory file skipepd past end"); + } + + contents_.remove_prefix(n); + + return Status::OK(); + } + }; + + class ReportCollector : public Reader::Reporter { + public: + size_t dropped_bytes_; + std::string message_; + + ReportCollector() : dropped_bytes_(0) { } + virtual void Corruption(size_t bytes, const Status& status) { + dropped_bytes_ += bytes; + message_.append(status.ToString()); + } + }; + + std::string& dest_contents() { + auto dest = dynamic_cast(writer_.file()); + assert(dest); + return dest->contents_; + } + + const std::string& dest_contents() const { + auto dest = dynamic_cast(writer_.file()); + assert(dest); + return dest->contents_; + } + + void reset_source_contents() { + auto src = dynamic_cast(reader_.file()); + assert(src); + src->contents_ = dest_contents(); + } + + unique_ptr dest_holder_; + unique_ptr source_holder_; + ReportCollector report_; + bool reading_; + Writer writer_; + Reader reader_; + + // Record metadata for testing initial offset functionality + static size_t initial_offset_record_sizes_[]; + static uint64_t initial_offset_last_record_offsets_[]; + + public: + LogTest() : dest_holder_(new StringDest), + source_holder_(new StringSource), + reading_(false), + writer_(std::move(dest_holder_)), + reader_(std::move(source_holder_), &report_, true/*checksum*/, + 0/*initial_offset*/) { + } + + void Write(const std::string& msg) { + ASSERT_TRUE(!reading_) << "Write() after starting to read"; + writer_.AddRecord(Slice(msg)); + } + + size_t WrittenBytes() const { + return dest_contents().size(); + } + + std::string Read() { + if (!reading_) { + reading_ = true; + reset_source_contents(); + } + std::string scratch; + Slice record; + if (reader_.ReadRecord(&record, &scratch)) { + return record.ToString(); + } else { + return "EOF"; + } + } + + void IncrementByte(int offset, int delta) { + dest_contents()[offset] += delta; + } + + void SetByte(int offset, char new_byte) { + dest_contents()[offset] = new_byte; + } + + void ShrinkSize(int bytes) { + dest_contents().resize(dest_contents().size() - bytes); + } + + void FixChecksum(int header_offset, int len) { + // Compute crc of type/len/data + uint32_t crc = crc32c::Value(&dest_contents()[header_offset+6], 1 + len); + crc = crc32c::Mask(crc); + EncodeFixed32(&dest_contents()[header_offset], crc); + } + + void ForceError() { + auto src = dynamic_cast(reader_.file()); + src->force_error_ = true; + } + + size_t DroppedBytes() const { + return report_.dropped_bytes_; + } + + std::string ReportMessage() const { + return report_.message_; + } + + // Returns OK iff recorded error message contains "msg" + std::string MatchError(const std::string& msg) const { + if (report_.message_.find(msg) == std::string::npos) { + return report_.message_; + } else { + return "OK"; + } + } + + void WriteInitialOffsetLog() { + for (int i = 0; i < 4; i++) { + std::string record(initial_offset_record_sizes_[i], + static_cast('a' + i)); + Write(record); + } + } + + void CheckOffsetPastEndReturnsNoRecords(uint64_t offset_past_end) { + WriteInitialOffsetLog(); + reading_ = true; + unique_ptr source(new StringSource); + source->contents_ = dest_contents(); + unique_ptr offset_reader( + new Reader(std::move(source), &report_, true/*checksum*/, + WrittenBytes() + offset_past_end)); + Slice record; + std::string scratch; + ASSERT_TRUE(!offset_reader->ReadRecord(&record, &scratch)); + } + + void CheckInitialOffsetRecord(uint64_t initial_offset, + int expected_record_offset) { + WriteInitialOffsetLog(); + reading_ = true; + unique_ptr source(new StringSource); + source->contents_ = dest_contents(); + unique_ptr offset_reader( + new Reader(std::move(source), &report_, true/*checksum*/, + initial_offset)); + Slice record; + std::string scratch; + ASSERT_TRUE(offset_reader->ReadRecord(&record, &scratch)); + ASSERT_EQ(initial_offset_record_sizes_[expected_record_offset], + record.size()); + ASSERT_EQ(initial_offset_last_record_offsets_[expected_record_offset], + offset_reader->LastRecordOffset()); + ASSERT_EQ((char)('a' + expected_record_offset), record.data()[0]); + } + +}; + +size_t LogTest::initial_offset_record_sizes_[] = + {10000, // Two sizable records in first block + 10000, + 2 * log::kBlockSize - 1000, // Span three blocks + 1}; + +uint64_t LogTest::initial_offset_last_record_offsets_[] = + {0, + kHeaderSize + 10000, + 2 * (kHeaderSize + 10000), + 2 * (kHeaderSize + 10000) + + (2 * log::kBlockSize - 1000) + 3 * kHeaderSize}; + + +TEST(LogTest, Empty) { + ASSERT_EQ("EOF", Read()); +} + +TEST(LogTest, ReadWrite) { + Write("foo"); + Write("bar"); + Write(""); + Write("xxxx"); + ASSERT_EQ("foo", Read()); + ASSERT_EQ("bar", Read()); + ASSERT_EQ("", Read()); + ASSERT_EQ("xxxx", Read()); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ("EOF", Read()); // Make sure reads at eof work +} + +TEST(LogTest, ManyBlocks) { + for (int i = 0; i < 100000; i++) { + Write(NumberString(i)); + } + for (int i = 0; i < 100000; i++) { + ASSERT_EQ(NumberString(i), Read()); + } + ASSERT_EQ("EOF", Read()); +} + +TEST(LogTest, Fragmentation) { + Write("small"); + Write(BigString("medium", 50000)); + Write(BigString("large", 100000)); + ASSERT_EQ("small", Read()); + ASSERT_EQ(BigString("medium", 50000), Read()); + ASSERT_EQ(BigString("large", 100000), Read()); + ASSERT_EQ("EOF", Read()); +} + +TEST(LogTest, MarginalTrailer) { + // Make a trailer that is exactly the same length as an empty record. + const int n = kBlockSize - 2*kHeaderSize; + Write(BigString("foo", n)); + ASSERT_EQ((unsigned int)(kBlockSize - kHeaderSize), WrittenBytes()); + Write(""); + Write("bar"); + ASSERT_EQ(BigString("foo", n), Read()); + ASSERT_EQ("", Read()); + ASSERT_EQ("bar", Read()); + ASSERT_EQ("EOF", Read()); +} + +TEST(LogTest, MarginalTrailer2) { + // Make a trailer that is exactly the same length as an empty record. + const int n = kBlockSize - 2*kHeaderSize; + Write(BigString("foo", n)); + ASSERT_EQ((unsigned int)(kBlockSize - kHeaderSize), WrittenBytes()); + Write("bar"); + ASSERT_EQ(BigString("foo", n), Read()); + ASSERT_EQ("bar", Read()); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ(0U, DroppedBytes()); + ASSERT_EQ("", ReportMessage()); +} + +TEST(LogTest, ShortTrailer) { + const int n = kBlockSize - 2*kHeaderSize + 4; + Write(BigString("foo", n)); + ASSERT_EQ((unsigned int)(kBlockSize - kHeaderSize + 4), WrittenBytes()); + Write(""); + Write("bar"); + ASSERT_EQ(BigString("foo", n), Read()); + ASSERT_EQ("", Read()); + ASSERT_EQ("bar", Read()); + ASSERT_EQ("EOF", Read()); +} + +TEST(LogTest, AlignedEof) { + const int n = kBlockSize - 2*kHeaderSize + 4; + Write(BigString("foo", n)); + ASSERT_EQ((unsigned int)(kBlockSize - kHeaderSize + 4), WrittenBytes()); + ASSERT_EQ(BigString("foo", n), Read()); + ASSERT_EQ("EOF", Read()); +} + +TEST(LogTest, RandomRead) { + const int N = 500; + Random write_rnd(301); + for (int i = 0; i < N; i++) { + Write(RandomSkewedString(i, &write_rnd)); + } + Random read_rnd(301); + for (int i = 0; i < N; i++) { + ASSERT_EQ(RandomSkewedString(i, &read_rnd), Read()); + } + ASSERT_EQ("EOF", Read()); +} + +// Tests of all the error paths in log_reader.cc follow: + +TEST(LogTest, ReadError) { + Write("foo"); + ForceError(); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ((unsigned int)kBlockSize, DroppedBytes()); + ASSERT_EQ("OK", MatchError("read error")); +} + +TEST(LogTest, BadRecordType) { + Write("foo"); + // Type is stored in header[6] + IncrementByte(6, 100); + FixChecksum(0, 3); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ(3U, DroppedBytes()); + ASSERT_EQ("OK", MatchError("unknown record type")); +} + +TEST(LogTest, TruncatedTrailingRecord) { + Write("foo"); + ShrinkSize(4); // Drop all payload as well as a header byte + ASSERT_EQ("EOF", Read()); + ASSERT_EQ((unsigned int)(kHeaderSize - 1), DroppedBytes()); + ASSERT_EQ("OK", MatchError("truncated record at end of file")); +} + +TEST(LogTest, BadLength) { + Write("foo"); + ShrinkSize(1); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ((unsigned int)(kHeaderSize + 2), DroppedBytes()); + ASSERT_EQ("OK", MatchError("bad record length")); +} + +TEST(LogTest, ChecksumMismatch) { + Write("foo"); + IncrementByte(0, 10); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ(10U, DroppedBytes()); + ASSERT_EQ("OK", MatchError("checksum mismatch")); +} + +TEST(LogTest, UnexpectedMiddleType) { + Write("foo"); + SetByte(6, kMiddleType); + FixChecksum(0, 3); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ(3U, DroppedBytes()); + ASSERT_EQ("OK", MatchError("missing start")); +} + +TEST(LogTest, UnexpectedLastType) { + Write("foo"); + SetByte(6, kLastType); + FixChecksum(0, 3); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ(3U, DroppedBytes()); + ASSERT_EQ("OK", MatchError("missing start")); +} + +TEST(LogTest, UnexpectedFullType) { + Write("foo"); + Write("bar"); + SetByte(6, kFirstType); + FixChecksum(0, 3); + ASSERT_EQ("bar", Read()); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ(3U, DroppedBytes()); + ASSERT_EQ("OK", MatchError("partial record without end")); +} + +TEST(LogTest, UnexpectedFirstType) { + Write("foo"); + Write(BigString("bar", 100000)); + SetByte(6, kFirstType); + FixChecksum(0, 3); + ASSERT_EQ(BigString("bar", 100000), Read()); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ(3U, DroppedBytes()); + ASSERT_EQ("OK", MatchError("partial record without end")); +} + +TEST(LogTest, ErrorJoinsRecords) { + // Consider two fragmented records: + // first(R1) last(R1) first(R2) last(R2) + // where the middle two fragments disappear. We do not want + // first(R1),last(R2) to get joined and returned as a valid record. + + // Write records that span two blocks + Write(BigString("foo", kBlockSize)); + Write(BigString("bar", kBlockSize)); + Write("correct"); + + // Wipe the middle block + for (int offset = kBlockSize; offset < 2*kBlockSize; offset++) { + SetByte(offset, 'x'); + } + + ASSERT_EQ("correct", Read()); + ASSERT_EQ("EOF", Read()); + const int dropped = DroppedBytes(); + ASSERT_LE(dropped, 2*kBlockSize + 100); + ASSERT_GE(dropped, 2*kBlockSize); +} + +TEST(LogTest, ReadStart) { + CheckInitialOffsetRecord(0, 0); +} + +TEST(LogTest, ReadSecondOneOff) { + CheckInitialOffsetRecord(1, 1); +} + +TEST(LogTest, ReadSecondTenThousand) { + CheckInitialOffsetRecord(10000, 1); +} + +TEST(LogTest, ReadSecondStart) { + CheckInitialOffsetRecord(10007, 1); +} + +TEST(LogTest, ReadThirdOneOff) { + CheckInitialOffsetRecord(10008, 2); +} + +TEST(LogTest, ReadThirdStart) { + CheckInitialOffsetRecord(20014, 2); +} + +TEST(LogTest, ReadFourthOneOff) { + CheckInitialOffsetRecord(20015, 3); +} + +TEST(LogTest, ReadFourthFirstBlockTrailer) { + CheckInitialOffsetRecord(log::kBlockSize - 4, 3); +} + +TEST(LogTest, ReadFourthMiddleBlock) { + CheckInitialOffsetRecord(log::kBlockSize + 1, 3); +} + +TEST(LogTest, ReadFourthLastBlock) { + CheckInitialOffsetRecord(2 * log::kBlockSize + 1, 3); +} + +TEST(LogTest, ReadFourthStart) { + CheckInitialOffsetRecord( + 2 * (kHeaderSize + 1000) + (2 * log::kBlockSize - 1000) + 3 * kHeaderSize, + 3); +} + +TEST(LogTest, ReadEnd) { + CheckOffsetPastEndReturnsNoRecords(0); +} + +TEST(LogTest, ReadPastEnd) { + CheckOffsetPastEndReturnsNoRecords(5); +} + +} // namespace log +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/db/log_writer.cc b/db/log_writer.cc new file mode 100644 index 00000000..f61abe72 --- /dev/null +++ b/db/log_writer.cc @@ -0,0 +1,103 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/log_writer.h" + +#include +#include "leveldb/env.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { +namespace log { + +Writer::Writer(unique_ptr&& dest) + : dest_(std::move(dest)), + block_offset_(0) { + for (int i = 0; i <= kMaxRecordType; i++) { + char t = static_cast(i); + type_crc_[i] = crc32c::Value(&t, 1); + } +} + +Writer::~Writer() { +} + +Status Writer::AddRecord(const Slice& slice) { + const char* ptr = slice.data(); + size_t left = slice.size(); + + // Fragment the record if necessary and emit it. Note that if slice + // is empty, we still want to iterate once to emit a single + // zero-length record + Status s; + bool begin = true; + do { + const int leftover = kBlockSize - block_offset_; + assert(leftover >= 0); + if (leftover < kHeaderSize) { + // Switch to a new block + if (leftover > 0) { + // Fill the trailer (literal below relies on kHeaderSize being 7) + assert(kHeaderSize == 7); + dest_->Append(Slice("\x00\x00\x00\x00\x00\x00", leftover)); + } + block_offset_ = 0; + } + + // Invariant: we never leave < kHeaderSize bytes in a block. + assert(kBlockSize - block_offset_ - kHeaderSize >= 0); + + const size_t avail = kBlockSize - block_offset_ - kHeaderSize; + const size_t fragment_length = (left < avail) ? left : avail; + + RecordType type; + const bool end = (left == fragment_length); + if (begin && end) { + type = kFullType; + } else if (begin) { + type = kFirstType; + } else if (end) { + type = kLastType; + } else { + type = kMiddleType; + } + + s = EmitPhysicalRecord(type, ptr, fragment_length); + ptr += fragment_length; + left -= fragment_length; + begin = false; + } while (s.ok() && left > 0); + return s; +} + +Status Writer::EmitPhysicalRecord(RecordType t, const char* ptr, size_t n) { + assert(n <= 0xffff); // Must fit in two bytes + assert(block_offset_ + kHeaderSize + n <= kBlockSize); + + // Format the header + char buf[kHeaderSize]; + buf[4] = static_cast(n & 0xff); + buf[5] = static_cast(n >> 8); + buf[6] = static_cast(t); + + // Compute the crc of the record type and the payload. + uint32_t crc = crc32c::Extend(type_crc_[t], ptr, n); + crc = crc32c::Mask(crc); // Adjust for storage + EncodeFixed32(buf, crc); + + // Write the header and the payload + Status s = dest_->Append(Slice(buf, kHeaderSize)); + if (s.ok()) { + s = dest_->Append(Slice(ptr, n)); + if (s.ok()) { + s = dest_->Flush(); + } + } + block_offset_ += kHeaderSize + n; + return s; +} + +} // namespace log +} // namespace leveldb diff --git a/db/log_writer.h b/db/log_writer.h new file mode 100644 index 00000000..a15bcf65 --- /dev/null +++ b/db/log_writer.h @@ -0,0 +1,54 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_LOG_WRITER_H_ +#define STORAGE_LEVELDB_DB_LOG_WRITER_H_ + +#include +#include +#include "db/log_format.h" +#include "leveldb/slice.h" +#include "leveldb/status.h" + +namespace leveldb { + +class WritableFile; + +using std::unique_ptr; + +namespace log { + +class Writer { + public: + // Create a writer that will append data to "*dest". + // "*dest" must be initially empty. + // "*dest" must remain live while this Writer is in use. + explicit Writer(unique_ptr&& dest); + ~Writer(); + + Status AddRecord(const Slice& slice); + + WritableFile* file() { return dest_.get(); } + const WritableFile* file() const { return dest_.get(); } + + private: + unique_ptr dest_; + int block_offset_; // Current offset in block + + // crc32c values for all supported record types. These are + // pre-computed to reduce the overhead of computing the crc of the + // record type stored in the header. + uint32_t type_crc_[kMaxRecordType + 1]; + + Status EmitPhysicalRecord(RecordType type, const char* ptr, size_t length); + + // No copying allowed + Writer(const Writer&); + void operator=(const Writer&); +}; + +} // namespace log +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_LOG_WRITER_H_ diff --git a/db/memtable.cc b/db/memtable.cc new file mode 100644 index 00000000..efe383fe --- /dev/null +++ b/db/memtable.cc @@ -0,0 +1,156 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/memtable.h" +#include "db/dbformat.h" +#include "leveldb/comparator.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "util/coding.h" + +namespace leveldb { + +static Slice GetLengthPrefixedSlice(const char* data) { + uint32_t len; + const char* p = data; + p = GetVarint32Ptr(p, p + 5, &len); // +5: we assume "p" is not corrupted + return Slice(p, len); +} + +MemTable::MemTable(const InternalKeyComparator& cmp, int numlevel) + : comparator_(cmp), + refs_(0), + table_(comparator_, &arena_), + flush_in_progress_(false), + flush_completed_(false), + file_number_(0), + edit_(numlevel), + first_seqno_(0) { +} + +MemTable::~MemTable() { + assert(refs_ == 0); +} + +size_t MemTable::ApproximateMemoryUsage() { return arena_.MemoryUsage(); } + +int MemTable::KeyComparator::operator()(const char* aptr, const char* bptr) + const { + // Internal keys are encoded as length-prefixed strings. + Slice a = GetLengthPrefixedSlice(aptr); + Slice b = GetLengthPrefixedSlice(bptr); + return comparator.Compare(a, b); +} + +// Encode a suitable internal key target for "target" and return it. +// Uses *scratch as scratch space, and the returned pointer will point +// into this scratch space. +static const char* EncodeKey(std::string* scratch, const Slice& target) { + scratch->clear(); + PutVarint32(scratch, target.size()); + scratch->append(target.data(), target.size()); + return scratch->data(); +} + +class MemTableIterator: public Iterator { + public: + explicit MemTableIterator(MemTable::Table* table) : iter_(table) { } + + virtual bool Valid() const { return iter_.Valid(); } + virtual void Seek(const Slice& k) { iter_.Seek(EncodeKey(&tmp_, k)); } + virtual void SeekToFirst() { iter_.SeekToFirst(); } + virtual void SeekToLast() { iter_.SeekToLast(); } + virtual void Next() { iter_.Next(); } + virtual void Prev() { iter_.Prev(); } + virtual Slice key() const { return GetLengthPrefixedSlice(iter_.key()); } + virtual Slice value() const { + Slice key_slice = GetLengthPrefixedSlice(iter_.key()); + return GetLengthPrefixedSlice(key_slice.data() + key_slice.size()); + } + + virtual Status status() const { return Status::OK(); } + + private: + MemTable::Table::Iterator iter_; + std::string tmp_; // For passing to EncodeKey + + // No copying allowed + MemTableIterator(const MemTableIterator&); + void operator=(const MemTableIterator&); +}; + +Iterator* MemTable::NewIterator() { + return new MemTableIterator(&table_); +} + +void MemTable::Add(SequenceNumber s, ValueType type, + const Slice& key, + const Slice& value) { + // Format of an entry is concatenation of: + // key_size : varint32 of internal_key.size() + // key bytes : char[internal_key.size()] + // value_size : varint32 of value.size() + // value bytes : char[value.size()] + size_t key_size = key.size(); + size_t val_size = value.size(); + size_t internal_key_size = key_size + 8; + const size_t encoded_len = + VarintLength(internal_key_size) + internal_key_size + + VarintLength(val_size) + val_size; + char* buf = arena_.Allocate(encoded_len); + char* p = EncodeVarint32(buf, internal_key_size); + memcpy(p, key.data(), key_size); + p += key_size; + EncodeFixed64(p, (s << 8) | type); + p += 8; + p = EncodeVarint32(p, val_size); + memcpy(p, value.data(), val_size); + assert((p + val_size) - buf == (unsigned)encoded_len); + table_.Insert(buf); + + // The first sequence number inserted into the memtable + assert(first_seqno_ == 0 || s > first_seqno_); + if (first_seqno_ == 0) { + first_seqno_ = s; + } +} + +bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) { + Slice memkey = key.memtable_key(); + Table::Iterator iter(&table_); + iter.Seek(memkey.data()); + if (iter.Valid()) { + // entry format is: + // klength varint32 + // userkey char[klength-8] + // tag uint64 + // vlength varint32 + // value char[vlength] + // Check that it belongs to same user key. We do not check the + // sequence number since the Seek() call above should have skipped + // all entries with overly large sequence numbers. + const char* entry = iter.key(); + uint32_t key_length; + const char* key_ptr = GetVarint32Ptr(entry, entry+5, &key_length); + if (comparator_.comparator.user_comparator()->Compare( + Slice(key_ptr, key_length - 8), + key.user_key()) == 0) { + // Correct user key + const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8); + switch (static_cast(tag & 0xff)) { + case kTypeValue: { + Slice v = GetLengthPrefixedSlice(key_ptr + key_length); + value->assign(v.data(), v.size()); + return true; + } + case kTypeDeletion: + *s = Status::NotFound(Slice()); + return true; + } + } + } + return false; +} + +} // namespace leveldb diff --git a/db/memtable.h b/db/memtable.h new file mode 100644 index 00000000..61aa2920 --- /dev/null +++ b/db/memtable.h @@ -0,0 +1,113 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_MEMTABLE_H_ +#define STORAGE_LEVELDB_DB_MEMTABLE_H_ + +#include +#include "leveldb/db.h" +#include "db/dbformat.h" +#include "db/skiplist.h" +#include "db/version_set.h" +#include "util/arena.h" + +namespace leveldb { + +class InternalKeyComparator; +class Mutex; +class MemTableIterator; + +class MemTable { + public: + // MemTables are reference counted. The initial reference count + // is zero and the caller must call Ref() at least once. + explicit MemTable(const InternalKeyComparator& comparator, + int numlevel = 7); + + // Increase reference count. + void Ref() { ++refs_; } + + // Drop reference count. Delete if no more references exist. + void Unref() { + --refs_; + assert(refs_ >= 0); + if (refs_ <= 0) { + delete this; + } + } + + // Returns an estimate of the number of bytes of data in use by this + // data structure. + // + // REQUIRES: external synchronization to prevent simultaneous + // operations on the same MemTable. + size_t ApproximateMemoryUsage(); + + // Return an iterator that yields the contents of the memtable. + // + // The caller must ensure that the underlying MemTable remains live + // while the returned iterator is live. The keys returned by this + // iterator are internal keys encoded by AppendInternalKey in the + // db/dbformat.{h,cc} module. + Iterator* NewIterator(); + + // Add an entry into memtable that maps key to value at the + // specified sequence number and with the specified type. + // Typically value will be empty if type==kTypeDeletion. + void Add(SequenceNumber seq, ValueType type, + const Slice& key, + const Slice& value); + + // If memtable contains a value for key, store it in *value and return true. + // If memtable contains a deletion for key, store a NotFound() error + // in *status and return true. + // Else, return false. + bool Get(const LookupKey& key, std::string* value, Status* s); + + // Returns the edits area that is needed for flushing the memtable + VersionEdit* GetEdits() { return &edit_; } + + // Returns the sequence number of the first element that was inserted + // into the memtable + SequenceNumber GetFirstSequenceNumber() { return first_seqno_; } + + private: + ~MemTable(); // Private since only Unref() should be used to delete it + + struct KeyComparator { + const InternalKeyComparator comparator; + explicit KeyComparator(const InternalKeyComparator& c) : comparator(c) { } + int operator()(const char* a, const char* b) const; + }; + friend class MemTableIterator; + friend class MemTableBackwardIterator; + friend class MemTableList; + + typedef SkipList Table; + + KeyComparator comparator_; + int refs_; + Arena arena_; + Table table_; + + // These are used to manage memtable flushes to storage + bool flush_in_progress_; // started the flush + bool flush_completed_; // finished the flush + uint64_t file_number_; // filled up after flush is complete + + // The udpates to be applied to the transaction log when this + // memtable is flushed to storage. + VersionEdit edit_; + + // The sequence number of the kv that was inserted first + SequenceNumber first_seqno_; + + // No copying allowed + MemTable(const MemTable&); + void operator=(const MemTable&); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_MEMTABLE_H_ diff --git a/db/memtablelist.cc b/db/memtablelist.cc new file mode 100644 index 00000000..c1ccda1a --- /dev/null +++ b/db/memtablelist.cc @@ -0,0 +1,194 @@ +// Copyright (c) 2012 Facebook. + + +#include "db/memtablelist.h" + +#include +#include "leveldb/db.h" +#include "db/memtable.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "util/coding.h" + +namespace leveldb { + +class InternalKeyComparator; +class Mutex; +class MemTableListIterator; +class VersionSet; + +using std::list; + +// Increase reference count on all underling memtables +void MemTableList::RefAll() { + for (list::iterator it = memlist_.begin(); + it != memlist_.end() ; ++it) { + (*it)->Ref(); + } +} + +// Drop reference count on all underling memtables +void MemTableList::UnrefAll() { + for (list::iterator it = memlist_.begin(); + it != memlist_.end() ; ++it) { + (*it)->Unref(); + } +} + +// Returns the total number of memtables in the list +int MemTableList::size() { + assert(num_flush_not_started_ <= size_); + return size_; +} + +// Returns true if there is at least one memtable on which flush has +// not yet started. +bool MemTableList::IsFlushPending() { + if (num_flush_not_started_ > 0) { + assert(imm_flush_needed.NoBarrier_Load() != nullptr); + return true; + } + return false; +} + +// Returns the earliest memtable that needs to be flushed. +// Returns null, if no such memtable exist. +MemTable* MemTableList::PickMemtableToFlush() { + for (list::reverse_iterator it = memlist_.rbegin(); + it != memlist_.rend(); it++) { + MemTable* m = *it; + if (!m->flush_in_progress_) { + assert(!m->flush_completed_); + num_flush_not_started_--; + if (num_flush_not_started_ == 0) { + imm_flush_needed.Release_Store(nullptr); + } + m->flush_in_progress_ = true; // flushing will start very soon + return m; + } + } + return nullptr; +} + +// Record a successful flush in the manifest file +Status MemTableList::InstallMemtableFlushResults(MemTable* m, + VersionSet* vset, Status flushStatus, + port::Mutex* mu, Logger* info_log, + uint64_t file_number, + std::set& pending_outputs) { + mu->AssertHeld(); + assert(m->flush_in_progress_); + assert(m->file_number_ == 0); + + // If the flush was not successful, then just reset state. + // Maybe a suceeding attempt to flush will be successful. + if (!flushStatus.ok()) { + m->flush_in_progress_ = false; + m->flush_completed_ = false; + m->edit_.Clear(); + num_flush_not_started_++; + imm_flush_needed.Release_Store((void *)1); + pending_outputs.erase(file_number); + return flushStatus; + } + + // flush was sucessful + m->flush_completed_ = true; + m->file_number_ = file_number; + + // if some other thread is already commiting, then return + Status s; + if (commit_in_progress_) { + return s; + } + + // Only a single thread can be executing this piece of code + commit_in_progress_ = true; + + // scan all memtables from the earliest, and commit those + // (in that order) that have finished flushing. + while (!memlist_.empty()) { + m = memlist_.back(); // get the last element + if (!m->flush_completed_) { + break; + } + Log(info_log, + "Level-0 commit table #%llu: started", + (unsigned long long)m->file_number_); + + // this can release and reacquire the mutex. + s = vset->LogAndApply(&m->edit_, mu); + + if (s.ok()) { // commit new state + Log(info_log, "Level-0 commit table #%llu: done", + (unsigned long long)m->file_number_); + memlist_.remove(m); + assert(m->file_number_ > 0); + + // pending_outputs can be cleared only after the newly created file + // has been written to a committed version so that other concurrently + // executing compaction threads do not mistakenly assume that this + // file is not live. + pending_outputs.erase(m->file_number_); + m->Unref(); + size_--; + } else { + //commit failed. setup state so that we can flush again. + Log(info_log, "Level-0 commit table #%llu: failed", + (unsigned long long)m->file_number_); + m->flush_completed_ = false; + m->flush_in_progress_ = false; + m->edit_.Clear(); + num_flush_not_started_++; + pending_outputs.erase(m->file_number_); + m->file_number_ = 0; + imm_flush_needed.Release_Store((void *)1); + s = Status::IOError("Unable to commit flushed memtable"); + break; + } + } + commit_in_progress_ = false; + return s; +} + +// New memtables are inserted at the front of the list. +void MemTableList::Add(MemTable* m) { + assert(size_ >= num_flush_not_started_); + size_++; + memlist_.push_front(m); + num_flush_not_started_++; + if (num_flush_not_started_ == 1) { + imm_flush_needed.Release_Store((void *)1); + } +} + +// Returns an estimate of the number of bytes of data in use. +size_t MemTableList::ApproximateMemoryUsage() { + size_t size = 0; + for (list::iterator it = memlist_.begin(); + it != memlist_.end(); ++it) { + size += (*it)->ApproximateMemoryUsage(); + } + return size; +} + +// Search all the memtables starting from the most recent one. +// Return the most recent value found, if any. +bool MemTableList::Get(const LookupKey& key, std::string* value, Status* s) { + for (list::iterator it = memlist_.begin(); + it != memlist_.end(); ++it) { + if ((*it)->Get(key, value, s)) { + return true; + } + } + return false; +} + +void MemTableList::GetMemTables(std::vector* output) { + for (list::iterator it = memlist_.begin(); + it != memlist_.end(); ++it) { + output->push_back(*it); + } +} + +} // namespace leveldb diff --git a/db/memtablelist.h b/db/memtablelist.h new file mode 100644 index 00000000..9ab91a67 --- /dev/null +++ b/db/memtablelist.h @@ -0,0 +1,97 @@ +// Copyright (c) 2012 Facebook. + +#ifndef STORAGE_LEVELDB_DB_MEMTABLELIST_H_ +#define STORAGE_LEVELDB_DB_MEMTABLELIST_H_ + +#include +#include +#include "leveldb/db.h" +#include "db/dbformat.h" +#include "db/skiplist.h" +#include "util/arena.h" +#include "memtable.h" + +namespace leveldb { + +class InternalKeyComparator; +class Mutex; +class MemTableListIterator; + +// +// This class stores refeernces to all the immutable memtables. +// The memtables are flushed to L0 as soon as possible and in +// any order. If there are more than one immutable memtable, their +// flushes can occur concurrently. However, they are 'committed' +// to the manifest in FIFO order to maintain correctness and +// recoverability from a crash. +// +class MemTableList { + public: + // A list of memtables. + MemTableList() : size_(0), num_flush_not_started_(0), + commit_in_progress_(false) { + imm_flush_needed.Release_Store(nullptr); + } + ~MemTableList() {}; + + // so that backgrund threads can detect non-nullptr pointer to + // determine whether this is anything more to start flushing. + port::AtomicPointer imm_flush_needed; + + // Increase reference count on all underling memtables + void RefAll(); + + // Drop reference count on all underling memtables + void UnrefAll(); + + // Returns the total number of memtables in the list + int size(); + + // Returns true if there is at least one memtable on which flush has + // not yet started. + bool IsFlushPending(); + + // Returns the earliest memtable that needs to be flushed. + // Returns null, if no such memtable exist. + MemTable* PickMemtableToFlush(); + + // Commit a successful flush in the manifest file + Status InstallMemtableFlushResults(MemTable* m, + VersionSet* vset, Status flushStatus, + port::Mutex* mu, Logger* info_log, + uint64_t file_number, + std::set& pending_outputs); + + // New memtables are inserted at the front of the list. + // Takes ownership of the referenced held on *m by the caller of Add(). + void Add(MemTable* m); + + // Returns an estimate of the number of bytes of data in use. + size_t ApproximateMemoryUsage(); + + // Search all the memtables starting from the most recent one. + // Return the most recent value found, if any. + bool Get(const LookupKey& key, std::string* value, Status* s); + + // Returns the list of underlying memtables. + void GetMemTables(std::vector* list); + + // Copying allowed + // MemTableList(const MemTableList&); + // void operator=(const MemTableList&); + + private: + std::list memlist_; + int size_; + + // the number of elements that still need flushing + int num_flush_not_started_; + + // committing in progress + bool commit_in_progress_; + +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_MEMTABLELIST_H_ diff --git a/db/repair.cc b/db/repair.cc new file mode 100644 index 00000000..b991f833 --- /dev/null +++ b/db/repair.cc @@ -0,0 +1,377 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// We recover the contents of the descriptor from the other files we find. +// (1) Any log files are first converted to tables +// (2) We scan every table to compute +// (a) smallest/largest for the table +// (b) largest sequence number in the table +// (3) We generate descriptor contents: +// - log number is set to zero +// - next-file-number is set to 1 + largest file number we found +// - last-sequence-number is set to largest sequence# found across +// all tables (see 2c) +// - compaction pointers are cleared +// - every table file is added at level 0 +// +// Possible optimization 1: +// (a) Compute total size and use to pick appropriate max-level M +// (b) Sort tables by largest sequence# in the table +// (c) For each table: if it overlaps earlier table, place in level-0, +// else place in level-M. +// Possible optimization 2: +// Store per-table metadata (smallest, largest, largest-seq#, ...) +// in the table's meta section to speed up ScanTable. + +#include "db/builder.h" +#include "db/db_impl.h" +#include "db/dbformat.h" +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "db/memtable.h" +#include "db/table_cache.h" +#include "db/version_edit.h" +#include "db/write_batch_internal.h" +#include "leveldb/comparator.h" +#include "leveldb/db.h" +#include "leveldb/env.h" + +namespace leveldb { + +namespace { + +class Repairer { + public: + Repairer(const std::string& dbname, const Options& options) + : dbname_(dbname), + env_(options.env), + icmp_(options.comparator), + ipolicy_(options.filter_policy), + options_(SanitizeOptions(dbname, &icmp_, &ipolicy_, options)), + next_file_number_(1) { + // TableCache can be small since we expect each table to be opened once. + table_cache_ = new TableCache(dbname_, &options_, 10); + edit_ = new VersionEdit(options.num_levels); + } + + ~Repairer() { + delete table_cache_; + delete edit_; + } + + Status Run() { + Status status = FindFiles(); + if (status.ok()) { + ConvertLogFilesToTables(); + ExtractMetaData(); + status = WriteDescriptor(); + } + if (status.ok()) { + unsigned long long bytes = 0; + for (size_t i = 0; i < tables_.size(); i++) { + bytes += tables_[i].meta.file_size; + } + Log(options_.info_log, + "**** Repaired leveldb %s; " + "recovered %d files; %llu bytes. " + "Some data may have been lost. " + "****", + dbname_.c_str(), + static_cast(tables_.size()), + bytes); + } + return status; + } + + private: + struct TableInfo { + FileMetaData meta; + SequenceNumber max_sequence; + }; + + std::string const dbname_; + Env* const env_; + InternalKeyComparator const icmp_; + InternalFilterPolicy const ipolicy_; + Options const options_; + bool owns_cache_; + TableCache* table_cache_; + VersionEdit* edit_; + + std::vector manifests_; + std::vector table_numbers_; + std::vector logs_; + std::vector tables_; + uint64_t next_file_number_; + + Status FindFiles() { + std::vector filenames; + Status status = env_->GetChildren(dbname_, &filenames); + if (!status.ok()) { + return status; + } + if (filenames.empty()) { + return Status::IOError(dbname_, "repair found no files"); + } + + uint64_t number; + FileType type; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type)) { + if (type == kDescriptorFile) { + manifests_.push_back(filenames[i]); + } else { + if (number + 1 > next_file_number_) { + next_file_number_ = number + 1; + } + if (type == kLogFile) { + logs_.push_back(number); + } else if (type == kTableFile) { + table_numbers_.push_back(number); + } else { + // Ignore other files + } + } + } + } + return status; + } + + void ConvertLogFilesToTables() { + for (size_t i = 0; i < logs_.size(); i++) { + std::string logname = LogFileName(dbname_, logs_[i]); + Status status = ConvertLogToTable(logs_[i]); + if (!status.ok()) { + Log(options_.info_log, "Log #%llu: ignoring conversion error: %s", + (unsigned long long) logs_[i], + status.ToString().c_str()); + } + ArchiveFile(logname); + } + } + + Status ConvertLogToTable(uint64_t log) { + struct LogReporter : public log::Reader::Reporter { + Env* env; + std::shared_ptr info_log; + uint64_t lognum; + virtual void Corruption(size_t bytes, const Status& s) { + // We print error messages for corruption, but continue repairing. + Log(info_log, "Log #%llu: dropping %d bytes; %s", + (unsigned long long) lognum, + static_cast(bytes), + s.ToString().c_str()); + } + }; + + // Open the log file + std::string logname = LogFileName(dbname_, log); + unique_ptr lfile; + Status status = env_->NewSequentialFile(logname, &lfile); + if (!status.ok()) { + return status; + } + + // Create the log reader. + LogReporter reporter; + reporter.env = env_; + reporter.info_log = options_.info_log; + reporter.lognum = log; + // We intentially make log::Reader do checksumming so that + // corruptions cause entire commits to be skipped instead of + // propagating bad information (like overly large sequence + // numbers). + log::Reader reader(std::move(lfile), &reporter, false/*do not checksum*/, + 0/*initial_offset*/); + + // Read all the records and add to a memtable + std::string scratch; + Slice record; + WriteBatch batch; + MemTable* mem = new MemTable(icmp_, options_.num_levels); + mem->Ref(); + int counter = 0; + while (reader.ReadRecord(&record, &scratch)) { + if (record.size() < 12) { + reporter.Corruption( + record.size(), Status::Corruption("log record too small")); + continue; + } + WriteBatchInternal::SetContents(&batch, record); + status = WriteBatchInternal::InsertInto(&batch, mem); + if (status.ok()) { + counter += WriteBatchInternal::Count(&batch); + } else { + Log(options_.info_log, "Log #%llu: ignoring %s", + (unsigned long long) log, + status.ToString().c_str()); + status = Status::OK(); // Keep going with rest of file + } + } + + // Do not record a version edit for this conversion to a Table + // since ExtractMetaData() will also generate edits. + FileMetaData meta; + meta.number = next_file_number_++; + Iterator* iter = mem->NewIterator(); + status = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta, + icmp_.user_comparator(), 0, 0); + delete iter; + mem->Unref(); + mem = nullptr; + if (status.ok()) { + if (meta.file_size > 0) { + table_numbers_.push_back(meta.number); + } + } + Log(options_.info_log, "Log #%llu: %d ops saved to Table #%llu %s", + (unsigned long long) log, + counter, + (unsigned long long) meta.number, + status.ToString().c_str()); + return status; + } + + void ExtractMetaData() { + std::vector kept; + for (size_t i = 0; i < table_numbers_.size(); i++) { + TableInfo t; + t.meta.number = table_numbers_[i]; + Status status = ScanTable(&t); + if (!status.ok()) { + std::string fname = TableFileName(dbname_, table_numbers_[i]); + Log(options_.info_log, "Table #%llu: ignoring %s", + (unsigned long long) table_numbers_[i], + status.ToString().c_str()); + ArchiveFile(fname); + } else { + tables_.push_back(t); + } + } + } + + Status ScanTable(TableInfo* t) { + std::string fname = TableFileName(dbname_, t->meta.number); + int counter = 0; + Status status = env_->GetFileSize(fname, &t->meta.file_size); + if (status.ok()) { + Iterator* iter = table_cache_->NewIterator( + ReadOptions(), t->meta.number, t->meta.file_size); + bool empty = true; + ParsedInternalKey parsed; + t->max_sequence = 0; + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + Slice key = iter->key(); + if (!ParseInternalKey(key, &parsed)) { + Log(options_.info_log, "Table #%llu: unparsable key %s", + (unsigned long long) t->meta.number, + EscapeString(key).c_str()); + continue; + } + + counter++; + if (empty) { + empty = false; + t->meta.smallest.DecodeFrom(key); + } + t->meta.largest.DecodeFrom(key); + if (parsed.sequence > t->max_sequence) { + t->max_sequence = parsed.sequence; + } + } + if (!iter->status().ok()) { + status = iter->status(); + } + delete iter; + } + Log(options_.info_log, "Table #%llu: %d entries %s", + (unsigned long long) t->meta.number, + counter, + status.ToString().c_str()); + return status; + } + + Status WriteDescriptor() { + std::string tmp = TempFileName(dbname_, 1); + unique_ptr file; + Status status = env_->NewWritableFile(tmp, &file); + if (!status.ok()) { + return status; + } + + SequenceNumber max_sequence = 0; + for (size_t i = 0; i < tables_.size(); i++) { + if (max_sequence < tables_[i].max_sequence) { + max_sequence = tables_[i].max_sequence; + } + } + + edit_->SetComparatorName(icmp_.user_comparator()->Name()); + edit_->SetLogNumber(0); + edit_->SetNextFile(next_file_number_); + edit_->SetLastSequence(max_sequence); + + for (size_t i = 0; i < tables_.size(); i++) { + // TODO(opt): separate out into multiple levels + const TableInfo& t = tables_[i]; + edit_->AddFile(0, t.meta.number, t.meta.file_size, + t.meta.smallest, t.meta.largest); + } + + //fprintf(stderr, "NewDescriptor:\n%s\n", edit_.DebugString().c_str()); + { + log::Writer log(std::move(file)); + std::string record; + edit_->EncodeTo(&record); + status = log.AddRecord(record); + } + + if (!status.ok()) { + env_->DeleteFile(tmp); + } else { + // Discard older manifests + for (size_t i = 0; i < manifests_.size(); i++) { + ArchiveFile(dbname_ + "/" + manifests_[i]); + } + + // Install new manifest + status = env_->RenameFile(tmp, DescriptorFileName(dbname_, 1)); + if (status.ok()) { + status = SetCurrentFile(env_, dbname_, 1); + } else { + env_->DeleteFile(tmp); + } + } + return status; + } + + void ArchiveFile(const std::string& fname) { + // Move into another directory. E.g., for + // dir/foo + // rename to + // dir/lost/foo + const char* slash = strrchr(fname.c_str(), '/'); + std::string new_dir; + if (slash != nullptr) { + new_dir.assign(fname.data(), slash - fname.data()); + } + new_dir.append("/lost"); + env_->CreateDir(new_dir); // Ignore error + std::string new_file = new_dir; + new_file.append("/"); + new_file.append((slash == nullptr) ? fname.c_str() : slash + 1); + Status s = env_->RenameFile(fname, new_file); + Log(options_.info_log, "Archiving %s: %s\n", + fname.c_str(), s.ToString().c_str()); + } +}; +} // namespace + +Status RepairDB(const std::string& dbname, const Options& options) { + Repairer repairer(dbname, options); + return repairer.Run(); +} + +} // namespace leveldb diff --git a/db/skiplist.h b/db/skiplist.h new file mode 100644 index 00000000..1c7b4dd7 --- /dev/null +++ b/db/skiplist.h @@ -0,0 +1,398 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Thread safety +// ------------- +// +// Writes require external synchronization, most likely a mutex. +// Reads require a guarantee that the SkipList will not be destroyed +// while the read is in progress. Apart from that, reads progress +// without any internal locking or synchronization. +// +// Invariants: +// +// (1) Allocated nodes are never deleted until the SkipList is +// destroyed. This is trivially guaranteed by the code since we +// never delete any skip list nodes. +// +// (2) The contents of a Node except for the next/prev pointers are +// immutable after the Node has been linked into the SkipList. +// Only Insert() modifies the list, and it is careful to initialize +// a node and use release-stores to publish the nodes in one or +// more lists. +// +// ... prev vs. next pointer ordering ... +// + +#ifndef STORAGE_LEVELDB_DB_SKIPLIST_H_ +#define STORAGE_LEVELDB_DB_SKIPLIST_H_ + +#include +#include +#include "port/port.h" +#include "util/arena.h" +#include "util/random.h" + +namespace leveldb { + +class Arena; + +template +class SkipList { + private: + struct Node; + + public: + // Create a new SkipList object that will use "cmp" for comparing keys, + // and will allocate memory using "*arena". Objects allocated in the arena + // must remain allocated for the lifetime of the skiplist object. + explicit SkipList(Comparator cmp, Arena* arena); + + // Insert key into the list. + // REQUIRES: nothing that compares equal to key is currently in the list. + void Insert(const Key& key); + + // Returns true iff an entry that compares equal to key is in the list. + bool Contains(const Key& key) const; + + // Iteration over the contents of a skip list + class Iterator { + public: + // Initialize an iterator over the specified list. + // The returned iterator is not valid. + explicit Iterator(const SkipList* list); + + // Returns true iff the iterator is positioned at a valid node. + bool Valid() const; + + // Returns the key at the current position. + // REQUIRES: Valid() + const Key& key() const; + + // Advances to the next position. + // REQUIRES: Valid() + void Next(); + + // Advances to the previous position. + // REQUIRES: Valid() + void Prev(); + + // Advance to the first entry with a key >= target + void Seek(const Key& target); + + // Position at the first entry in list. + // Final state of iterator is Valid() iff list is not empty. + void SeekToFirst(); + + // Position at the last entry in list. + // Final state of iterator is Valid() iff list is not empty. + void SeekToLast(); + + private: + const SkipList* list_; + Node* node_; + // Intentionally copyable + }; + + private: + enum { kMaxHeight = 12 }; + + // Immutable after construction + Comparator const compare_; + Arena* const arena_; // Arena used for allocations of nodes + + Node* const head_; + + // Modified only by Insert(). Read racily by readers, but stale + // values are ok. + port::AtomicPointer max_height_; // Height of the entire list + + // Used for optimizing sequential insert patterns + Node* prev_[kMaxHeight]; + + inline int GetMaxHeight() const { + return static_cast( + reinterpret_cast(max_height_.NoBarrier_Load())); + } + + // Read/written only by Insert(). + Random rnd_; + + Node* NewNode(const Key& key, int height); + int RandomHeight(); + bool Equal(const Key& a, const Key& b) const { return (compare_(a, b) == 0); } + + // Return true if key is greater than the data stored in "n" + bool KeyIsAfterNode(const Key& key, Node* n) const; + + // Return the earliest node that comes at or after key. + // Return nullptr if there is no such node. + // + // If prev is non-nullptr, fills prev[level] with pointer to previous + // node at "level" for every level in [0..max_height_-1]. + Node* FindGreaterOrEqual(const Key& key, Node** prev) const; + + // Return the latest node with a key < key. + // Return head_ if there is no such node. + Node* FindLessThan(const Key& key) const; + + // Return the last node in the list. + // Return head_ if list is empty. + Node* FindLast() const; + + // No copying allowed + SkipList(const SkipList&); + void operator=(const SkipList&); +}; + +// Implementation details follow +template +struct SkipList::Node { + explicit Node(const Key& k) : key(k) { } + + Key const key; + + // Accessors/mutators for links. Wrapped in methods so we can + // add the appropriate barriers as necessary. + Node* Next(int n) { + assert(n >= 0); + // Use an 'acquire load' so that we observe a fully initialized + // version of the returned Node. + return reinterpret_cast(next_[n].Acquire_Load()); + } + void SetNext(int n, Node* x) { + assert(n >= 0); + // Use a 'release store' so that anybody who reads through this + // pointer observes a fully initialized version of the inserted node. + next_[n].Release_Store(x); + } + + // No-barrier variants that can be safely used in a few locations. + Node* NoBarrier_Next(int n) { + assert(n >= 0); + return reinterpret_cast(next_[n].NoBarrier_Load()); + } + void NoBarrier_SetNext(int n, Node* x) { + assert(n >= 0); + next_[n].NoBarrier_Store(x); + } + + private: + // Array of length equal to the node height. next_[0] is lowest level link. + port::AtomicPointer next_[1]; +}; + +template +typename SkipList::Node* +SkipList::NewNode(const Key& key, int height) { + char* mem = arena_->AllocateAligned( + sizeof(Node) + sizeof(port::AtomicPointer) * (height - 1)); + return new (mem) Node(key); +} + +template +inline SkipList::Iterator::Iterator(const SkipList* list) { + list_ = list; + node_ = nullptr; +} + +template +inline bool SkipList::Iterator::Valid() const { + return node_ != nullptr; +} + +template +inline const Key& SkipList::Iterator::key() const { + assert(Valid()); + return node_->key; +} + +template +inline void SkipList::Iterator::Next() { + assert(Valid()); + node_ = node_->Next(0); +} + +template +inline void SkipList::Iterator::Prev() { + // Instead of using explicit "prev" links, we just search for the + // last node that falls before key. + assert(Valid()); + node_ = list_->FindLessThan(node_->key); + if (node_ == list_->head_) { + node_ = nullptr; + } +} + +template +inline void SkipList::Iterator::Seek(const Key& target) { + node_ = list_->FindGreaterOrEqual(target, nullptr); +} + +template +inline void SkipList::Iterator::SeekToFirst() { + node_ = list_->head_->Next(0); +} + +template +inline void SkipList::Iterator::SeekToLast() { + node_ = list_->FindLast(); + if (node_ == list_->head_) { + node_ = nullptr; + } +} + +template +int SkipList::RandomHeight() { + // Increase height with probability 1 in kBranching + static const unsigned int kBranching = 4; + int height = 1; + while (height < kMaxHeight && ((rnd_.Next() % kBranching) == 0)) { + height++; + } + assert(height > 0); + assert(height <= kMaxHeight); + return height; +} + +template +bool SkipList::KeyIsAfterNode(const Key& key, Node* n) const { + // nullptr n is considered infinite + return (n != nullptr) && (compare_(n->key, key) < 0); +} + +template +typename SkipList::Node* SkipList::FindGreaterOrEqual(const Key& key, Node** prev) + const { + // Use prev as an optimization hint and fallback to slow path + if (prev && !KeyIsAfterNode(key, prev[0]->Next(0))) { + Node* x = prev[0]; + Node* next = x->Next(0); + if ((x == head_) || KeyIsAfterNode(key, x)) { + return next; + } + } + // Normal lookup + Node* x = head_; + int level = GetMaxHeight() - 1; + while (true) { + Node* next = x->Next(level); + if (KeyIsAfterNode(key, next)) { + // Keep searching in this list + x = next; + } else { + if (prev != nullptr) prev[level] = x; + if (level == 0) { + return next; + } else { + // Switch to next list + level--; + } + } + } +} + +template +typename SkipList::Node* +SkipList::FindLessThan(const Key& key) const { + Node* x = head_; + int level = GetMaxHeight() - 1; + while (true) { + assert(x == head_ || compare_(x->key, key) < 0); + Node* next = x->Next(level); + if (next == nullptr || compare_(next->key, key) >= 0) { + if (level == 0) { + return x; + } else { + // Switch to next list + level--; + } + } else { + x = next; + } + } +} + +template +typename SkipList::Node* SkipList::FindLast() + const { + Node* x = head_; + int level = GetMaxHeight() - 1; + while (true) { + Node* next = x->Next(level); + if (next == nullptr) { + if (level == 0) { + return x; + } else { + // Switch to next list + level--; + } + } else { + x = next; + } + } +} + +template +SkipList::SkipList(Comparator cmp, Arena* arena) + : compare_(cmp), + arena_(arena), + head_(NewNode(0 /* any key will do */, kMaxHeight)), + max_height_(reinterpret_cast(1)), + rnd_(0xdeadbeef) { + for (int i = 0; i < kMaxHeight; i++) { + head_->SetNext(i, nullptr); + prev_[i] = head_; + } +} + +template +void SkipList::Insert(const Key& key) { + // TODO(opt): We can use a barrier-free variant of FindGreaterOrEqual() + // here since Insert() is externally synchronized. + Node* x = FindGreaterOrEqual(key, prev_); + + // Our data structure does not allow duplicate insertion + assert(x == nullptr || !Equal(key, x->key)); + + int height = RandomHeight(); + if (height > GetMaxHeight()) { + for (int i = GetMaxHeight(); i < height; i++) { + prev_[i] = head_; + } + //fprintf(stderr, "Change height from %d to %d\n", max_height_, height); + + // It is ok to mutate max_height_ without any synchronization + // with concurrent readers. A concurrent reader that observes + // the new value of max_height_ will see either the old value of + // new level pointers from head_ (nullptr), or a new value set in + // the loop below. In the former case the reader will + // immediately drop to the next level since nullptr sorts after all + // keys. In the latter case the reader will use the new node. + max_height_.NoBarrier_Store(reinterpret_cast(height)); + } + + x = NewNode(key, height); + for (int i = 0; i < height; i++) { + // NoBarrier_SetNext() suffices since we will add a barrier when + // we publish a pointer to "x" in prev[i]. + x->NoBarrier_SetNext(i, prev_[i]->NoBarrier_Next(i)); + prev_[i]->SetNext(i, x); + } + prev_[0] = x; +} + +template +bool SkipList::Contains(const Key& key) const { + Node* x = FindGreaterOrEqual(key, nullptr); + if (x != nullptr && Equal(key, x->key)) { + return true; + } else { + return false; + } +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_SKIPLIST_H_ diff --git a/db/skiplist_test.cc b/db/skiplist_test.cc new file mode 100644 index 00000000..fa8a21a3 --- /dev/null +++ b/db/skiplist_test.cc @@ -0,0 +1,378 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/skiplist.h" +#include +#include "leveldb/env.h" +#include "util/arena.h" +#include "util/hash.h" +#include "util/random.h" +#include "util/testharness.h" + +namespace leveldb { + +typedef uint64_t Key; + +struct TestComparator { + int operator()(const Key& a, const Key& b) const { + if (a < b) { + return -1; + } else if (a > b) { + return +1; + } else { + return 0; + } + } +}; + +class SkipTest { }; + +TEST(SkipTest, Empty) { + Arena arena; + TestComparator cmp; + SkipList list(cmp, &arena); + ASSERT_TRUE(!list.Contains(10)); + + SkipList::Iterator iter(&list); + ASSERT_TRUE(!iter.Valid()); + iter.SeekToFirst(); + ASSERT_TRUE(!iter.Valid()); + iter.Seek(100); + ASSERT_TRUE(!iter.Valid()); + iter.SeekToLast(); + ASSERT_TRUE(!iter.Valid()); +} + +TEST(SkipTest, InsertAndLookup) { + const int N = 2000; + const int R = 5000; + Random rnd(1000); + std::set keys; + Arena arena; + TestComparator cmp; + SkipList list(cmp, &arena); + for (int i = 0; i < N; i++) { + Key key = rnd.Next() % R; + if (keys.insert(key).second) { + list.Insert(key); + } + } + + for (int i = 0; i < R; i++) { + if (list.Contains(i)) { + ASSERT_EQ(keys.count(i), 1U); + } else { + ASSERT_EQ(keys.count(i), 0U); + } + } + + // Simple iterator tests + { + SkipList::Iterator iter(&list); + ASSERT_TRUE(!iter.Valid()); + + iter.Seek(0); + ASSERT_TRUE(iter.Valid()); + ASSERT_EQ(*(keys.begin()), iter.key()); + + iter.SeekToFirst(); + ASSERT_TRUE(iter.Valid()); + ASSERT_EQ(*(keys.begin()), iter.key()); + + iter.SeekToLast(); + ASSERT_TRUE(iter.Valid()); + ASSERT_EQ(*(keys.rbegin()), iter.key()); + } + + // Forward iteration test + for (int i = 0; i < R; i++) { + SkipList::Iterator iter(&list); + iter.Seek(i); + + // Compare against model iterator + std::set::iterator model_iter = keys.lower_bound(i); + for (int j = 0; j < 3; j++) { + if (model_iter == keys.end()) { + ASSERT_TRUE(!iter.Valid()); + break; + } else { + ASSERT_TRUE(iter.Valid()); + ASSERT_EQ(*model_iter, iter.key()); + ++model_iter; + iter.Next(); + } + } + } + + // Backward iteration test + { + SkipList::Iterator iter(&list); + iter.SeekToLast(); + + // Compare against model iterator + for (std::set::reverse_iterator model_iter = keys.rbegin(); + model_iter != keys.rend(); + ++model_iter) { + ASSERT_TRUE(iter.Valid()); + ASSERT_EQ(*model_iter, iter.key()); + iter.Prev(); + } + ASSERT_TRUE(!iter.Valid()); + } +} + +// We want to make sure that with a single writer and multiple +// concurrent readers (with no synchronization other than when a +// reader's iterator is created), the reader always observes all the +// data that was present in the skip list when the iterator was +// constructor. Because insertions are happening concurrently, we may +// also observe new values that were inserted since the iterator was +// constructed, but we should never miss any values that were present +// at iterator construction time. +// +// We generate multi-part keys: +// +// where: +// key is in range [0..K-1] +// gen is a generation number for key +// hash is hash(key,gen) +// +// The insertion code picks a random key, sets gen to be 1 + the last +// generation number inserted for that key, and sets hash to Hash(key,gen). +// +// At the beginning of a read, we snapshot the last inserted +// generation number for each key. We then iterate, including random +// calls to Next() and Seek(). For every key we encounter, we +// check that it is either expected given the initial snapshot or has +// been concurrently added since the iterator started. +class ConcurrentTest { + private: + static const uint32_t K = 4; + + static uint64_t key(Key key) { return (key >> 40); } + static uint64_t gen(Key key) { return (key >> 8) & 0xffffffffu; } + static uint64_t hash(Key key) { return key & 0xff; } + + static uint64_t HashNumbers(uint64_t k, uint64_t g) { + uint64_t data[2] = { k, g }; + return Hash(reinterpret_cast(data), sizeof(data), 0); + } + + static Key MakeKey(uint64_t k, uint64_t g) { + assert(sizeof(Key) == sizeof(uint64_t)); + assert(k <= K); // We sometimes pass K to seek to the end of the skiplist + assert(g <= 0xffffffffu); + return ((k << 40) | (g << 8) | (HashNumbers(k, g) & 0xff)); + } + + static bool IsValidKey(Key k) { + return hash(k) == (HashNumbers(key(k), gen(k)) & 0xff); + } + + static Key RandomTarget(Random* rnd) { + switch (rnd->Next() % 10) { + case 0: + // Seek to beginning + return MakeKey(0, 0); + case 1: + // Seek to end + return MakeKey(K, 0); + default: + // Seek to middle + return MakeKey(rnd->Next() % K, 0); + } + } + + // Per-key generation + struct State { + port::AtomicPointer generation[K]; + void Set(int k, intptr_t v) { + generation[k].Release_Store(reinterpret_cast(v)); + } + intptr_t Get(int k) { + return reinterpret_cast(generation[k].Acquire_Load()); + } + + State() { + for (unsigned int k = 0; k < K; k++) { + Set(k, 0); + } + } + }; + + // Current state of the test + State current_; + + Arena arena_; + + // SkipList is not protected by mu_. We just use a single writer + // thread to modify it. + SkipList list_; + + public: + ConcurrentTest() : list_(TestComparator(), &arena_) { } + + // REQUIRES: External synchronization + void WriteStep(Random* rnd) { + const uint32_t k = rnd->Next() % K; + const intptr_t g = current_.Get(k) + 1; + const Key key = MakeKey(k, g); + list_.Insert(key); + current_.Set(k, g); + } + + void ReadStep(Random* rnd) { + // Remember the initial committed state of the skiplist. + State initial_state; + for (unsigned int k = 0; k < K; k++) { + initial_state.Set(k, current_.Get(k)); + } + + Key pos = RandomTarget(rnd); + SkipList::Iterator iter(&list_); + iter.Seek(pos); + while (true) { + Key current; + if (!iter.Valid()) { + current = MakeKey(K, 0); + } else { + current = iter.key(); + ASSERT_TRUE(IsValidKey(current)) << current; + } + ASSERT_LE(pos, current) << "should not go backwards"; + + // Verify that everything in [pos,current) was not present in + // initial_state. + while (pos < current) { + ASSERT_LT(key(pos), K) << pos; + + // Note that generation 0 is never inserted, so it is ok if + // <*,0,*> is missing. + ASSERT_TRUE((gen(pos) == 0U) || + (gen(pos) > (uint64_t)initial_state.Get(key(pos))) + ) << "key: " << key(pos) + << "; gen: " << gen(pos) + << "; initgen: " + << initial_state.Get(key(pos)); + + // Advance to next key in the valid key space + if (key(pos) < key(current)) { + pos = MakeKey(key(pos) + 1, 0); + } else { + pos = MakeKey(key(pos), gen(pos) + 1); + } + } + + if (!iter.Valid()) { + break; + } + + if (rnd->Next() % 2) { + iter.Next(); + pos = MakeKey(key(pos), gen(pos) + 1); + } else { + Key new_target = RandomTarget(rnd); + if (new_target > pos) { + pos = new_target; + iter.Seek(new_target); + } + } + } + } +}; +const uint32_t ConcurrentTest::K; + +// Simple test that does single-threaded testing of the ConcurrentTest +// scaffolding. +TEST(SkipTest, ConcurrentWithoutThreads) { + ConcurrentTest test; + Random rnd(test::RandomSeed()); + for (int i = 0; i < 10000; i++) { + test.ReadStep(&rnd); + test.WriteStep(&rnd); + } +} + +class TestState { + public: + ConcurrentTest t_; + int seed_; + port::AtomicPointer quit_flag_; + + enum ReaderState { + STARTING, + RUNNING, + DONE + }; + + explicit TestState(int s) + : seed_(s), + quit_flag_(nullptr), + state_(STARTING), + state_cv_(&mu_) {} + + void Wait(ReaderState s) { + mu_.Lock(); + while (state_ != s) { + state_cv_.Wait(); + } + mu_.Unlock(); + } + + void Change(ReaderState s) { + mu_.Lock(); + state_ = s; + state_cv_.Signal(); + mu_.Unlock(); + } + + private: + port::Mutex mu_; + ReaderState state_; + port::CondVar state_cv_; +}; + +static void ConcurrentReader(void* arg) { + TestState* state = reinterpret_cast(arg); + Random rnd(state->seed_); + int64_t reads = 0; + state->Change(TestState::RUNNING); + while (!state->quit_flag_.Acquire_Load()) { + state->t_.ReadStep(&rnd); + ++reads; + } + state->Change(TestState::DONE); +} + +static void RunConcurrent(int run) { + const int seed = test::RandomSeed() + (run * 100); + Random rnd(seed); + const int N = 1000; + const int kSize = 1000; + for (int i = 0; i < N; i++) { + if ((i % 100) == 0) { + fprintf(stderr, "Run %d of %d\n", i, N); + } + TestState state(seed + 1); + Env::Default()->Schedule(ConcurrentReader, &state); + state.Wait(TestState::RUNNING); + for (int i = 0; i < kSize; i++) { + state.t_.WriteStep(&rnd); + } + state.quit_flag_.Release_Store(&state); // Any non-nullptr arg will do + state.Wait(TestState::DONE); + } +} + +TEST(SkipTest, Concurrent1) { RunConcurrent(1); } +TEST(SkipTest, Concurrent2) { RunConcurrent(2); } +TEST(SkipTest, Concurrent3) { RunConcurrent(3); } +TEST(SkipTest, Concurrent4) { RunConcurrent(4); } +TEST(SkipTest, Concurrent5) { RunConcurrent(5); } + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/db/snapshot.h b/db/snapshot.h new file mode 100644 index 00000000..96cf203a --- /dev/null +++ b/db/snapshot.h @@ -0,0 +1,88 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_SNAPSHOT_H_ +#define STORAGE_LEVELDB_DB_SNAPSHOT_H_ + +#include "leveldb/db.h" + +namespace leveldb { + +class SnapshotList; + +// Snapshots are kept in a doubly-linked list in the DB. +// Each SnapshotImpl corresponds to a particular sequence number. +class SnapshotImpl : public Snapshot { + public: + SequenceNumber number_; // const after creation + + private: + friend class SnapshotList; + + // SnapshotImpl is kept in a doubly-linked circular list + SnapshotImpl* prev_; + SnapshotImpl* next_; + + SnapshotList* list_; // just for sanity checks +}; + +class SnapshotList { + public: + SnapshotList() { + list_.prev_ = &list_; + list_.next_ = &list_; + list_.number_ = 0xFFFFFFFFL; // placeholder marker, for debugging + } + + bool empty() const { return list_.next_ == &list_; } + SnapshotImpl* oldest() const { assert(!empty()); return list_.next_; } + SnapshotImpl* newest() const { assert(!empty()); return list_.prev_; } + + const SnapshotImpl* New(SequenceNumber seq) { + SnapshotImpl* s = new SnapshotImpl; + s->number_ = seq; + s->list_ = this; + s->next_ = &list_; + s->prev_ = list_.prev_; + s->prev_->next_ = s; + s->next_->prev_ = s; + return s; + } + + void Delete(const SnapshotImpl* s) { + assert(s->list_ == this); + s->prev_->next_ = s->next_; + s->next_->prev_ = s->prev_; + delete s; + } + + // retrieve all snapshot numbers. They are sorted in ascending order. + void getAll(std::vector& ret) { + SnapshotImpl* s = &list_; + if (empty()) return; + SequenceNumber prev __attribute__((unused)) = 0; + while (s->next_ != &list_) { + assert(prev <= s->next_->number_); + assert(prev = s->next_->number_); // assignment + ret.push_back(s->next_->number_); + s = s ->next_; + } + } + + // get the sequence number of the most recent snapshot + const SequenceNumber GetNewest() { + if (empty()) { + return 0; + } + return newest()->number_; + } + + private: + // Dummy head of doubly-linked list of snapshots + SnapshotImpl list_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_SNAPSHOT_H_ diff --git a/db/table_cache.cc b/db/table_cache.cc new file mode 100644 index 00000000..f83578e5 --- /dev/null +++ b/db/table_cache.cc @@ -0,0 +1,130 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/table_cache.h" + +#include "db/filename.h" + +#include "leveldb/env.h" +#include "leveldb/table.h" +#include "leveldb/statistics.h" +#include "util/coding.h" + +namespace leveldb { + +struct TableAndFile { + unique_ptr table; +}; + +static class Statistics* dbstatistics; + +static void DeleteEntry(const Slice& key, void* value) { + TableAndFile* tf = reinterpret_cast(value); + RecordTick(dbstatistics, NO_FILE_CLOSES); + delete tf; +} + +static void UnrefEntry(void* arg1, void* arg2) { + Cache* cache = reinterpret_cast(arg1); + Cache::Handle* h = reinterpret_cast(arg2); + cache->Release(h); +} + +TableCache::TableCache(const std::string& dbname, + const Options* options, + int entries) + : env_(options->env), + dbname_(dbname), + options_(options), + cache_(NewLRUCache(entries, options->table_cache_numshardbits)) { + dbstatistics = options->statistics; +} + +TableCache::~TableCache() { +} + +Status TableCache::FindTable(uint64_t file_number, uint64_t file_size, + Cache::Handle** handle, bool* tableIO) { + Status s; + char buf[sizeof(file_number)]; + EncodeFixed64(buf, file_number); + Slice key(buf, sizeof(buf)); + *handle = cache_->Lookup(key); + if (*handle == nullptr) { + if (tableIO != nullptr) { + *tableIO = true; // we had to do IO from storage + } + std::string fname = TableFileName(dbname_, file_number); + unique_ptr file; + unique_ptr
table; + s = env_->NewRandomAccessFile(fname, &file); + RecordTick(options_->statistics, NO_FILE_OPENS); + if (s.ok()) { + s = Table::Open(*options_, std::move(file), file_size, &table); + } + + if (!s.ok()) { + assert(table == nullptr); + RecordTick(options_->statistics, NO_FILE_ERRORS); + // We do not cache error results so that if the error is transient, + // or somebody repairs the file, we recover automatically. + } else { + TableAndFile* tf = new TableAndFile; + tf->table = std::move(table); + assert(file.get() == nullptr); + *handle = cache_->Insert(key, tf, 1, &DeleteEntry); + } + } + return s; +} + +Iterator* TableCache::NewIterator(const ReadOptions& options, + uint64_t file_number, + uint64_t file_size, + Table** tableptr) { + if (tableptr != nullptr) { + *tableptr = nullptr; + } + + Cache::Handle* handle = nullptr; + Status s = FindTable(file_number, file_size, &handle); + if (!s.ok()) { + return NewErrorIterator(s); + } + + Table* table = + reinterpret_cast(cache_->Value(handle))->table.get(); + Iterator* result = table->NewIterator(options); + result->RegisterCleanup(&UnrefEntry, cache_.get(), handle); + if (tableptr != nullptr) { + *tableptr = table; + } + return result; +} + +Status TableCache::Get(const ReadOptions& options, + uint64_t file_number, + uint64_t file_size, + const Slice& k, + void* arg, + void (*saver)(void*, const Slice&, const Slice&, bool), + bool* tableIO) { + Cache::Handle* handle = nullptr; + Status s = FindTable(file_number, file_size, &handle, tableIO); + if (s.ok()) { + Table* t = + reinterpret_cast(cache_->Value(handle))->table.get(); + s = t->InternalGet(options, k, arg, saver); + cache_->Release(handle); + } + return s; +} + +void TableCache::Evict(uint64_t file_number) { + char buf[sizeof(file_number)]; + EncodeFixed64(buf, file_number); + cache_->Erase(Slice(buf, sizeof(buf))); +} + +} // namespace leveldb diff --git a/db/table_cache.h b/db/table_cache.h new file mode 100644 index 00000000..67449309 --- /dev/null +++ b/db/table_cache.h @@ -0,0 +1,63 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Thread-safe (provides internal synchronization) + +#ifndef STORAGE_LEVELDB_DB_TABLE_CACHE_H_ +#define STORAGE_LEVELDB_DB_TABLE_CACHE_H_ + +#include +#include +#include "db/dbformat.h" +#include "leveldb/cache.h" +#include "leveldb/table.h" +#include "port/port.h" + +namespace leveldb { + +class Env; + +class TableCache { + public: + TableCache(const std::string& dbname, const Options* options, int entries); + ~TableCache(); + + // Return an iterator for the specified file number (the corresponding + // file length must be exactly "file_size" bytes). If "tableptr" is + // non-nullptr, also sets "*tableptr" to point to the Table object + // underlying the returned iterator, or nullptr if no Table object underlies + // the returned iterator. The returned "*tableptr" object is owned by + // the cache and should not be deleted, and is valid for as long as the + // returned iterator is live. + Iterator* NewIterator(const ReadOptions& options, + uint64_t file_number, + uint64_t file_size, + Table** tableptr = nullptr); + + // If a seek to internal key "k" in specified file finds an entry, + // call (*handle_result)(arg, found_key, found_value). + Status Get(const ReadOptions& options, + uint64_t file_number, + uint64_t file_size, + const Slice& k, + void* arg, + void (*handle_result)(void*, const Slice&, const Slice&, bool), + bool* tableIO); + + // Evict any entry for the specified file number + void Evict(uint64_t file_number); + + private: + Env* const env_; + const std::string dbname_; + const Options* options_; + std::shared_ptr cache_; + + Status FindTable(uint64_t file_number, uint64_t file_size, Cache::Handle**, + bool* tableIO = nullptr); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_TABLE_CACHE_H_ diff --git a/db/transaction_log_iterator_impl.cc b/db/transaction_log_iterator_impl.cc new file mode 100644 index 00000000..70ec8c9d --- /dev/null +++ b/db/transaction_log_iterator_impl.cc @@ -0,0 +1,172 @@ +#include "db/transaction_log_iterator_impl.h" +#include "db/write_batch_internal.h" +#include "db/filename.h" +namespace leveldb { + +TransactionLogIteratorImpl::TransactionLogIteratorImpl( + const std::string& dbname, + const Options* options, + SequenceNumber& seq, + std::vector* files, + SequenceNumber const * const lastFlushedSequence) : + dbname_(dbname), + options_(options), + sequenceNumber_(seq), + files_(files), + started_(false), + isValid_(true), + currentFileIndex_(0), + lastFlushedSequence_(lastFlushedSequence) { + assert(files_ != nullptr); + assert(lastFlushedSequence_); +} + +LogReporter +TransactionLogIteratorImpl::NewLogReporter(const uint64_t logNumber) { + LogReporter reporter; + reporter.env = options_->env; + reporter.info_log = options_->info_log.get(); + reporter.log_number = logNumber; + return reporter; +} + +Status TransactionLogIteratorImpl::OpenLogFile( + const LogFile& logFile, + unique_ptr* file) { + Env* env = options_->env; + if (logFile.type == kArchivedLogFile) { + std::string fname = ArchivedLogFileName(dbname_, logFile.logNumber); + return env->NewSequentialFile(fname, file); + } else { + std::string fname = LogFileName(dbname_, logFile.logNumber); + Status status = env->NewSequentialFile(fname, file); + if (!status.ok()) { + // If cannot open file in DB directory. + // Try the archive dir, as it could have moved in the meanwhile. + fname = ArchivedLogFileName(dbname_, logFile.logNumber); + status = env->NewSequentialFile(fname, file); + if (!status.ok()) { + return Status::IOError(" Requested file not present in the dir"); + } + } + return status; + } +} + +BatchResult TransactionLogIteratorImpl::GetBatch() { + assert(isValid_); // cannot call in a non valid state. + BatchResult result; + result.sequence = currentSequence_; + result.writeBatchPtr = std::move(currentBatch_); + return result; +} + +Status TransactionLogIteratorImpl::status() { + return currentStatus_; +} + +bool TransactionLogIteratorImpl::Valid() { + return started_ && isValid_; +} + +void TransactionLogIteratorImpl::Next() { +// First seek to the given seqNo. in the current file. + LogFile currentLogFile = files_->at(currentFileIndex_); + LogReporter reporter = NewLogReporter(currentLogFile.logNumber); + std::string scratch; + Slice record; + + if (!started_) { + isValid_ = false; + if (sequenceNumber_ > *lastFlushedSequence_) { + currentStatus_ = Status::IOError("Looking for a sequence, " + "which is not flushed yet."); + return; + } + unique_ptr file; + Status status = OpenLogFile(currentLogFile, &file); + if (!status.ok()) { + currentStatus_ = status; + return; + } + assert(file); + unique_ptr reader( + new log::Reader(std::move(file), &reporter, true, 0)); + assert(reader); + while (reader->ReadRecord(&record, &scratch)) { + if (record.size() < 12) { + reporter.Corruption( + record.size(), Status::Corruption("log record too small")); + continue; + } + UpdateCurrentWriteBatch(record); + if (currentSequence_ >= sequenceNumber_) { + assert(currentSequence_ < *lastFlushedSequence_); + isValid_ = true; + currentLogReader_ = std::move(reader); + break; + } + } + if (!isValid_) { + // TODO read the entire first file. and did not find the seq number. + // Error out. + currentStatus_ = + Status::NotFound("Did not find the Seq no. in first file"); + } + started_ = true; + } else { +LOOK_NEXT_FILE: + assert(currentLogReader_); + bool openNextFile = true; + + if (currentSequence_ == *lastFlushedSequence_) { + // The last update has been read. and next is being called. + isValid_ = false; + currentStatus_ = Status::OK(); + } + + while (currentLogReader_->ReadRecord(&record, &scratch) && + currentSequence_ < *lastFlushedSequence_) { + if (record.size() < 12) { + reporter.Corruption( + record.size(), Status::Corruption("log record too small")); + continue; + } else { + UpdateCurrentWriteBatch(record); + openNextFile = false; + break; + } + } + + if (openNextFile) { + if (currentFileIndex_ < files_->size() - 1) { + ++currentFileIndex_; + currentLogReader_.reset(); + unique_ptr file; + Status status = OpenLogFile(files_->at(currentFileIndex_), &file); + if (!status.ok()) { + isValid_ = false; + currentStatus_ = status; + return; + } + currentLogReader_.reset( + new log::Reader(std::move(file), &reporter, true, 0)); + goto LOOK_NEXT_FILE; + } else { + // LOOKED AT FILES. WE ARE DONE HERE. + isValid_ = false; + currentStatus_ = Status::IOError(" NO MORE DATA LEFT"); + } + } + + } +} + +void TransactionLogIteratorImpl::UpdateCurrentWriteBatch(const Slice& record) { + WriteBatch* batch = new WriteBatch(); + WriteBatchInternal::SetContents(batch, record); + currentSequence_ = WriteBatchInternal::Sequence(batch); + currentBatch_.reset(batch); +} + +} // namespace leveldb diff --git a/db/transaction_log_iterator_impl.h b/db/transaction_log_iterator_impl.h new file mode 100644 index 00000000..c1e541e5 --- /dev/null +++ b/db/transaction_log_iterator_impl.h @@ -0,0 +1,70 @@ +// Copyright 2008-present Facebook. All Rights Reserved. +#ifndef STORAGE_LEVELDB_INCLUDE_WRITES_ITERATOR_IMPL_H_ +#define STORAGE_LEVELDB_INCLUDE_WRITES_ITERATOR_IMPL_H_ + +#include + +#include "leveldb/env.h" +#include "leveldb/options.h" +#include "leveldb/types.h" +#include "leveldb/transaction_log_iterator.h" +#include "db/log_file.h" +#include "db/log_reader.h" + +namespace leveldb { + +struct LogReporter : public log::Reader::Reporter { + Env* env; + Logger* info_log; + uint64_t log_number; + virtual void Corruption(size_t bytes, const Status& s) { + Log(info_log, "%ld: dropping %d bytes; %s", + log_number, static_cast(bytes), s.ToString().c_str()); + } +}; + +class TransactionLogIteratorImpl : public TransactionLogIterator { + public: + TransactionLogIteratorImpl(const std::string& dbname, + const Options* options, + SequenceNumber& seqNum, + std::vector* files, + SequenceNumber const * const lastFlushedSequence); + + virtual ~TransactionLogIteratorImpl() { + // TODO move to cc file. + delete files_; + } + + virtual bool Valid(); + + virtual void Next(); + + virtual Status status(); + + virtual BatchResult GetBatch(); + + private: + const std::string& dbname_; + const Options* options_; + const uint64_t sequenceNumber_; + const std::vector* files_; + bool started_; + bool isValid_; // not valid when it starts of. + Status currentStatus_; + size_t currentFileIndex_; + std::unique_ptr currentBatch_; + unique_ptr currentLogReader_; + Status OpenLogFile(const LogFile& logFile, unique_ptr* file); + LogReporter NewLogReporter(uint64_t logNumber); + SequenceNumber const * const lastFlushedSequence_; + // represents the sequence number being read currently. + SequenceNumber currentSequence_; + + void UpdateCurrentWriteBatch(const Slice& record); +}; + + + +} // namespace leveldb +#endif // STORAGE_LEVELDB_INCLUDE_WRITES_ITERATOR_IMPL_H_ diff --git a/db/version_edit.cc b/db/version_edit.cc new file mode 100644 index 00000000..ed63c101 --- /dev/null +++ b/db/version_edit.cc @@ -0,0 +1,275 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/version_edit.h" + +#include "db/version_set.h" +#include "util/coding.h" + +namespace leveldb { + +// Tag numbers for serialized VersionEdit. These numbers are written to +// disk and should not be changed. +enum Tag { + kComparator = 1, + kLogNumber = 2, + kNextFileNumber = 3, + kLastSequence = 4, + kCompactPointer = 5, + kDeletedFile = 6, + kNewFile = 7, + // 8 was used for large value refs + kPrevLogNumber = 9 +}; + +void VersionEdit::Clear() { + comparator_.clear(); + log_number_ = 0; + prev_log_number_ = 0; + last_sequence_ = 0; + next_file_number_ = 0; + has_comparator_ = false; + has_log_number_ = false; + has_prev_log_number_ = false; + has_next_file_number_ = false; + has_last_sequence_ = false; + deleted_files_.clear(); + new_files_.clear(); +} + +void VersionEdit::EncodeTo(std::string* dst) const { + if (has_comparator_) { + PutVarint32(dst, kComparator); + PutLengthPrefixedSlice(dst, comparator_); + } + if (has_log_number_) { + PutVarint32(dst, kLogNumber); + PutVarint64(dst, log_number_); + } + if (has_prev_log_number_) { + PutVarint32(dst, kPrevLogNumber); + PutVarint64(dst, prev_log_number_); + } + if (has_next_file_number_) { + PutVarint32(dst, kNextFileNumber); + PutVarint64(dst, next_file_number_); + } + if (has_last_sequence_) { + PutVarint32(dst, kLastSequence); + PutVarint64(dst, last_sequence_); + } + + for (size_t i = 0; i < compact_pointers_.size(); i++) { + PutVarint32(dst, kCompactPointer); + PutVarint32(dst, compact_pointers_[i].first); // level + PutLengthPrefixedSlice(dst, compact_pointers_[i].second.Encode()); + } + + for (DeletedFileSet::const_iterator iter = deleted_files_.begin(); + iter != deleted_files_.end(); + ++iter) { + PutVarint32(dst, kDeletedFile); + PutVarint32(dst, iter->first); // level + PutVarint64(dst, iter->second); // file number + } + + for (size_t i = 0; i < new_files_.size(); i++) { + const FileMetaData& f = new_files_[i].second; + PutVarint32(dst, kNewFile); + PutVarint32(dst, new_files_[i].first); // level + PutVarint64(dst, f.number); + PutVarint64(dst, f.file_size); + PutLengthPrefixedSlice(dst, f.smallest.Encode()); + PutLengthPrefixedSlice(dst, f.largest.Encode()); + } +} + +static bool GetInternalKey(Slice* input, InternalKey* dst) { + Slice str; + if (GetLengthPrefixedSlice(input, &str)) { + dst->DecodeFrom(str); + return true; + } else { + return false; + } +} + +bool VersionEdit::GetLevel(Slice* input, int* level, const char** msg) { + uint32_t v; + if (GetVarint32(input, &v) && + (int)v < number_levels_) { + *level = v; + return true; + } else { + if ((int)v >= number_levels_) { + *msg = "db already has more levels than options.num_levels"; + } + return false; + } +} + +Status VersionEdit::DecodeFrom(const Slice& src) { + Clear(); + Slice input = src; + const char* msg = nullptr; + uint32_t tag; + + // Temporary storage for parsing + int level; + uint64_t number; + FileMetaData f; + Slice str; + InternalKey key; + + while (msg == nullptr && GetVarint32(&input, &tag)) { + switch (tag) { + case kComparator: + if (GetLengthPrefixedSlice(&input, &str)) { + comparator_ = str.ToString(); + has_comparator_ = true; + } else { + msg = "comparator name"; + } + break; + + case kLogNumber: + if (GetVarint64(&input, &log_number_)) { + has_log_number_ = true; + } else { + msg = "log number"; + } + break; + + case kPrevLogNumber: + if (GetVarint64(&input, &prev_log_number_)) { + has_prev_log_number_ = true; + } else { + msg = "previous log number"; + } + break; + + case kNextFileNumber: + if (GetVarint64(&input, &next_file_number_)) { + has_next_file_number_ = true; + } else { + msg = "next file number"; + } + break; + + case kLastSequence: + if (GetVarint64(&input, &last_sequence_)) { + has_last_sequence_ = true; + } else { + msg = "last sequence number"; + } + break; + + case kCompactPointer: + if (GetLevel(&input, &level, &msg) && + GetInternalKey(&input, &key)) { + compact_pointers_.push_back(std::make_pair(level, key)); + } else { + if (!msg) { + msg = "compaction pointer"; + } + } + break; + + case kDeletedFile: + if (GetLevel(&input, &level, &msg) && + GetVarint64(&input, &number)) { + deleted_files_.insert(std::make_pair(level, number)); + } else { + if (!msg) { + msg = "deleted file"; + } + } + break; + + case kNewFile: + if (GetLevel(&input, &level, &msg) && + GetVarint64(&input, &f.number) && + GetVarint64(&input, &f.file_size) && + GetInternalKey(&input, &f.smallest) && + GetInternalKey(&input, &f.largest)) { + new_files_.push_back(std::make_pair(level, f)); + } else { + if (!msg) { + msg = "new-file entry"; + } + } + break; + + default: + msg = "unknown tag"; + break; + } + } + + if (msg == nullptr && !input.empty()) { + msg = "invalid tag"; + } + + Status result; + if (msg != nullptr) { + result = Status::Corruption("VersionEdit", msg); + } + return result; +} + +std::string VersionEdit::DebugString() const { + std::string r; + r.append("VersionEdit {"); + if (has_comparator_) { + r.append("\n Comparator: "); + r.append(comparator_); + } + if (has_log_number_) { + r.append("\n LogNumber: "); + AppendNumberTo(&r, log_number_); + } + if (has_prev_log_number_) { + r.append("\n PrevLogNumber: "); + AppendNumberTo(&r, prev_log_number_); + } + if (has_next_file_number_) { + r.append("\n NextFile: "); + AppendNumberTo(&r, next_file_number_); + } + if (has_last_sequence_) { + r.append("\n LastSeq: "); + AppendNumberTo(&r, last_sequence_); + } + for (size_t i = 0; i < compact_pointers_.size(); i++) { + r.append("\n CompactPointer: "); + AppendNumberTo(&r, compact_pointers_[i].first); + r.append(" "); + r.append(compact_pointers_[i].second.DebugString()); + } + for (DeletedFileSet::const_iterator iter = deleted_files_.begin(); + iter != deleted_files_.end(); + ++iter) { + r.append("\n DeleteFile: "); + AppendNumberTo(&r, iter->first); + r.append(" "); + AppendNumberTo(&r, iter->second); + } + for (size_t i = 0; i < new_files_.size(); i++) { + const FileMetaData& f = new_files_[i].second; + r.append("\n AddFile: "); + AppendNumberTo(&r, new_files_[i].first); + r.append(" "); + AppendNumberTo(&r, f.number); + r.append(" "); + AppendNumberTo(&r, f.file_size); + r.append(" "); + r.append(f.smallest.DebugString()); + r.append(" .. "); + r.append(f.largest.DebugString()); + } + r.append("\n}\n"); + return r; +} + +} // namespace leveldb diff --git a/db/version_edit.h b/db/version_edit.h new file mode 100644 index 00000000..3776c217 --- /dev/null +++ b/db/version_edit.h @@ -0,0 +1,115 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_VERSION_EDIT_H_ +#define STORAGE_LEVELDB_DB_VERSION_EDIT_H_ + +#include +#include +#include +#include "db/dbformat.h" + +namespace leveldb { + +class VersionSet; + +struct FileMetaData { + int refs; + int allowed_seeks; // Seeks allowed until compaction + uint64_t number; + uint64_t file_size; // File size in bytes + InternalKey smallest; // Smallest internal key served by table + InternalKey largest; // Largest internal key served by table + bool being_compacted; // Is this file undergoing compaction? + + FileMetaData() : refs(0), allowed_seeks(1 << 30), file_size(0), + being_compacted(false) { } +}; + +class VersionEdit { + public: + /* implicit */ VersionEdit(int number_levels) : + number_levels_(number_levels) { + Clear(); + } + ~VersionEdit() { } + + void Clear(); + + void SetComparatorName(const Slice& name) { + has_comparator_ = true; + comparator_ = name.ToString(); + } + void SetLogNumber(uint64_t num) { + has_log_number_ = true; + log_number_ = num; + } + void SetPrevLogNumber(uint64_t num) { + has_prev_log_number_ = true; + prev_log_number_ = num; + } + void SetNextFile(uint64_t num) { + has_next_file_number_ = true; + next_file_number_ = num; + } + void SetLastSequence(SequenceNumber seq) { + has_last_sequence_ = true; + last_sequence_ = seq; + } + void SetCompactPointer(int level, const InternalKey& key) { + compact_pointers_.push_back(std::make_pair(level, key)); + } + + // Add the specified file at the specified number. + // REQUIRES: This version has not been saved (see VersionSet::SaveTo) + // REQUIRES: "smallest" and "largest" are smallest and largest keys in file + void AddFile(int level, uint64_t file, + uint64_t file_size, + const InternalKey& smallest, + const InternalKey& largest) { + FileMetaData f; + f.number = file; + f.file_size = file_size; + f.smallest = smallest; + f.largest = largest; + new_files_.push_back(std::make_pair(level, f)); + } + + // Delete the specified "file" from the specified "level". + void DeleteFile(int level, uint64_t file) { + deleted_files_.insert(std::make_pair(level, file)); + } + + void EncodeTo(std::string* dst) const; + Status DecodeFrom(const Slice& src); + + std::string DebugString() const; + + private: + friend class VersionSet; + + typedef std::set< std::pair > DeletedFileSet; + + bool GetLevel(Slice* input, int* level, const char** msg); + + int number_levels_; + std::string comparator_; + uint64_t log_number_; + uint64_t prev_log_number_; + uint64_t next_file_number_; + SequenceNumber last_sequence_; + bool has_comparator_; + bool has_log_number_; + bool has_prev_log_number_; + bool has_next_file_number_; + bool has_last_sequence_; + + std::vector< std::pair > compact_pointers_; + DeletedFileSet deleted_files_; + std::vector< std::pair > new_files_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_VERSION_EDIT_H_ diff --git a/db/version_edit_test.cc b/db/version_edit_test.cc new file mode 100644 index 00000000..b211eb1a --- /dev/null +++ b/db/version_edit_test.cc @@ -0,0 +1,46 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/version_edit.h" +#include "util/testharness.h" + +namespace leveldb { + +static void TestEncodeDecode(const VersionEdit& edit) { + std::string encoded, encoded2; + edit.EncodeTo(&encoded); + VersionEdit parsed(7); + Status s = parsed.DecodeFrom(encoded); + ASSERT_TRUE(s.ok()) << s.ToString(); + parsed.EncodeTo(&encoded2); + ASSERT_EQ(encoded, encoded2); +} + +class VersionEditTest { }; + +TEST(VersionEditTest, EncodeDecode) { + static const uint64_t kBig = 1ull << 50; + + VersionEdit edit(7); + for (int i = 0; i < 4; i++) { + TestEncodeDecode(edit); + edit.AddFile(3, kBig + 300 + i, kBig + 400 + i, + InternalKey("foo", kBig + 500 + i, kTypeValue), + InternalKey("zoo", kBig + 600 + i, kTypeDeletion)); + edit.DeleteFile(4, kBig + 700 + i); + edit.SetCompactPointer(i, InternalKey("x", kBig + 900 + i, kTypeValue)); + } + + edit.SetComparatorName("foo"); + edit.SetLogNumber(kBig + 100); + edit.SetNextFile(kBig + 200); + edit.SetLastSequence(kBig + 1000); + TestEncodeDecode(edit); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/db/version_set.cc b/db/version_set.cc new file mode 100644 index 00000000..8c1983ad --- /dev/null +++ b/db/version_set.cc @@ -0,0 +1,2269 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/version_set.h" + +#include +#include +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "db/memtable.h" +#include "db/table_cache.h" +#include "leveldb/env.h" +#include "leveldb/table_builder.h" +#include "table/merger.h" +#include "table/two_level_iterator.h" +#include "util/coding.h" +#include "util/logging.h" + +namespace leveldb { + +static int64_t TotalFileSize(const std::vector& files) { + int64_t sum = 0; + for (size_t i = 0; i < files.size() && files[i]; i++) { + sum += files[i]->file_size; + } + return sum; +} + +Version::~Version() { + assert(refs_ == 0); + + // Remove from linked list + prev_->next_ = next_; + next_->prev_ = prev_; + + // Drop references to files + for (int level = 0; level < vset_->NumberLevels(); level++) { + for (size_t i = 0; i < files_[level].size(); i++) { + FileMetaData* f = files_[level][i]; + assert(f->refs > 0); + f->refs--; + if (f->refs <= 0) { + delete f; + } + } + } + delete[] files_; +} + +int FindFile(const InternalKeyComparator& icmp, + const std::vector& files, + const Slice& key) { + uint32_t left = 0; + uint32_t right = files.size(); + while (left < right) { + uint32_t mid = (left + right) / 2; + const FileMetaData* f = files[mid]; + if (icmp.InternalKeyComparator::Compare(f->largest.Encode(), key) < 0) { + // Key at "mid.largest" is < "target". Therefore all + // files at or before "mid" are uninteresting. + left = mid + 1; + } else { + // Key at "mid.largest" is >= "target". Therefore all files + // after "mid" are uninteresting. + right = mid; + } + } + return right; +} + +static bool AfterFile(const Comparator* ucmp, + const Slice* user_key, const FileMetaData* f) { + // nullptr user_key occurs before all keys and is therefore never after *f + return (user_key != nullptr && + ucmp->Compare(*user_key, f->largest.user_key()) > 0); +} + +static bool BeforeFile(const Comparator* ucmp, + const Slice* user_key, const FileMetaData* f) { + // nullptr user_key occurs after all keys and is therefore never before *f + return (user_key != nullptr && + ucmp->Compare(*user_key, f->smallest.user_key()) < 0); +} + +bool SomeFileOverlapsRange( + const InternalKeyComparator& icmp, + bool disjoint_sorted_files, + const std::vector& files, + const Slice* smallest_user_key, + const Slice* largest_user_key) { + const Comparator* ucmp = icmp.user_comparator(); + if (!disjoint_sorted_files) { + // Need to check against all files + for (size_t i = 0; i < files.size(); i++) { + const FileMetaData* f = files[i]; + if (AfterFile(ucmp, smallest_user_key, f) || + BeforeFile(ucmp, largest_user_key, f)) { + // No overlap + } else { + return true; // Overlap + } + } + return false; + } + + // Binary search over file list + uint32_t index = 0; + if (smallest_user_key != nullptr) { + // Find the earliest possible internal key for smallest_user_key + InternalKey small(*smallest_user_key, kMaxSequenceNumber,kValueTypeForSeek); + index = FindFile(icmp, files, small.Encode()); + } + + if (index >= files.size()) { + // beginning of range is after all files, so no overlap. + return false; + } + + return !BeforeFile(ucmp, largest_user_key, files[index]); +} + +// An internal iterator. For a given version/level pair, yields +// information about the files in the level. For a given entry, key() +// is the largest key that occurs in the file, and value() is an +// 16-byte value containing the file number and file size, both +// encoded using EncodeFixed64. +class Version::LevelFileNumIterator : public Iterator { + public: + LevelFileNumIterator(const InternalKeyComparator& icmp, + const std::vector* flist) + : icmp_(icmp), + flist_(flist), + index_(flist->size()) { // Marks as invalid + } + virtual bool Valid() const { + return index_ < flist_->size(); + } + virtual void Seek(const Slice& target) { + index_ = FindFile(icmp_, *flist_, target); + } + virtual void SeekToFirst() { index_ = 0; } + virtual void SeekToLast() { + index_ = flist_->empty() ? 0 : flist_->size() - 1; + } + virtual void Next() { + assert(Valid()); + index_++; + } + virtual void Prev() { + assert(Valid()); + if (index_ == 0) { + index_ = flist_->size(); // Marks as invalid + } else { + index_--; + } + } + Slice key() const { + assert(Valid()); + return (*flist_)[index_]->largest.Encode(); + } + Slice value() const { + assert(Valid()); + EncodeFixed64(value_buf_, (*flist_)[index_]->number); + EncodeFixed64(value_buf_+8, (*flist_)[index_]->file_size); + return Slice(value_buf_, sizeof(value_buf_)); + } + virtual Status status() const { return Status::OK(); } + private: + const InternalKeyComparator icmp_; + const std::vector* const flist_; + uint32_t index_; + + // Backing store for value(). Holds the file number and size. + mutable char value_buf_[16]; +}; + +static Iterator* GetFileIterator(void* arg, + const ReadOptions& options, + const Slice& file_value) { + TableCache* cache = reinterpret_cast(arg); + if (file_value.size() != 16) { + return NewErrorIterator( + Status::Corruption("FileReader invoked with unexpected value")); + } else { + return cache->NewIterator(options, + DecodeFixed64(file_value.data()), + DecodeFixed64(file_value.data() + 8)); + } +} + +Iterator* Version::NewConcatenatingIterator(const ReadOptions& options, + int level) const { + return NewTwoLevelIterator( + new LevelFileNumIterator(vset_->icmp_, &files_[level]), + &GetFileIterator, vset_->table_cache_, options); +} + +void Version::AddIterators(const ReadOptions& options, + std::vector* iters) { + // Merge all level zero files together since they may overlap + for (size_t i = 0; i < files_[0].size(); i++) { + iters->push_back( + vset_->table_cache_->NewIterator( + options, files_[0][i]->number, files_[0][i]->file_size)); + } + + // For levels > 0, we can use a concatenating iterator that sequentially + // walks through the non-overlapping files in the level, opening them + // lazily. + for (int level = 1; level < vset_->NumberLevels(); level++) { + if (!files_[level].empty()) { + iters->push_back(NewConcatenatingIterator(options, level)); + } + } +} + +// Callback from TableCache::Get() +namespace { +enum SaverState { + kNotFound, + kFound, + kDeleted, + kCorrupt, +}; +struct Saver { + SaverState state; + const Comparator* ucmp; + Slice user_key; + std::string* value; + bool didIO; // did we do any disk io? +}; +} +static void SaveValue(void* arg, const Slice& ikey, const Slice& v, bool didIO){ + Saver* s = reinterpret_cast(arg); + ParsedInternalKey parsed_key; + s->didIO = didIO; + if (!ParseInternalKey(ikey, &parsed_key)) { + s->state = kCorrupt; + } else { + if (s->ucmp->Compare(parsed_key.user_key, s->user_key) == 0) { + s->state = (parsed_key.type == kTypeValue) ? kFound : kDeleted; + if (s->state == kFound) { + s->value->assign(v.data(), v.size()); + } + } + } +} + +static bool NewestFirst(FileMetaData* a, FileMetaData* b) { + return a->number > b->number; +} + +Version::Version(VersionSet* vset, uint64_t version_number) + : vset_(vset), next_(this), prev_(this), refs_(0), + files_by_size_(vset->NumberLevels()), + next_file_to_compact_by_size_(vset->NumberLevels()), + file_to_compact_(nullptr), + file_to_compact_level_(-1), + compaction_score_(vset->NumberLevels()), + compaction_level_(vset->NumberLevels()), + offset_manifest_file_(0), + version_number_(version_number) { + files_ = new std::vector[vset->NumberLevels()]; +} + +Status Version::Get(const ReadOptions& options, + const LookupKey& k, + std::string* value, + GetStats* stats) { + Slice ikey = k.internal_key(); + Slice user_key = k.user_key(); + const Comparator* ucmp = vset_->icmp_.user_comparator(); + Status s; + + stats->seek_file = nullptr; + stats->seek_file_level = -1; + FileMetaData* last_file_read = nullptr; + int last_file_read_level = -1; + + // We can search level-by-level since entries never hop across + // levels. Therefore we are guaranteed that if we find data + // in an smaller level, later levels are irrelevant. + std::vector tmp; + FileMetaData* tmp2; + for (int level = 0; level < vset_->NumberLevels(); level++) { + size_t num_files = files_[level].size(); + if (num_files == 0) continue; + + // Get the list of files to search in this level + FileMetaData* const* files = &files_[level][0]; + if (level == 0) { + // Level-0 files may overlap each other. Find all files that + // overlap user_key and process them in order from newest to oldest. + tmp.reserve(num_files); + for (uint32_t i = 0; i < num_files; i++) { + FileMetaData* f = files[i]; + if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 && + ucmp->Compare(user_key, f->largest.user_key()) <= 0) { + tmp.push_back(f); + } + } + if (tmp.empty()) continue; + + std::sort(tmp.begin(), tmp.end(), NewestFirst); + files = &tmp[0]; + num_files = tmp.size(); + } else { + // Binary search to find earliest index whose largest key >= ikey. + uint32_t index = FindFile(vset_->icmp_, files_[level], ikey); + if (index >= num_files) { + files = nullptr; + num_files = 0; + } else { + tmp2 = files[index]; + if (ucmp->Compare(user_key, tmp2->smallest.user_key()) < 0) { + // All of "tmp2" is past any data for user_key + files = nullptr; + num_files = 0; + } else { + files = &tmp2; + num_files = 1; + } + } + } + + for (uint32_t i = 0; i < num_files; ++i) { + + FileMetaData* f = files[i]; + Saver saver; + saver.state = kNotFound; + saver.ucmp = ucmp; + saver.user_key = user_key; + saver.value = value; + saver.didIO = false; + bool tableIO = false; + s = vset_->table_cache_->Get(options, f->number, f->file_size, + ikey, &saver, SaveValue, &tableIO); + if (!s.ok()) { + return s; + } + + if (last_file_read != nullptr && stats->seek_file == nullptr) { + // We have had more than one seek for this read. Charge the 1st file. + stats->seek_file = last_file_read; + stats->seek_file_level = last_file_read_level; + } + + // If we did any IO as part of the read, then we remember it because + // it is a possible candidate for seek-based compaction. saver.didIO + // is true if the block had to be read in from storage and was not + // pre-exisiting in the block cache. Also, if this file was not pre- + // existing in the table cache and had to be freshly opened that needed + // the index blocks to be read-in, then tableIO is true. One thing + // to note is that the index blocks are not part of the block cache. + if (saver.didIO || tableIO) { + last_file_read = f; + last_file_read_level = level; + } + + switch (saver.state) { + case kNotFound: + break; // Keep searching in other files + case kFound: + return s; + case kDeleted: + s = Status::NotFound(Slice()); // Use empty error message for speed + return s; + case kCorrupt: + s = Status::Corruption("corrupted key for ", user_key); + return s; + } + } + } + + return Status::NotFound(Slice()); // Use an empty error message for speed +} + +bool Version::UpdateStats(const GetStats& stats) { + FileMetaData* f = stats.seek_file; + if (f != nullptr) { + f->allowed_seeks--; + if (f->allowed_seeks <= 0 && file_to_compact_ == nullptr) { + file_to_compact_ = f; + file_to_compact_level_ = stats.seek_file_level; + return true; + } + } + return false; +} + +void Version::Ref() { + ++refs_; +} + +void Version::Unref() { + assert(this != &vset_->dummy_versions_); + assert(refs_ >= 1); + --refs_; + if (refs_ == 0) { + delete this; + } +} + +bool Version::OverlapInLevel(int level, + const Slice* smallest_user_key, + const Slice* largest_user_key) { + return SomeFileOverlapsRange(vset_->icmp_, (level > 0), files_[level], + smallest_user_key, largest_user_key); +} + +int Version::PickLevelForMemTableOutput( + const Slice& smallest_user_key, + const Slice& largest_user_key) { + int level = 0; + if (!OverlapInLevel(0, &smallest_user_key, &largest_user_key)) { + // Push to next level if there is no overlap in next level, + // and the #bytes overlapping in the level after that are limited. + InternalKey start(smallest_user_key, kMaxSequenceNumber, kValueTypeForSeek); + InternalKey limit(largest_user_key, 0, static_cast(0)); + std::vector overlaps; + int max_mem_compact_level = vset_->options_->max_mem_compaction_level; + while (max_mem_compact_level > 0 && level < max_mem_compact_level) { + if (OverlapInLevel(level + 1, &smallest_user_key, &largest_user_key)) { + break; + } + if (level + 2 >= vset_->NumberLevels()) { + level++; + break; + } + GetOverlappingInputs(level + 2, &start, &limit, &overlaps); + const int64_t sum = TotalFileSize(overlaps); + if (sum > vset_->MaxGrandParentOverlapBytes(level)) { + break; + } + level++; + } + } + + return level; +} + +// Store in "*inputs" all files in "level" that overlap [begin,end] +// If hint_index is specified, then it points to a file in the +// overlapping range. +// The file_index returns a pointer to any file in an overlapping range. +void Version::GetOverlappingInputs( + int level, + const InternalKey* begin, + const InternalKey* end, + std::vector* inputs, + int hint_index, + int* file_index) { + inputs->clear(); + Slice user_begin, user_end; + if (begin != nullptr) { + user_begin = begin->user_key(); + } + if (end != nullptr) { + user_end = end->user_key(); + } + if (file_index) { + *file_index = -1; + } + const Comparator* user_cmp = vset_->icmp_.user_comparator(); + if (begin != nullptr && end != nullptr && level > 0) { + GetOverlappingInputsBinarySearch(level, user_begin, user_end, inputs, + hint_index, file_index); + return; + } + for (size_t i = 0; i < files_[level].size(); ) { + FileMetaData* f = files_[level][i++]; + const Slice file_start = f->smallest.user_key(); + const Slice file_limit = f->largest.user_key(); + if (begin != nullptr && user_cmp->Compare(file_limit, user_begin) < 0) { + // "f" is completely before specified range; skip it + } else if (end != nullptr && user_cmp->Compare(file_start, user_end) > 0) { + // "f" is completely after specified range; skip it + } else { + inputs->push_back(f); + if (level == 0) { + // Level-0 files may overlap each other. So check if the newly + // added file has expanded the range. If so, restart search. + if (begin != nullptr && user_cmp->Compare(file_start, user_begin) < 0) { + user_begin = file_start; + inputs->clear(); + i = 0; + } else if (end != nullptr + && user_cmp->Compare(file_limit, user_end) > 0) { + user_end = file_limit; + inputs->clear(); + i = 0; + } + } else if (file_index) { + *file_index = i-1; + } + } + } +} + +// Store in "*inputs" all files in "level" that overlap [begin,end] +// Employ binary search to find at least one file that overlaps the +// specified range. From that file, iterate backwards and +// forwards to find all overlapping files. +void Version::GetOverlappingInputsBinarySearch( + int level, + const Slice& user_begin, + const Slice& user_end, + std::vector* inputs, + int hint_index, + int* file_index) { + assert(level > 0); + int min = 0; + int mid = 0; + int max = files_[level].size() -1; + bool foundOverlap = false; + const Comparator* user_cmp = vset_->icmp_.user_comparator(); + + // if the caller already knows the index of a file that has overlap, + // then we can skip the binary search. + if (hint_index != -1) { + mid = hint_index; + foundOverlap = true; + } + + while (!foundOverlap && min <= max) { + mid = (min + max)/2; + FileMetaData* f = files_[level][mid]; + const Slice file_start = f->smallest.user_key(); + const Slice file_limit = f->largest.user_key(); + if (user_cmp->Compare(file_limit, user_begin) < 0) { + min = mid + 1; + } else if (user_cmp->Compare(user_end, file_start) < 0) { + max = mid - 1; + } else { + foundOverlap = true; + break; + } + } + + // If there were no overlapping files, return immediately. + if (!foundOverlap) { + return; + } + // returns the index where an overlap is found + if (file_index) { + *file_index = mid; + } + ExtendOverlappingInputs(level, user_begin, user_end, inputs, mid); +} + +// Store in "*inputs" all files in "level" that overlap [begin,end] +// The midIndex specifies the index of at least one file that +// overlaps the specified range. From that file, iterate backward +// and forward to find all overlapping files. +void Version::ExtendOverlappingInputs( + int level, + const Slice& user_begin, + const Slice& user_end, + std::vector* inputs, + int midIndex) { + + const Comparator* user_cmp = vset_->icmp_.user_comparator(); +#ifndef NDEBUG + { + // assert that the file at midIndex overlaps with the range + assert(midIndex < files_[level].size()); + FileMetaData* f = files_[level][midIndex]; + const Slice fstart = f->smallest.user_key(); + const Slice flimit = f->largest.user_key(); + if (user_cmp->Compare(fstart, user_begin) >= 0) { + assert(user_cmp->Compare(fstart, user_end) <= 0); + } else { + assert(user_cmp->Compare(flimit, user_begin) >= 0); + } + } +#endif + int startIndex = midIndex + 1; + int endIndex = midIndex; + int count __attribute__((unused)) = 0; + + // check backwards from 'mid' to lower indices + for (int i = midIndex; i >= 0 ; i--) { + FileMetaData* f = files_[level][i]; + const Slice file_limit = f->largest.user_key(); + if (user_cmp->Compare(file_limit, user_begin) >= 0) { + startIndex = i; + assert((count++, true)); + } else { + break; + } + } + // check forward from 'mid+1' to higher indices + for (unsigned int i = midIndex+1; i < files_[level].size(); i++) { + FileMetaData* f = files_[level][i]; + const Slice file_start = f->smallest.user_key(); + if (user_cmp->Compare(file_start, user_end) <= 0) { + assert((count++, true)); + endIndex = i; + } else { + break; + } + } + assert(count == endIndex - startIndex + 1); + + // insert overlapping files into vector + for (int i = startIndex; i <= endIndex; i++) { + FileMetaData* f = files_[level][i]; + inputs->push_back(f); + } +} + +std::string Version::DebugString(bool hex) const { + std::string r; + for (int level = 0; level < vset_->NumberLevels(); level++) { + // E.g., + // --- level 1 --- + // 17:123['a' .. 'd'] + // 20:43['e' .. 'g'] + r.append("--- level "); + AppendNumberTo(&r, level); + r.append(" --- version# "); + AppendNumberTo(&r, version_number_); + r.append(" ---\n"); + const std::vector& files = files_[level]; + for (size_t i = 0; i < files.size(); i++) { + r.push_back(' '); + AppendNumberTo(&r, files[i]->number); + r.push_back(':'); + AppendNumberTo(&r, files[i]->file_size); + r.append("["); + r.append(files[i]->smallest.DebugString(hex)); + r.append(" .. "); + r.append(files[i]->largest.DebugString(hex)); + r.append("]\n"); + } + } + return r; +} + +// this is used to batch writes to the manifest file +struct VersionSet::ManifestWriter { + Status status; + bool done; + port::CondVar cv; + VersionEdit* edit; + + explicit ManifestWriter(port::Mutex* mu, VersionEdit* e) : + done(false), cv(mu), edit(e) {} +}; + +// A helper class so we can efficiently apply a whole sequence +// of edits to a particular state without creating intermediate +// Versions that contain full copies of the intermediate state. +class VersionSet::Builder { + private: + // Helper to sort by v->files_[file_number].smallest + struct BySmallestKey { + const InternalKeyComparator* internal_comparator; + + bool operator()(FileMetaData* f1, FileMetaData* f2) const { + int r = internal_comparator->Compare(f1->smallest, f2->smallest); + if (r != 0) { + return (r < 0); + } else { + // Break ties by file number + return (f1->number < f2->number); + } + } + }; + + typedef std::set FileSet; + struct LevelState { + std::set deleted_files; + FileSet* added_files; + }; + + VersionSet* vset_; + Version* base_; + LevelState* levels_; + + public: + // Initialize a builder with the files from *base and other info from *vset + Builder(VersionSet* vset, Version* base) + : vset_(vset), + base_(base) { + base_->Ref(); + levels_ = new LevelState[vset_->NumberLevels()]; + BySmallestKey cmp; + cmp.internal_comparator = &vset_->icmp_; + for (int level = 0; level < vset_->NumberLevels(); level++) { + levels_[level].added_files = new FileSet(cmp); + } + } + + ~Builder() { + for (int level = 0; level < vset_->NumberLevels(); level++) { + const FileSet* added = levels_[level].added_files; + std::vector to_unref; + to_unref.reserve(added->size()); + for (FileSet::const_iterator it = added->begin(); + it != added->end(); ++it) { + to_unref.push_back(*it); + } + delete added; + for (uint32_t i = 0; i < to_unref.size(); i++) { + FileMetaData* f = to_unref[i]; + f->refs--; + if (f->refs <= 0) { + delete f; + } + } + } + delete[] levels_; + base_->Unref(); + } + + void CheckConsistency(Version* v) { +#ifndef NDEBUG + for (int level = 0; level < vset_->NumberLevels(); level++) { + // Make sure there is no overlap in levels > 0 + if (level > 0) { + for (uint32_t i = 1; i < v->files_[level].size(); i++) { + const InternalKey& prev_end = v->files_[level][i-1]->largest; + const InternalKey& this_begin = v->files_[level][i]->smallest; + if (vset_->icmp_.Compare(prev_end, this_begin) >= 0) { + fprintf(stderr, "overlapping ranges in same level %s vs. %s\n", + prev_end.DebugString().c_str(), + this_begin.DebugString().c_str()); + abort(); + } + } + } + } +#endif + } + + void CheckConsistencyForDeletes(VersionEdit* edit, int number, int level) { +#ifndef NDEBUG + // a file to be deleted better exist in the previous version + bool found = false; + for (int l = 0; !found && l < edit->number_levels_; l++) { + const std::vector& base_files = base_->files_[l]; + for (int i = 0; i < base_files.size(); i++) { + FileMetaData* f = base_files[i]; + if (f->number == number) { + found = true; + break; + } + } + } + // if the file did not exist in the previous version, then it + // is possibly moved from lower level to higher level in current + // version + for (int l = level+1; !found && l < edit->number_levels_; l++) { + const FileSet* added = levels_[l].added_files; + for (FileSet::const_iterator added_iter = added->begin(); + added_iter != added->end(); ++added_iter) { + FileMetaData* f = *added_iter; + if (f->number == number) { + found = true; + break; + } + } + } + + // maybe this file was added in a previous edit that was Applied + if (!found) { + const FileSet* added = levels_[level].added_files; + for (FileSet::const_iterator added_iter = added->begin(); + added_iter != added->end(); ++added_iter) { + FileMetaData* f = *added_iter; + if (f->number == number) { + found = true; + break; + } + } + } + assert(found); +#endif + } + + // Apply all of the edits in *edit to the current state. + void Apply(VersionEdit* edit) { + CheckConsistency(base_); + + // Update compaction pointers + for (size_t i = 0; i < edit->compact_pointers_.size(); i++) { + const int level = edit->compact_pointers_[i].first; + vset_->compact_pointer_[level] = + edit->compact_pointers_[i].second.Encode().ToString(); + } + + // Delete files + const VersionEdit::DeletedFileSet& del = edit->deleted_files_; + for (VersionEdit::DeletedFileSet::const_iterator iter = del.begin(); + iter != del.end(); + ++iter) { + const int level = iter->first; + const uint64_t number = iter->second; + levels_[level].deleted_files.insert(number); + CheckConsistencyForDeletes(edit, number, level); + } + + // Add new files + for (size_t i = 0; i < edit->new_files_.size(); i++) { + const int level = edit->new_files_[i].first; + FileMetaData* f = new FileMetaData(edit->new_files_[i].second); + f->refs = 1; + + // We arrange to automatically compact this file after + // a certain number of seeks. Let's assume: + // (1) One seek costs 10ms + // (2) Writing or reading 1MB costs 10ms (100MB/s) + // (3) A compaction of 1MB does 25MB of IO: + // 1MB read from this level + // 10-12MB read from next level (boundaries may be misaligned) + // 10-12MB written to next level + // This implies that 25 seeks cost the same as the compaction + // of 1MB of data. I.e., one seek costs approximately the + // same as the compaction of 40KB of data. We are a little + // conservative and allow approximately one seek for every 16KB + // of data before triggering a compaction. + f->allowed_seeks = (f->file_size / 16384); + if (f->allowed_seeks < 100) f->allowed_seeks = 100; + + levels_[level].deleted_files.erase(f->number); + levels_[level].added_files->insert(f); + } + } + + // Save the current state in *v. + void SaveTo(Version* v) { + CheckConsistency(base_); + CheckConsistency(v); + BySmallestKey cmp; + cmp.internal_comparator = &vset_->icmp_; + for (int level = 0; level < vset_->NumberLevels(); level++) { + // Merge the set of added files with the set of pre-existing files. + // Drop any deleted files. Store the result in *v. + const std::vector& base_files = base_->files_[level]; + std::vector::const_iterator base_iter = base_files.begin(); + std::vector::const_iterator base_end = base_files.end(); + const FileSet* added = levels_[level].added_files; + v->files_[level].reserve(base_files.size() + added->size()); + for (FileSet::const_iterator added_iter = added->begin(); + added_iter != added->end(); + ++added_iter) { + // Add all smaller files listed in base_ + for (std::vector::const_iterator bpos + = std::upper_bound(base_iter, base_end, *added_iter, cmp); + base_iter != bpos; + ++base_iter) { + MaybeAddFile(v, level, *base_iter); + } + + MaybeAddFile(v, level, *added_iter); + } + + // Add remaining base files + for (; base_iter != base_end; ++base_iter) { + MaybeAddFile(v, level, *base_iter); + } + } + CheckConsistency(v); + } + + void MaybeAddFile(Version* v, int level, FileMetaData* f) { + if (levels_[level].deleted_files.count(f->number) > 0) { + // File is deleted: do nothing + } else { + std::vector* files = &v->files_[level]; + if (level > 0 && !files->empty()) { + // Must not overlap + assert(vset_->icmp_.Compare((*files)[files->size()-1]->largest, + f->smallest) < 0); + } + f->refs++; + files->push_back(f); + } + } +}; + +VersionSet::VersionSet(const std::string& dbname, + const Options* options, + TableCache* table_cache, + const InternalKeyComparator* cmp) + : env_(options->env), + dbname_(dbname), + options_(options), + table_cache_(table_cache), + icmp_(*cmp), + next_file_number_(2), + manifest_file_number_(0), // Filled by Recover() + last_sequence_(0), + log_number_(0), + prev_log_number_(0), + num_levels_(options_->num_levels), + dummy_versions_(this), + current_(nullptr), + compactions_in_progress_(options_->num_levels), + current_version_number_(0), + last_observed_manifest_size_(0) { + compact_pointer_ = new std::string[options_->num_levels]; + Init(options_->num_levels); + AppendVersion(new Version(this, current_version_number_++)); +} + +VersionSet::~VersionSet() { + current_->Unref(); + assert(dummy_versions_.next_ == &dummy_versions_); // List must be empty + delete[] compact_pointer_; + delete[] max_file_size_; + delete[] level_max_bytes_; +} + +void VersionSet::Init(int num_levels) { + max_file_size_ = new uint64_t[num_levels]; + level_max_bytes_ = new uint64_t[num_levels]; + int target_file_size_multiplier = options_->target_file_size_multiplier; + int max_bytes_multiplier = options_->max_bytes_for_level_multiplier; + for (int i = 0; i < num_levels; i++) { + if (i > 1) { + max_file_size_[i] = max_file_size_[i-1] * target_file_size_multiplier; + level_max_bytes_[i] = level_max_bytes_[i-1] * max_bytes_multiplier; + } else { + max_file_size_[i] = options_->target_file_size_base; + level_max_bytes_[i] = options_->max_bytes_for_level_base; + } + } +} + +void VersionSet::AppendVersion(Version* v) { + // Make "v" current + assert(v->refs_ == 0); + assert(v != current_); + if (current_ != nullptr) { + assert(current_->refs_ > 0); + current_->Unref(); + } + current_ = v; + v->Ref(); + + // Append to linked list + v->prev_ = dummy_versions_.prev_; + v->next_ = &dummy_versions_; + v->prev_->next_ = v; + v->next_->prev_ = v; +} + +Status VersionSet::LogAndApply(VersionEdit* edit, port::Mutex* mu, + bool new_descriptor_log) { + mu->AssertHeld(); + + // queue our request + ManifestWriter w(mu, edit); + manifest_writers_.push_back(&w); + while (!w.done && &w != manifest_writers_.front()) { + w.cv.Wait(); + } + if (w.done) { + return w.status; + } + + std::vector batch_edits; + Version* v = new Version(this, current_version_number_++); + Builder builder(this, current_); + + // process all requests in the queue + ManifestWriter* last_writer = &w; + assert(!manifest_writers_.empty()); + assert(manifest_writers_.front() == &w); + std::deque::iterator iter = manifest_writers_.begin(); + for (; iter != manifest_writers_.end(); ++iter) { + last_writer = *iter; + LogAndApplyHelper(&builder, v, last_writer->edit, mu); + batch_edits.push_back(last_writer->edit); + } + builder.SaveTo(v); + + // Initialize new descriptor log file if necessary by creating + // a temporary file that contains a snapshot of the current version. + std::string new_manifest_file; + uint64_t new_manifest_file_size = 0; + Status s; + + // No need to perform this check if a new Manifest is being created anyways. + if (!descriptor_log_ || + last_observed_manifest_size_ > options_->max_manifest_file_size) { + new_descriptor_log = true; + manifest_file_number_ = NewFileNumber(); // Change manifest file no. + } + + if (!descriptor_log_ || new_descriptor_log) { + // No reason to unlock *mu here since we only hit this path in the + // first call to LogAndApply (when opening the database). + assert(!descriptor_log_ || new_descriptor_log); + new_manifest_file = DescriptorFileName(dbname_, manifest_file_number_); + edit->SetNextFile(next_file_number_); + unique_ptr descriptor_file; + s = env_->NewWritableFile(new_manifest_file, &descriptor_file); + if (s.ok()) { + descriptor_log_.reset(new log::Writer(std::move(descriptor_file))); + s = WriteSnapshot(descriptor_log_.get()); + } + } + + // Unlock during expensive MANIFEST log write. New writes cannot get here + // because &w is ensuring that all new writes get queued. + { + mu->Unlock(); + + // The calles to Finalize and UpdateFilesBySize are cpu-heavy + // and is best called outside the mutex. + Finalize(v); + UpdateFilesBySize(v); + + // Write new record to MANIFEST log + if (s.ok()) { + std::string record; + for (unsigned int i = 0; i < batch_edits.size(); i++) { + batch_edits[i]->EncodeTo(&record); + s = descriptor_log_->AddRecord(record); + if (!s.ok()) { + break; + } + } + if (s.ok()) { + if (options_->use_fsync) { + s = descriptor_log_->file()->Fsync(); + } else { + s = descriptor_log_->file()->Sync(); + } + } + if (!s.ok()) { + Log(options_->info_log, "MANIFEST write: %s\n", s.ToString().c_str()); + if (ManifestContains(record)) { + Log(options_->info_log, + "MANIFEST contains log record despite error; advancing to new " + "version to prevent mismatch between in-memory and logged state" + " If paranoid is set, then the db is now in readonly mode."); + s = Status::OK(); + } + } + } + + // If we just created a new descriptor file, install it by writing a + // new CURRENT file that points to it. + if (s.ok() && !new_manifest_file.empty()) { + s = SetCurrentFile(env_, dbname_, manifest_file_number_); + } + + // find offset in manifest file where this version is stored. + new_manifest_file_size = descriptor_log_->file()->GetFileSize(); + + mu->Lock(); + // cache the manifest_file_size so that it can be used to rollover in the + // next call to LogAndApply + last_observed_manifest_size_ = new_manifest_file_size; + } + + // Install the new version + if (s.ok()) { + v->offset_manifest_file_ = new_manifest_file_size; + AppendVersion(v); + log_number_ = edit->log_number_; + prev_log_number_ = edit->prev_log_number_; + + } else { + Log(options_->info_log, "Error in committing version %ld", + v->GetVersionNumber()); + delete v; + if (!new_manifest_file.empty()) { + descriptor_log_.reset(); + env_->DeleteFile(new_manifest_file); + } + } + + // wake up all the waiting writers + while (true) { + ManifestWriter* ready = manifest_writers_.front(); + manifest_writers_.pop_front(); + if (ready != &w) { + ready->status = s; + ready->done = true; + ready->cv.Signal(); + } + if (ready == last_writer) break; + } + // Notify new head of write queue + if (!manifest_writers_.empty()) { + manifest_writers_.front()->cv.Signal(); + } + return s; +} + +void VersionSet::LogAndApplyHelper(Builder* builder, Version* v, + VersionEdit* edit, port::Mutex* mu) { + mu->AssertHeld(); + + if (edit->has_log_number_) { + assert(edit->log_number_ >= log_number_); + assert(edit->log_number_ < next_file_number_); + } else { + edit->SetLogNumber(log_number_); + } + + if (!edit->has_prev_log_number_) { + edit->SetPrevLogNumber(prev_log_number_); + } + + edit->SetNextFile(next_file_number_); + edit->SetLastSequence(last_sequence_); + + builder->Apply(edit); +} + +Status VersionSet::Recover() { + struct LogReporter : public log::Reader::Reporter { + Status* status; + virtual void Corruption(size_t bytes, const Status& s) { + if (this->status->ok()) *this->status = s; + } + }; + + // Read "CURRENT" file, which contains a pointer to the current manifest file + std::string current; + Status s = ReadFileToString(env_, CurrentFileName(dbname_), ¤t); + if (!s.ok()) { + return s; + } + if (current.empty() || current[current.size()-1] != '\n') { + return Status::Corruption("CURRENT file does not end with newline"); + } + current.resize(current.size() - 1); + + Log(options_->info_log, "Recovering from manifest file:%s\n", + current.c_str()); + + std::string dscname = dbname_ + "/" + current; + unique_ptr file; + s = env_->NewSequentialFile(dscname, &file); + if (!s.ok()) { + return s; + } + uint64_t manifest_file_size; + s = env_->GetFileSize(dscname, &manifest_file_size); + if (!s.ok()) { + return s; + } + + bool have_log_number = false; + bool have_prev_log_number = false; + bool have_next_file = false; + bool have_last_sequence = false; + uint64_t next_file = 0; + uint64_t last_sequence = 0; + uint64_t log_number = 0; + uint64_t prev_log_number = 0; + Builder builder(this, current_); + + { + LogReporter reporter; + reporter.status = &s; + log::Reader reader(std::move(file), &reporter, true/*checksum*/, + 0/*initial_offset*/); + Slice record; + std::string scratch; + while (reader.ReadRecord(&record, &scratch) && s.ok()) { + VersionEdit edit(NumberLevels()); + s = edit.DecodeFrom(record); + if (s.ok()) { + if (edit.has_comparator_ && + edit.comparator_ != icmp_.user_comparator()->Name()) { + s = Status::InvalidArgument( + edit.comparator_ + "does not match existing comparator ", + icmp_.user_comparator()->Name()); + } + } + + if (s.ok()) { + builder.Apply(&edit); + } + + if (edit.has_log_number_) { + log_number = edit.log_number_; + have_log_number = true; + } + + if (edit.has_prev_log_number_) { + prev_log_number = edit.prev_log_number_; + have_prev_log_number = true; + } + + if (edit.has_next_file_number_) { + next_file = edit.next_file_number_; + have_next_file = true; + } + + if (edit.has_last_sequence_) { + last_sequence = edit.last_sequence_; + have_last_sequence = true; + } + } + } + file.reset(); + + if (s.ok()) { + if (!have_next_file) { + s = Status::Corruption("no meta-nextfile entry in descriptor"); + } else if (!have_log_number) { + s = Status::Corruption("no meta-lognumber entry in descriptor"); + } else if (!have_last_sequence) { + s = Status::Corruption("no last-sequence-number entry in descriptor"); + } + + if (!have_prev_log_number) { + prev_log_number = 0; + } + + MarkFileNumberUsed(prev_log_number); + MarkFileNumberUsed(log_number); + } + + if (s.ok()) { + Version* v = new Version(this, current_version_number_++); + builder.SaveTo(v); + // Install recovered version + Finalize(v); + v->offset_manifest_file_ = manifest_file_size; + AppendVersion(v); + manifest_file_number_ = next_file; + next_file_number_ = next_file + 1; + last_sequence_ = last_sequence; + log_number_ = log_number; + prev_log_number_ = prev_log_number; + + Log(options_->info_log, "Recovered from manifest file:%s succeeded," + "manifest_file_number is %ld, next_file_number is %ld, " + "last_sequence is %ld, log_number is %ld," + "prev_log_number is %ld\n", + current.c_str(), manifest_file_number_, next_file_number_, + last_sequence_, log_number_, prev_log_number_); + } + + return s; +} + +Status VersionSet::DumpManifest(Options& options, std::string& dscname, + bool verbose, bool hex) { + struct LogReporter : public log::Reader::Reporter { + Status* status; + virtual void Corruption(size_t bytes, const Status& s) { + if (this->status->ok()) *this->status = s; + } + }; + + // Open the specified manifest file. + unique_ptr file; + Status s = options.env->NewSequentialFile(dscname, &file); + if (!s.ok()) { + return s; + } + + bool have_log_number = false; + bool have_prev_log_number = false; + bool have_next_file = false; + bool have_last_sequence = false; + uint64_t next_file = 0; + uint64_t last_sequence = 0; + uint64_t log_number = 0; + uint64_t prev_log_number = 0; + int count = 0; + VersionSet::Builder builder(this, current_); + + { + LogReporter reporter; + reporter.status = &s; + log::Reader reader(std::move(file), &reporter, true/*checksum*/, + 0/*initial_offset*/); + Slice record; + std::string scratch; + while (reader.ReadRecord(&record, &scratch) && s.ok()) { + VersionEdit edit(NumberLevels()); + s = edit.DecodeFrom(record); + if (s.ok()) { + if (edit.has_comparator_ && + edit.comparator_ != icmp_.user_comparator()->Name()) { + s = Status::InvalidArgument( + edit.comparator_ + "does not match existing comparator ", + icmp_.user_comparator()->Name()); + } + } + + // Write out each individual edit + if (verbose) { + printf("*************************Edit[%d] = %s\n", + count, edit.DebugString().c_str()); + } + count++; + + if (s.ok()) { + builder.Apply(&edit); + } + + if (edit.has_log_number_) { + log_number = edit.log_number_; + have_log_number = true; + } + + if (edit.has_prev_log_number_) { + prev_log_number = edit.prev_log_number_; + have_prev_log_number = true; + } + + if (edit.has_next_file_number_) { + next_file = edit.next_file_number_; + have_next_file = true; + } + + if (edit.has_last_sequence_) { + last_sequence = edit.last_sequence_; + have_last_sequence = true; + } + } + } + file.reset(); + + if (s.ok()) { + if (!have_next_file) { + s = Status::Corruption("no meta-nextfile entry in descriptor"); + printf("no meta-nextfile entry in descriptor"); + } else if (!have_log_number) { + s = Status::Corruption("no meta-lognumber entry in descriptor"); + printf("no meta-lognumber entry in descriptor"); + } else if (!have_last_sequence) { + printf("no last-sequence-number entry in descriptor"); + s = Status::Corruption("no last-sequence-number entry in descriptor"); + } + + if (!have_prev_log_number) { + prev_log_number = 0; + } + + MarkFileNumberUsed(prev_log_number); + MarkFileNumberUsed(log_number); + } + + if (s.ok()) { + Version* v = new Version(this, 0); + builder.SaveTo(v); + // Install recovered version + Finalize(v); + AppendVersion(v); + manifest_file_number_ = next_file; + next_file_number_ = next_file + 1; + last_sequence_ = last_sequence; + log_number_ = log_number; + prev_log_number_ = prev_log_number; + + printf("manifest_file_number %ld next_file_number %ld last_sequence %ld log_number %ld prev_log_number %ld\n", + manifest_file_number_, next_file_number_, + last_sequence, log_number, prev_log_number); + printf("%s \n", v->DebugString(hex).c_str()); + } + + return s; +} + +void VersionSet::MarkFileNumberUsed(uint64_t number) { + if (next_file_number_ <= number) { + next_file_number_ = number + 1; + } +} + +void VersionSet::Finalize(Version* v) { + + double max_score = 0; + int max_score_level = 0; + + for (int level = 0; level < NumberLevels()-1; level++) { + double score; + if (level == 0) { + // We treat level-0 specially by bounding the number of files + // instead of number of bytes for two reasons: + // + // (1) With larger write-buffer sizes, it is nice not to do too + // many level-0 compactions. + // + // (2) The files in level-0 are merged on every read and + // therefore we wish to avoid too many files when the individual + // file size is small (perhaps because of a small write-buffer + // setting, or very high compression ratios, or lots of + // overwrites/deletions). + int numfiles = 0; + for (unsigned int i = 0; i < v->files_[level].size(); i++) { + if (!v->files_[level][i]->being_compacted) { + numfiles++; + } + } + + // If we are slowing down writes, then we better compact that first + if (numfiles >= options_->level0_stop_writes_trigger) { + score = 1000000; + // Log(options_->info_log, "XXX score l0 = 1000000000 max"); + } else if (numfiles >= options_->level0_slowdown_writes_trigger) { + score = 10000; + // Log(options_->info_log, "XXX score l0 = 1000000 medium"); + } else { + score = numfiles / + static_cast(options_->level0_file_num_compaction_trigger); + if (score >= 1) { + // Log(options_->info_log, "XXX score l0 = %d least", (int)score); + } + } + } else { + // Compute the ratio of current size to size limit. + const uint64_t level_bytes = TotalFileSize(v->files_[level]) - + SizeBeingCompacted(level); + score = static_cast(level_bytes) / MaxBytesForLevel(level); + if (score > 1) { + // Log(options_->info_log, "XXX score l%d = %d ", level, (int)score); + } + if (max_score < score) { + max_score = score; + max_score_level = level; + } + } + v->compaction_level_[level] = level; + v->compaction_score_[level] = score; + } + + // update the max compaction score in levels 1 to n-1 + v->max_compaction_score_ = max_score; + v->max_compaction_score_level_ = max_score_level; + + // sort all the levels based on their score. Higher scores get listed + // first. Use bubble sort because the number of entries are small. + for(int i = 0; i < NumberLevels()-2; i++) { + for (int j = i+1; j < NumberLevels()-1; j++) { + if (v->compaction_score_[i] < v->compaction_score_[j]) { + double score = v->compaction_score_[i]; + int level = v->compaction_level_[i]; + v->compaction_score_[i] = v->compaction_score_[j]; + v->compaction_level_[i] = v->compaction_level_[j]; + v->compaction_score_[j] = score; + v->compaction_level_[j] = level; + } + } + } +} + +// a static compator used to sort files based on their size +static bool compareSize(const VersionSet::Fsize& first, + const VersionSet::Fsize& second) { + return (first.file->file_size > second.file->file_size); +} + +// sort all files in level1 to level(n-1) based on file size +void VersionSet::UpdateFilesBySize(Version* v) { + + // No need to sort the highest level because it is never compacted. + for (int level = 0; level < NumberLevels()-1; level++) { + + const std::vector& files = v->files_[level]; + std::vector& files_by_size = v->files_by_size_[level]; + assert(files_by_size.size() == 0); + + // populate a temp vector for sorting based on size + std::vector temp(files.size()); + for (unsigned int i = 0; i < files.size(); i++) { + temp[i].index = i; + temp[i].file = files[i]; + } + + // sort the top number_of_files_to_sort_ based on file size + int num = Version::number_of_files_to_sort_; + if (num > (int)temp.size()) { + num = temp.size(); + } + std::partial_sort(temp.begin(), temp.begin() + num, + temp.end(), compareSize); + assert(temp.size() == files.size()); + + // initialize files_by_size_ + for (unsigned int i = 0; i < temp.size(); i++) { + files_by_size.push_back(temp[i].index); + } + v->next_file_to_compact_by_size_[level] = 0; + assert(v->files_[level].size() == v->files_by_size_[level].size()); + } +} + +Status VersionSet::WriteSnapshot(log::Writer* log) { + // TODO: Break up into multiple records to reduce memory usage on recovery? + + // Save metadata + VersionEdit edit(NumberLevels()); + edit.SetComparatorName(icmp_.user_comparator()->Name()); + + // Save compaction pointers + for (int level = 0; level < NumberLevels(); level++) { + if (!compact_pointer_[level].empty()) { + InternalKey key; + key.DecodeFrom(compact_pointer_[level]); + edit.SetCompactPointer(level, key); + } + } + + // Save files + for (int level = 0; level < NumberLevels(); level++) { + const std::vector& files = current_->files_[level]; + for (size_t i = 0; i < files.size(); i++) { + const FileMetaData* f = files[i]; + edit.AddFile(level, f->number, f->file_size, f->smallest, f->largest); + } + } + + std::string record; + edit.EncodeTo(&record); + return log->AddRecord(record); +} + +int VersionSet::NumLevelFiles(int level) const { + assert(level >= 0); + assert(level < NumberLevels()); + return current_->files_[level].size(); +} + +const char* VersionSet::LevelSummary(LevelSummaryStorage* scratch) const { + int len = snprintf(scratch->buffer, sizeof(scratch->buffer), "files["); + for (int i = 0; i < NumberLevels(); i++) { + int sz = sizeof(scratch->buffer) - len; + int ret = snprintf(scratch->buffer + len, sz, "%d ", + int(current_->files_[i].size())); + if (ret < 0 || ret >= sz) + break; + len += ret; + } + snprintf(scratch->buffer + len, sizeof(scratch->buffer) - len, "]"); + return scratch->buffer; +} + +const char* VersionSet::LevelDataSizeSummary( + LevelSummaryStorage* scratch) const { + int len = snprintf(scratch->buffer, sizeof(scratch->buffer), "files_size["); + for (int i = 0; i < NumberLevels(); i++) { + int sz = sizeof(scratch->buffer) - len; + int ret = snprintf(scratch->buffer + len, sz, "%ld ", + NumLevelBytes(i)); + if (ret < 0 || ret >= sz) + break; + len += ret; + } + snprintf(scratch->buffer + len, sizeof(scratch->buffer) - len, "]"); + return scratch->buffer; +} + +// Opens the mainfest file and reads all records +// till it finds the record we are looking for. +bool VersionSet::ManifestContains(const std::string& record) const { + std::string fname = DescriptorFileName(dbname_, manifest_file_number_); + Log(options_->info_log, "ManifestContains: checking %s\n", fname.c_str()); + unique_ptr file; + Status s = env_->NewSequentialFile(fname, &file); + if (!s.ok()) { + Log(options_->info_log, "ManifestContains: %s\n", s.ToString().c_str()); + Log(options_->info_log, + "ManifestContains: is unable to reopen the manifest file %s", + fname.c_str()); + return false; + } + log::Reader reader(std::move(file), nullptr, true/*checksum*/, 0); + Slice r; + std::string scratch; + bool result = false; + while (reader.ReadRecord(&r, &scratch)) { + if (r == Slice(record)) { + result = true; + break; + } + } + Log(options_->info_log, "ManifestContains: result = %d\n", result ? 1 : 0); + return result; +} + + +uint64_t VersionSet::ApproximateOffsetOf(Version* v, const InternalKey& ikey) { + uint64_t result = 0; + for (int level = 0; level < NumberLevels(); level++) { + const std::vector& files = v->files_[level]; + for (size_t i = 0; i < files.size(); i++) { + if (icmp_.Compare(files[i]->largest, ikey) <= 0) { + // Entire file is before "ikey", so just add the file size + result += files[i]->file_size; + } else if (icmp_.Compare(files[i]->smallest, ikey) > 0) { + // Entire file is after "ikey", so ignore + if (level > 0) { + // Files other than level 0 are sorted by meta->smallest, so + // no further files in this level will contain data for + // "ikey". + break; + } + } else { + // "ikey" falls in the range for this table. Add the + // approximate offset of "ikey" within the table. + Table* tableptr; + Iterator* iter = table_cache_->NewIterator( + ReadOptions(), files[i]->number, files[i]->file_size, &tableptr); + if (tableptr != nullptr) { + result += tableptr->ApproximateOffsetOf(ikey.Encode()); + } + delete iter; + } + } + } + return result; +} + +void VersionSet::AddLiveFiles(std::set* live) { + for (Version* v = dummy_versions_.next_; + v != &dummy_versions_; + v = v->next_) { + for (int level = 0; level < NumberLevels(); level++) { + const std::vector& files = v->files_[level]; + for (size_t i = 0; i < files.size(); i++) { + live->insert(files[i]->number); + } + } + } +} + +void VersionSet::AddLiveFilesCurrentVersion(std::set* live) { + Version* v = current_; + for (int level = 0; level < NumberLevels(); level++) { + const std::vector& files = v->files_[level]; + for (size_t i = 0; i < files.size(); i++) { + live->insert(files[i]->number); + } + } +} + +int64_t VersionSet::NumLevelBytes(int level) const { + assert(level >= 0); + assert(level < NumberLevels()); + if(current_ && level < (int)current_->files_->size()) + return TotalFileSize(current_->files_[level]); + else + return 0; +} + +int64_t VersionSet::MaxNextLevelOverlappingBytes() { + int64_t result = 0; + std::vector overlaps; + for (int level = 1; level < NumberLevels() - 1; level++) { + for (size_t i = 0; i < current_->files_[level].size(); i++) { + const FileMetaData* f = current_->files_[level][i]; + current_->GetOverlappingInputs(level+1, &f->smallest, &f->largest, + &overlaps); + const int64_t sum = TotalFileSize(overlaps); + if (sum > result) { + result = sum; + } + } + } + return result; +} + +// Stores the minimal range that covers all entries in inputs in +// *smallest, *largest. +// REQUIRES: inputs is not empty +void VersionSet::GetRange(const std::vector& inputs, + InternalKey* smallest, + InternalKey* largest) { + assert(!inputs.empty()); + smallest->Clear(); + largest->Clear(); + for (size_t i = 0; i < inputs.size(); i++) { + FileMetaData* f = inputs[i]; + if (i == 0) { + *smallest = f->smallest; + *largest = f->largest; + } else { + if (icmp_.Compare(f->smallest, *smallest) < 0) { + *smallest = f->smallest; + } + if (icmp_.Compare(f->largest, *largest) > 0) { + *largest = f->largest; + } + } + } +} + +// Stores the minimal range that covers all entries in inputs1 and inputs2 +// in *smallest, *largest. +// REQUIRES: inputs is not empty +void VersionSet::GetRange2(const std::vector& inputs1, + const std::vector& inputs2, + InternalKey* smallest, + InternalKey* largest) { + std::vector all = inputs1; + all.insert(all.end(), inputs2.begin(), inputs2.end()); + GetRange(all, smallest, largest); +} + +Iterator* VersionSet::MakeInputIterator(Compaction* c) { + ReadOptions options; + options.verify_checksums = options_->paranoid_checks; + options.fill_cache = false; + + // Level-0 files have to be merged together. For other levels, + // we will make a concatenating iterator per level. + // TODO(opt): use concatenating iterator for level-0 if there is no overlap + const int space = (c->level() == 0 ? c->inputs_[0].size() + 1 : 2); + Iterator** list = new Iterator*[space]; + int num = 0; + for (int which = 0; which < 2; which++) { + if (!c->inputs_[which].empty()) { + if (c->level() + which == 0) { + const std::vector& files = c->inputs_[which]; + for (size_t i = 0; i < files.size(); i++) { + list[num++] = table_cache_->NewIterator( + options, files[i]->number, files[i]->file_size); + } + } else { + // Create concatenating iterator for the files from this level + list[num++] = NewTwoLevelIterator( + new Version::LevelFileNumIterator(icmp_, &c->inputs_[which]), + &GetFileIterator, table_cache_, options); + } + } + } + assert(num <= space); + Iterator* result = NewMergingIterator(&icmp_, list, num); + delete[] list; + return result; +} + +double VersionSet::MaxBytesForLevel(int level) { + // Note: the result for level zero is not really used since we set + // the level-0 compaction threshold based on number of files. + assert(level >= 0); + assert(level < NumberLevels()); + return level_max_bytes_[level]; +} + +uint64_t VersionSet::MaxFileSizeForLevel(int level) { + assert(level >= 0); + assert(level < NumberLevels()); + return max_file_size_[level]; +} + +int64_t VersionSet::ExpandedCompactionByteSizeLimit(int level) { + uint64_t result = MaxFileSizeForLevel(level); + result *= options_->expanded_compaction_factor; + return result; +} + +int64_t VersionSet::MaxGrandParentOverlapBytes(int level) { + uint64_t result = MaxFileSizeForLevel(level); + result *= options_->max_grandparent_overlap_factor; + return result; +} + +// verify that the files listed in this compaction are present +// in the current version +bool VersionSet::VerifyCompactionFileConsistency(Compaction* c) { +#ifndef NDEBUG + if (c->input_version_ != current_) { + Log(options_->info_log, "VerifyCompactionFileConsistency version mismatch"); + } + + // verify files in level + int level = c->level(); + for (int i = 0; i < c->num_input_files(0); i++) { + uint64_t number = c->input(0,i)->number; + + // look for this file in the current version + bool found = false; + for (unsigned int j = 0; j < current_->files_[level].size(); j++) { + FileMetaData* f = current_->files_[level][j]; + if (f->number == number) { + found = true; + break; + } + } + if (!found) { + return false; // input files non existant in current version + } + } + // verify level+1 files + level++; + for (int i = 0; i < c->num_input_files(1); i++) { + uint64_t number = c->input(1,i)->number; + + // look for this file in the current version + bool found = false; + for (unsigned int j = 0; j < current_->files_[level].size(); j++) { + FileMetaData* f = current_->files_[level][j]; + if (f->number == number) { + found = true; + break; + } + } + if (!found) { + return false; // input files non existant in current version + } + } +#endif + return true; // everything good +} + +// Clear all files to indicate that they are not being compacted +// Delete this compaction from the list of running compactions. +void VersionSet::ReleaseCompactionFiles(Compaction* c, Status status) { + c->MarkFilesBeingCompacted(false); + compactions_in_progress_[c->level()].erase(c); + if (!status.ok()) { + c->ResetNextCompactionIndex(); + } +} + +// The total size of files that are currently being compacted +uint64_t VersionSet::SizeBeingCompacted(int level) { + uint64_t total = 0; + for (std::set::iterator it = + compactions_in_progress_[level].begin(); + it != compactions_in_progress_[level].end(); + ++it) { + Compaction* c = (*it); + assert(c->level() == level); + for (int i = 0; i < c->num_input_files(0); i++) { + total += c->input(0,i)->file_size; + } + } + return total; +} + +Compaction* VersionSet::PickCompactionBySize(int level, double score) { + Compaction* c = nullptr; + + // level 0 files are overlapping. So we cannot pick more + // than one concurrent compactions at this level. This + // could be made better by looking at key-ranges that are + // being compacted at level 0. + if (level == 0 && compactions_in_progress_[level].size() == 1) { + return nullptr; + } + + assert(level >= 0); + assert(level+1 < NumberLevels()); + c = new Compaction(level, MaxFileSizeForLevel(level), + MaxGrandParentOverlapBytes(level), NumberLevels()); + c->score_ = score; + + // Pick the largest file in this level that is not already + // being compacted + std::vector& file_size = current_->files_by_size_[level]; + + // record the first file that is not yet compacted + int nextIndex = -1; + + for (unsigned int i = current_->next_file_to_compact_by_size_[level]; + i < file_size.size(); i++) { + int index = file_size[i]; + FileMetaData* f = current_->files_[level][index]; + + // check to verify files are arranged in descending size + assert((i == file_size.size() - 1) || + (i >= Version::number_of_files_to_sort_-1) || + (f->file_size >= current_->files_[level][file_size[i+1]]->file_size)); + + // do not pick a file to compact if it is being compacted + // from n-1 level. + if (f->being_compacted) { + continue; + } + + // remember the startIndex for the next call to PickCompaction + if (nextIndex == -1) { + nextIndex = i; + } + + //if (i > Version::number_of_files_to_sort_) { + // Log(options_->info_log, "XXX Looking at index %d", i); + //} + + // Do not pick this file if its parents at level+1 are being compacted. + // Maybe we can avoid redoing this work in SetupOtherInputs + int parent_index = -1; + if (ParentRangeInCompaction(&f->smallest, &f->largest, level, + &parent_index)) { + continue; + } + c->inputs_[0].push_back(f); + c->base_index_ = index; + c->parent_index_ = parent_index; + break; + } + + if (c->inputs_[0].empty()) { + delete c; + c = nullptr; + } + + // store where to start the iteration in the next call to PickCompaction + current_->next_file_to_compact_by_size_[level] = nextIndex; + + return c; +} + +Compaction* VersionSet::PickCompaction() { + Compaction* c = nullptr; + int level = -1; + + // compute the compactions needed. It is better to do it here + // and also in LogAndApply(), otherwise the values could be stale. + Finalize(current_); + + // We prefer compactions triggered by too much data in a level over + // the compactions triggered by seeks. + // + // Find the compactions by size on all levels. + for (int i = 0; i < NumberLevels()-1; i++) { + assert(i == 0 || current_->compaction_score_[i] <= + current_->compaction_score_[i-1]); + level = current_->compaction_level_[i]; + if ((current_->compaction_score_[i] >= 1)) { + c = PickCompactionBySize(level, current_->compaction_score_[i]); + if (c != nullptr) { + break; + } + } + } + + // Find compactions needed by seeks + if (c == nullptr && (current_->file_to_compact_ != nullptr)) { + level = current_->file_to_compact_level_; + + // Only allow one level 0 compaction at a time. + if (level != 0 || compactions_in_progress_[0].empty()) { + c = new Compaction(level, MaxFileSizeForLevel(level), + MaxGrandParentOverlapBytes(level), NumberLevels(), true); + c->inputs_[0].push_back(current_->file_to_compact_); + } + } + + if (c == nullptr) { + return nullptr; + } + + c->input_version_ = current_; + c->input_version_->Ref(); + + // Files in level 0 may overlap each other, so pick up all overlapping ones + // Two level 0 compaction won't run at the same time, so don't need to worry + // about files on level 0 being compacted. + if (level == 0) { + assert(compactions_in_progress_[0].empty()); + InternalKey smallest, largest; + GetRange(c->inputs_[0], &smallest, &largest); + // Note that the next call will discard the file we placed in + // c->inputs_[0] earlier and replace it with an overlapping set + // which will include the picked file. + c->inputs_[0].clear(); + current_->GetOverlappingInputs(0, &smallest, &largest, &c->inputs_[0]); + if (ParentRangeInCompaction(&smallest, &largest, + level, &c->parent_index_)) { + delete c; + return nullptr; + } + assert(!c->inputs_[0].empty()); + } + + SetupOtherInputs(c); + + // mark all the files that are being compacted + c->MarkFilesBeingCompacted(true); + + // remember this currently undergoing compaction + compactions_in_progress_[level].insert(c); + + return c; +} + +// Returns true if any one of the parent files are being compacted +bool VersionSet::ParentRangeInCompaction(const InternalKey* smallest, + const InternalKey* largest, int level, int* parent_index) { + std::vector inputs; + + current_->GetOverlappingInputs(level+1, smallest, largest, + &inputs, *parent_index, parent_index); + return FilesInCompaction(inputs); +} + +// Returns true if any one of specified files are being compacted +bool VersionSet::FilesInCompaction(std::vector& files) { + for (unsigned int i = 0; i < files.size(); i++) { + if (files[i]->being_compacted) { + return true; + } + } + return false; +} + +void VersionSet::SetupOtherInputs(Compaction* c) { + const int level = c->level(); + InternalKey smallest, largest; + GetRange(c->inputs_[0], &smallest, &largest); + + current_->GetOverlappingInputs(level+1, &smallest, &largest, &c->inputs_[1], + c->parent_index_, &c->parent_index_); + + // Get entire range covered by compaction + InternalKey all_start, all_limit; + GetRange2(c->inputs_[0], c->inputs_[1], &all_start, &all_limit); + + // See if we can grow the number of inputs in "level" without + // changing the number of "level+1" files we pick up. + if (!c->inputs_[1].empty()) { + std::vector expanded0; + current_->GetOverlappingInputs(level, &all_start, &all_limit, &expanded0, + c->base_index_, nullptr); + const int64_t inputs0_size = TotalFileSize(c->inputs_[0]); + const int64_t inputs1_size = TotalFileSize(c->inputs_[1]); + const int64_t expanded0_size = TotalFileSize(expanded0); + int64_t limit = ExpandedCompactionByteSizeLimit(level); + if (expanded0.size() > c->inputs_[0].size() && + inputs1_size + expanded0_size < limit && + !FilesInCompaction(expanded0)) { + InternalKey new_start, new_limit; + GetRange(expanded0, &new_start, &new_limit); + std::vector expanded1; + current_->GetOverlappingInputs(level+1, &new_start, &new_limit, + &expanded1, c->parent_index_, + &c->parent_index_); + if (expanded1.size() == c->inputs_[1].size() && + !FilesInCompaction(expanded1)) { + Log(options_->info_log, + "Expanding@%d %d+%d (%ld+%ld bytes) to %d+%d (%ld+%ld bytes)\n", + level, + int(c->inputs_[0].size()), + int(c->inputs_[1].size()), + long(inputs0_size), long(inputs1_size), + int(expanded0.size()), + int(expanded1.size()), + long(expanded0_size), long(inputs1_size)); + smallest = new_start; + largest = new_limit; + c->inputs_[0] = expanded0; + c->inputs_[1] = expanded1; + GetRange2(c->inputs_[0], c->inputs_[1], &all_start, &all_limit); + } + } + } + + // Compute the set of grandparent files that overlap this compaction + // (parent == level+1; grandparent == level+2) + if (level + 2 < NumberLevels()) { + current_->GetOverlappingInputs(level + 2, &all_start, &all_limit, + &c->grandparents_); + } + + if (false) { + Log(options_->info_log, "Compacting %d '%s' .. '%s'", + level, + smallest.DebugString().c_str(), + largest.DebugString().c_str()); + } + + // Update the place where we will do the next compaction for this level. + // We update this immediately instead of waiting for the VersionEdit + // to be applied so that if the compaction fails, we will try a different + // key range next time. + compact_pointer_[level] = largest.Encode().ToString(); + c->edit_->SetCompactPointer(level, largest); +} + +Compaction* VersionSet::CompactRange( + int level, + const InternalKey* begin, + const InternalKey* end) { + std::vector inputs; + current_->GetOverlappingInputs(level, begin, end, &inputs); + if (inputs.empty()) { + return nullptr; + } + + // Avoid compacting too much in one shot in case the range is large. + const uint64_t limit = MaxFileSizeForLevel(level) * + options_->source_compaction_factor; + uint64_t total = 0; + for (size_t i = 0; i < inputs.size(); i++) { + uint64_t s = inputs[i]->file_size; + total += s; + if (total >= limit) { + inputs.resize(i + 1); + break; + } + } + + Compaction* c = new Compaction(level, MaxFileSizeForLevel(level), + MaxGrandParentOverlapBytes(level), NumberLevels()); + c->input_version_ = current_; + c->input_version_->Ref(); + c->inputs_[0] = inputs; + SetupOtherInputs(c); + + // These files that are to be manaully compacted do not trample + // upon other files because manual compactions are processed when + // the system has a max of 1 background compaction thread. + c->MarkFilesBeingCompacted(true); + return c; +} + +Compaction::Compaction(int level, uint64_t target_file_size, + uint64_t max_grandparent_overlap_bytes, int number_levels, + bool seek_compaction) + : level_(level), + max_output_file_size_(target_file_size), + maxGrandParentOverlapBytes_(max_grandparent_overlap_bytes), + input_version_(nullptr), + number_levels_(number_levels), + seek_compaction_(seek_compaction), + grandparent_index_(0), + seen_key_(false), + overlapped_bytes_(0), + base_index_(-1), + parent_index_(-1), + score_(0) { + edit_ = new VersionEdit(number_levels_); + level_ptrs_ = new size_t[number_levels_]; + for (int i = 0; i < number_levels_; i++) { + level_ptrs_[i] = 0; + } +} + +Compaction::~Compaction() { + delete[] level_ptrs_; + delete edit_; + if (input_version_ != nullptr) { + input_version_->Unref(); + } +} + +bool Compaction::IsTrivialMove() const { + // Avoid a move if there is lots of overlapping grandparent data. + // Otherwise, the move could create a parent file that will require + // a very expensive merge later on. + return (num_input_files(0) == 1 && + num_input_files(1) == 0 && + TotalFileSize(grandparents_) <= maxGrandParentOverlapBytes_); +} + +void Compaction::AddInputDeletions(VersionEdit* edit) { + for (int which = 0; which < 2; which++) { + for (size_t i = 0; i < inputs_[which].size(); i++) { + edit->DeleteFile(level_ + which, inputs_[which][i]->number); + } + } +} + +bool Compaction::IsBaseLevelForKey(const Slice& user_key) { + // Maybe use binary search to find right entry instead of linear search? + const Comparator* user_cmp = input_version_->vset_->icmp_.user_comparator(); + for (int lvl = level_ + 2; lvl < number_levels_; lvl++) { + const std::vector& files = input_version_->files_[lvl]; + for (; level_ptrs_[lvl] < files.size(); ) { + FileMetaData* f = files[level_ptrs_[lvl]]; + if (user_cmp->Compare(user_key, f->largest.user_key()) <= 0) { + // We've advanced far enough + if (user_cmp->Compare(user_key, f->smallest.user_key()) >= 0) { + // Key falls in this file's range, so definitely not base level + return false; + } + break; + } + level_ptrs_[lvl]++; + } + } + return true; +} + +bool Compaction::ShouldStopBefore(const Slice& internal_key) { + // Scan to find earliest grandparent file that contains key. + const InternalKeyComparator* icmp = &input_version_->vset_->icmp_; + while (grandparent_index_ < grandparents_.size() && + icmp->Compare(internal_key, + grandparents_[grandparent_index_]->largest.Encode()) > 0) { + if (seen_key_) { + overlapped_bytes_ += grandparents_[grandparent_index_]->file_size; + } + assert(grandparent_index_ + 1 >= grandparents_.size() || + icmp->Compare(grandparents_[grandparent_index_]->largest.Encode(), + grandparents_[grandparent_index_+1]->smallest.Encode()) + < 0); + grandparent_index_++; + } + seen_key_ = true; + + if (overlapped_bytes_ > maxGrandParentOverlapBytes_) { + // Too much overlap for current output; start new output + overlapped_bytes_ = 0; + return true; + } else { + return false; + } +} + +// Mark (or clear) each file that is being compacted +void Compaction::MarkFilesBeingCompacted(bool value) { + for (int i = 0; i < 2; i++) { + std::vector v = inputs_[i]; + for (unsigned int j = 0; j < inputs_[i].size(); j++) { + assert(value ? !inputs_[i][j]->being_compacted : + inputs_[i][j]->being_compacted); + inputs_[i][j]->being_compacted = value; + } + } +} + +void Compaction::ReleaseInputs() { + if (input_version_ != nullptr) { + input_version_->Unref(); + input_version_ = nullptr; + } +} + +void Compaction::ResetNextCompactionIndex() { + input_version_->ResetNextCompactionIndex(level_); +} + +static void InputSummary(std::vector& files, + char* output, + int len) { + int write = 0; + for (unsigned int i = 0; i < files.size(); i++) { + int sz = len - write; + int ret = snprintf(output + write, sz, "%lu(%lu) ", + files.at(i)->number, + files.at(i)->file_size); + if (ret < 0 || ret >= sz) + break; + write += ret; + } +} + +void Compaction::Summary(char* output, int len) { + int write = snprintf(output, len, + "Base version %ld Base level %d, seek compaction:%d, inputs:", + input_version_->GetVersionNumber(), level_, seek_compaction_); + if(write < 0 || write > len) + return; + + char level_low_summary[100]; + InputSummary(inputs_[0], level_low_summary, sizeof(level_low_summary)); + char level_up_summary[100]; + if (inputs_[1].size()) { + InputSummary(inputs_[1], level_up_summary, sizeof(level_up_summary)); + } else { + level_up_summary[0] = '\0'; + } + + snprintf(output + write, len - write, "[%s],[%s]", + level_low_summary, level_up_summary); +} + +} // namespace leveldb diff --git a/db/version_set.h b/db/version_set.h new file mode 100644 index 00000000..f8ec7162 --- /dev/null +++ b/db/version_set.h @@ -0,0 +1,572 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// The representation of a DBImpl consists of a set of Versions. The +// newest version is called "current". Older versions may be kept +// around to provide a consistent view to live iterators. +// +// Each Version keeps track of a set of Table files per level. The +// entire set of versions is maintained in a VersionSet. +// +// Version,VersionSet are thread-compatible, but require external +// synchronization on all accesses. + +#ifndef STORAGE_LEVELDB_DB_VERSION_SET_H_ +#define STORAGE_LEVELDB_DB_VERSION_SET_H_ + +#include +#include +#include +#include +#include +#include "db/dbformat.h" +#include "db/version_edit.h" +#include "port/port.h" +#include "db/table_cache.h" + +namespace leveldb { + +namespace log { class Writer; } + +class Compaction; +class Iterator; +class MemTable; +class TableBuilder; +class TableCache; +class Version; +class VersionSet; +class WritableFile; + +// Return the smallest index i such that files[i]->largest >= key. +// Return files.size() if there is no such file. +// REQUIRES: "files" contains a sorted list of non-overlapping files. +extern int FindFile(const InternalKeyComparator& icmp, + const std::vector& files, + const Slice& key); + +// Returns true iff some file in "files" overlaps the user key range +// [*smallest,*largest]. +// smallest==nullptr represents a key smaller than all keys in the DB. +// largest==nullptr represents a key largest than all keys in the DB. +// REQUIRES: If disjoint_sorted_files, files[] contains disjoint ranges +// in sorted order. +extern bool SomeFileOverlapsRange( + const InternalKeyComparator& icmp, + bool disjoint_sorted_files, + const std::vector& files, + const Slice* smallest_user_key, + const Slice* largest_user_key); + +class Version { + public: + // Append to *iters a sequence of iterators that will + // yield the contents of this Version when merged together. + // REQUIRES: This version has been saved (see VersionSet::SaveTo) + void AddIterators(const ReadOptions&, std::vector* iters); + + // Lookup the value for key. If found, store it in *val and + // return OK. Else return a non-OK status. Fills *stats. + // REQUIRES: lock is not held + struct GetStats { + FileMetaData* seek_file; + int seek_file_level; + }; + Status Get(const ReadOptions&, const LookupKey& key, std::string* val, + GetStats* stats); + + // Adds "stats" into the current state. Returns true if a new + // compaction may need to be triggered, false otherwise. + // REQUIRES: lock is held + bool UpdateStats(const GetStats& stats); + + // Reference count management (so Versions do not disappear out from + // under live iterators) + void Ref(); + void Unref(); + + void GetOverlappingInputs( + int level, + const InternalKey* begin, // nullptr means before all keys + const InternalKey* end, // nullptr means after all keys + std::vector* inputs, + int hint_index = -1, // index of overlap file + int* file_index = nullptr); // return index of overlap file + + void GetOverlappingInputsBinarySearch( + int level, + const Slice& begin, // nullptr means before all keys + const Slice& end, // nullptr means after all keys + std::vector* inputs, + int hint_index, // index of overlap file + int* file_index); // return index of overlap file + + void ExtendOverlappingInputs( + int level, + const Slice& begin, // nullptr means before all keys + const Slice& end, // nullptr means after all keys + std::vector* inputs, + int index); // start extending from this index + + // Returns true iff some file in the specified level overlaps + // some part of [*smallest_user_key,*largest_user_key]. + // smallest_user_key==NULL represents a key smaller than all keys in the DB. + // largest_user_key==NULL represents a key largest than all keys in the DB. + bool OverlapInLevel(int level, + const Slice* smallest_user_key, + const Slice* largest_user_key); + + // Return the level at which we should place a new memtable compaction + // result that covers the range [smallest_user_key,largest_user_key]. + int PickLevelForMemTableOutput(const Slice& smallest_user_key, + const Slice& largest_user_key); + + int NumFiles(int level) const { return files_[level].size(); } + + // Return a human readable string that describes this version's contents. + std::string DebugString(bool hex = false) const; + + // Returns the version nuber of this version + uint64_t GetVersionNumber() { + return version_number_; + } + + private: + friend class Compaction; + friend class VersionSet; + + class LevelFileNumIterator; + Iterator* NewConcatenatingIterator(const ReadOptions&, int level) const; + + VersionSet* vset_; // VersionSet to which this Version belongs + Version* next_; // Next version in linked list + Version* prev_; // Previous version in linked list + int refs_; // Number of live refs to this version + + // List of files per level, files in each level are arranged + // in increasing order of keys + std::vector* files_; + + // A list for the same set of files that are stored in files_, + // but files in each level are now sorted based on file + // size. The file with the largest size is at the front. + // This vector stores the index of the file from files_. + std::vector< std::vector > files_by_size_; + + // An index into files_by_size_ that specifies the first + // file that is not yet compacted + std::vector next_file_to_compact_by_size_; + + // Only the first few entries of files_by_size_ are sorted. + // There is no need to sort all the files because it is likely + // that on a running system, we need to look at only the first + // few largest files because a new version is created every few + // seconds/minutes (because of concurrent compactions). + static const int number_of_files_to_sort_ = 50; + + // Next file to compact based on seek stats. + FileMetaData* file_to_compact_; + int file_to_compact_level_; + + // Level that should be compacted next and its compaction score. + // Score < 1 means compaction is not strictly needed. These fields + // are initialized by Finalize(). + // The most critical level to be compacted is listed first + // These are used to pick the best compaction level + std::vector compaction_score_; + std::vector compaction_level_; + double max_compaction_score_; // max score in l1 to ln-1 + int max_compaction_score_level_; // level on which max score occurs + + // The offset in the manifest file where this version is stored. + uint64_t offset_manifest_file_; + + // A version number that uniquely represents this version. This is + // used for debugging and logging purposes only. + uint64_t version_number_; + + explicit Version(VersionSet* vset, uint64_t version_number = 0); + + ~Version(); + + // re-initializes the index that is used to offset into files_by_size_ + // to find the next compaction candidate file. + void ResetNextCompactionIndex(int level) { + next_file_to_compact_by_size_[level] = 0; + } + + // No copying allowed + Version(const Version&); + void operator=(const Version&); +}; + +class VersionSet { + public: + VersionSet(const std::string& dbname, + const Options* options, + TableCache* table_cache, + const InternalKeyComparator*); + ~VersionSet(); + + // Apply *edit to the current version to form a new descriptor that + // is both saved to persistent state and installed as the new + // current version. Will release *mu while actually writing to the file. + // REQUIRES: *mu is held on entry. + // REQUIRES: no other thread concurrently calls LogAndApply() + Status LogAndApply(VersionEdit* edit, port::Mutex* mu, + bool new_descriptor_log = false); + + // Recover the last saved descriptor from persistent storage. + Status Recover(); + + // Try to reduce the number of levels. This call is valid when + // only one level from the new max level to the old + // max level containing files. + // For example, a db currently has 7 levels [0-6], and a call to + // to reduce to 5 [0-4] can only be executed when only one level + // among [4-6] contains files. + Status ReduceNumberOfLevels(int new_levels, port::Mutex* mu); + + // Return the current version. + Version* current() const { return current_; } + + // Return the current manifest file number + uint64_t ManifestFileNumber() const { return manifest_file_number_; } + + // Allocate and return a new file number + uint64_t NewFileNumber() { return next_file_number_++; } + + // Arrange to reuse "file_number" unless a newer file number has + // already been allocated. + // REQUIRES: "file_number" was returned by a call to NewFileNumber(). + void ReuseFileNumber(uint64_t file_number) { + if (next_file_number_ == file_number + 1) { + next_file_number_ = file_number; + } + } + + // Return the number of Table files at the specified level. + int NumLevelFiles(int level) const; + + // Return the combined file size of all files at the specified level. + int64_t NumLevelBytes(int level) const; + + // Return the last sequence number. + uint64_t LastSequence() const { return last_sequence_; } + + // Set the last sequence number to s. + void SetLastSequence(uint64_t s) { + assert(s >= last_sequence_); + last_sequence_ = s; + } + + // Mark the specified file number as used. + void MarkFileNumberUsed(uint64_t number); + + // Return the current log file number. + uint64_t LogNumber() const { return log_number_; } + + // Return the log file number for the log file that is currently + // being compacted, or zero if there is no such log file. + uint64_t PrevLogNumber() const { return prev_log_number_; } + + int NumberLevels() const { return num_levels_; } + + // Pick level and inputs for a new compaction. + // Returns nullptr if there is no compaction to be done. + // Otherwise returns a pointer to a heap-allocated object that + // describes the compaction. Caller should delete the result. + Compaction* PickCompaction(); + + // Return a compaction object for compacting the range [begin,end] in + // the specified level. Returns nullptr if there is nothing in that + // level that overlaps the specified range. Caller should delete + // the result. + Compaction* CompactRange( + int level, + const InternalKey* begin, + const InternalKey* end); + + // Return the maximum overlapping data (in bytes) at next level for any + // file at a level >= 1. + int64_t MaxNextLevelOverlappingBytes(); + + // Create an iterator that reads over the compaction inputs for "*c". + // The caller should delete the iterator when no longer needed. + Iterator* MakeInputIterator(Compaction* c); + + // Returns true iff some level needs a compaction because it has + // exceeded its target size. + bool NeedsSizeCompaction() const { + for (int i = 0; i < NumberLevels()-1; i++) { + if (current_->compaction_score_[i] >= 1) { + return true; + } + } + return false; + } + // Returns true iff some level needs a compaction. + bool NeedsCompaction() const { + return ((current_->file_to_compact_ != nullptr) || + NeedsSizeCompaction()); + } + + // Returns the maxmimum compaction score for levels 1 to max + double MaxCompactionScore() const { + return current_->max_compaction_score_; + } + + // See field declaration + int MaxCompactionScoreLevel() const { + return current_->max_compaction_score_level_; + } + + // Add all files listed in any live version to *live. + // May also mutate some internal state. + void AddLiveFiles(std::set* live); + + // Add all files listed in the current version to *live. + void AddLiveFilesCurrentVersion(std::set* live); + + // Return the approximate offset in the database of the data for + // "key" as of version "v". + uint64_t ApproximateOffsetOf(Version* v, const InternalKey& key); + + // Return a human-readable short (single-line) summary of the number + // of files per level. Uses *scratch as backing store. + struct LevelSummaryStorage { + char buffer[100]; + }; + const char* LevelSummary(LevelSummaryStorage* scratch) const; + + // printf contents (for debugging) + Status DumpManifest(Options& options, std::string& manifestFileName, + bool verbose, bool hex = false); + + // Return a human-readable short (single-line) summary of the data size + // of files per level. Uses *scratch as backing store. + const char* LevelDataSizeSummary(LevelSummaryStorage* scratch) const; + + // Return the size of the current manifest file + const uint64_t ManifestFileSize() { return current_->offset_manifest_file_; } + + // For the specfied level, pick a compaction. + // Returns nullptr if there is no compaction to be done. + // If level is 0 and there is already a compaction on that level, this + // function will return nullptr. + Compaction* PickCompactionBySize(int level, double score); + + // Free up the files that were participated in a compaction + void ReleaseCompactionFiles(Compaction* c, Status status); + + // verify that the files that we started with for a compaction + // still exist in the current version and in the same original level. + // This ensures that a concurrent compaction did not erroneously + // pick the same files to compact. + bool VerifyCompactionFileConsistency(Compaction* c); + + // used to sort files by size + typedef struct fsize { + int index; + FileMetaData* file; + } Fsize; + + // Sort all files for this version based on their file size and + // record results in files_by_size_. The largest files are listed first. + void UpdateFilesBySize(Version *v); + + // Get the max file size in a given level. + uint64_t MaxFileSizeForLevel(int level); + + private: + class Builder; + struct ManifestWriter; + + friend class Compaction; + friend class Version; + + void Init(int num_levels); + + void Finalize(Version* v); + + void GetRange(const std::vector& inputs, + InternalKey* smallest, + InternalKey* largest); + + void GetRange2(const std::vector& inputs1, + const std::vector& inputs2, + InternalKey* smallest, + InternalKey* largest); + + void SetupOtherInputs(Compaction* c); + + // Save current contents to *log + Status WriteSnapshot(log::Writer* log); + + void AppendVersion(Version* v); + + bool ManifestContains(const std::string& record) const; + + double MaxBytesForLevel(int level); + + int64_t ExpandedCompactionByteSizeLimit(int level); + + int64_t MaxGrandParentOverlapBytes(int level); + + Env* const env_; + const std::string dbname_; + const Options* const options_; + TableCache* const table_cache_; + const InternalKeyComparator icmp_; + uint64_t next_file_number_; + uint64_t manifest_file_number_; + uint64_t last_sequence_; + uint64_t log_number_; + uint64_t prev_log_number_; // 0 or backing store for memtable being compacted + + int num_levels_; + + // Opened lazily + unique_ptr descriptor_log_; + Version dummy_versions_; // Head of circular doubly-linked list of versions. + Version* current_; // == dummy_versions_.prev_ + + // Per-level key at which the next compaction at that level should start. + // Either an empty string, or a valid InternalKey. + std::string* compact_pointer_; + + // Per-level target file size. + uint64_t* max_file_size_; + + // Per-level max bytes + uint64_t* level_max_bytes_; + + // record all the ongoing compactions for all levels + std::vector > compactions_in_progress_; + + // generates a increasing version number for every new version + uint64_t current_version_number_; + + // Queue of writers to the manifest file + std::deque manifest_writers_; + + // Store the manifest file size when it is checked. + // Save us the cost of checking file size twice in LogAndApply + uint64_t last_observed_manifest_size_; + + // No copying allowed + VersionSet(const VersionSet&); + void operator=(const VersionSet&); + + // Return the total amount of data that is undergoing + // compactions at this level + uint64_t SizeBeingCompacted(int level); + + // Returns true if any one of the parent files are being compacted + bool ParentRangeInCompaction(const InternalKey* smallest, + const InternalKey* largest, int level, int* index); + + // Returns true if any one of the specified files are being compacted + bool FilesInCompaction(std::vector& files); + + void LogAndApplyHelper(Builder*b, Version* v, + VersionEdit* edit, port::Mutex* mu); +}; + +// A Compaction encapsulates information about a compaction. +class Compaction { + public: + ~Compaction(); + + // Return the level that is being compacted. Inputs from "level" + // and "level+1" will be merged to produce a set of "level+1" files. + int level() const { return level_; } + + // Return the object that holds the edits to the descriptor done + // by this compaction. + VersionEdit* edit() { return edit_; } + + // "which" must be either 0 or 1 + int num_input_files(int which) const { return inputs_[which].size(); } + + // Return the ith input file at "level()+which" ("which" must be 0 or 1). + FileMetaData* input(int which, int i) const { return inputs_[which][i]; } + + // Maximum size of files to build during this compaction. + uint64_t MaxOutputFileSize() const { return max_output_file_size_; } + + // Is this a trivial compaction that can be implemented by just + // moving a single input file to the next level (no merging or splitting) + bool IsTrivialMove() const; + + // Add all inputs to this compaction as delete operations to *edit. + void AddInputDeletions(VersionEdit* edit); + + // Returns true if the information we have available guarantees that + // the compaction is producing data in "level+1" for which no data exists + // in levels greater than "level+1". + bool IsBaseLevelForKey(const Slice& user_key); + + // Returns true iff we should stop building the current output + // before processing "internal_key". + bool ShouldStopBefore(const Slice& internal_key); + + // Release the input version for the compaction, once the compaction + // is successful. + void ReleaseInputs(); + + void Summary(char* output, int len); + + // Return the score that was used to pick this compaction run. + double score() const { return score_; } + + private: + friend class Version; + friend class VersionSet; + + explicit Compaction(int level, uint64_t target_file_size, + uint64_t max_grandparent_overlap_bytes, int number_levels, + bool seek_compaction = false); + + int level_; + uint64_t max_output_file_size_; + int64_t maxGrandParentOverlapBytes_; + Version* input_version_; + VersionEdit* edit_; + int number_levels_; + + bool seek_compaction_; + + // Each compaction reads inputs from "level_" and "level_+1" + std::vector inputs_[2]; // The two sets of inputs + + // State used to check for number of of overlapping grandparent files + // (parent == level_ + 1, grandparent == level_ + 2) + std::vector grandparents_; + size_t grandparent_index_; // Index in grandparent_starts_ + bool seen_key_; // Some output key has been seen + int64_t overlapped_bytes_; // Bytes of overlap between current output + // and grandparent files + int base_index_; // index of the file in files_[level_] + int parent_index_; // index of some file with same range in files_[level_+1] + double score_; // score that was used to pick this compaction. + + // State for implementing IsBaseLevelForKey + + // level_ptrs_ holds indices into input_version_->levels_: our state + // is that we are positioned at one of the file ranges for each + // higher level than the ones involved in this compaction (i.e. for + // all L >= level_ + 2). + size_t* level_ptrs_; + + // mark (or clear) all files that are being compacted + void MarkFilesBeingCompacted(bool); + + // In case of compaction error, reset the nextIndex that is used + // to pick up the next file to be compacted from files_by_size_ + void ResetNextCompactionIndex(); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_VERSION_SET_H_ diff --git a/db/version_set_reduce_num_levels.cc b/db/version_set_reduce_num_levels.cc new file mode 100644 index 00000000..b110ef6f --- /dev/null +++ b/db/version_set_reduce_num_levels.cc @@ -0,0 +1,74 @@ +// Copyright (c) 2012 Facebook. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "db/version_set.h" + +#include +#include +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "util/logging.h" + +namespace leveldb { + +Status VersionSet::ReduceNumberOfLevels(int new_levels, port::Mutex* mu) { + + if(new_levels <= 1) { + return Status::InvalidArgument( + "Number of levels needs to be bigger than 1"); + } + + Version* current_version = current_; + int current_levels = NumberLevels(); + + if (current_levels <= new_levels) { + return Status::OK(); + } + + // Make sure there are file only on one level from + // (new_levels-1) to (current_levels-1) + int first_nonempty_level = -1; + int first_nonempty_level_filenum = 0; + for (int i = new_levels - 1; i < current_levels; i++) { + int file_num = NumLevelFiles(i); + if (file_num != 0) { + if (first_nonempty_level < 0) { + first_nonempty_level = i; + first_nonempty_level_filenum = file_num; + } else { + char msg[255]; + sprintf(msg, "Found at least two levels containing files: " + "[%d:%d],[%d:%d].\n", + first_nonempty_level, first_nonempty_level_filenum, i, file_num); + return Status::InvalidArgument(msg); + } + } + } + + Status st; + std::vector* old_files_list = current_version->files_; + std::vector* new_files_list = + new std::vector[new_levels]; + for (int i = 0; i < new_levels - 1; i++) { + new_files_list[i] = old_files_list[i]; + } + + if (first_nonempty_level > 0) { + new_files_list[new_levels - 1] = old_files_list[first_nonempty_level]; + } + + delete[] current_version->files_; + current_version->files_ = new_files_list; + + delete[] compact_pointer_; + delete[] max_file_size_; + delete[] level_max_bytes_; + num_levels_ = new_levels; + compact_pointer_ = new std::string[new_levels]; + Init(new_levels); + st = LogAndApply(new VersionEdit(new_levels), mu, true); + return st; +} + +} diff --git a/db/version_set_test.cc b/db/version_set_test.cc new file mode 100644 index 00000000..17424e1b --- /dev/null +++ b/db/version_set_test.cc @@ -0,0 +1,179 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/version_set.h" +#include "util/logging.h" +#include "util/testharness.h" +#include "util/testutil.h" + +namespace leveldb { + +class FindFileTest { + public: + std::vector files_; + bool disjoint_sorted_files_; + + FindFileTest() : disjoint_sorted_files_(true) { } + + ~FindFileTest() { + for (unsigned int i = 0; i < files_.size(); i++) { + delete files_[i]; + } + } + + void Add(const char* smallest, const char* largest, + SequenceNumber smallest_seq = 100, + SequenceNumber largest_seq = 100) { + FileMetaData* f = new FileMetaData; + f->number = files_.size() + 1; + f->smallest = InternalKey(smallest, smallest_seq, kTypeValue); + f->largest = InternalKey(largest, largest_seq, kTypeValue); + files_.push_back(f); + } + + int Find(const char* key) { + InternalKey target(key, 100, kTypeValue); + InternalKeyComparator cmp(BytewiseComparator()); + return FindFile(cmp, files_, target.Encode()); + } + + bool Overlaps(const char* smallest, const char* largest) { + InternalKeyComparator cmp(BytewiseComparator()); + Slice s(smallest != nullptr ? smallest : ""); + Slice l(largest != nullptr ? largest : ""); + return SomeFileOverlapsRange(cmp, disjoint_sorted_files_, files_, + (smallest != nullptr ? &s : nullptr), + (largest != nullptr ? &l : nullptr)); + } +}; + +TEST(FindFileTest, Empty) { + ASSERT_EQ(0, Find("foo")); + ASSERT_TRUE(! Overlaps("a", "z")); + ASSERT_TRUE(! Overlaps(nullptr, "z")); + ASSERT_TRUE(! Overlaps("a", nullptr)); + ASSERT_TRUE(! Overlaps(nullptr, nullptr)); +} + +TEST(FindFileTest, Single) { + Add("p", "q"); + ASSERT_EQ(0, Find("a")); + ASSERT_EQ(0, Find("p")); + ASSERT_EQ(0, Find("p1")); + ASSERT_EQ(0, Find("q")); + ASSERT_EQ(1, Find("q1")); + ASSERT_EQ(1, Find("z")); + + ASSERT_TRUE(! Overlaps("a", "b")); + ASSERT_TRUE(! Overlaps("z1", "z2")); + ASSERT_TRUE(Overlaps("a", "p")); + ASSERT_TRUE(Overlaps("a", "q")); + ASSERT_TRUE(Overlaps("a", "z")); + ASSERT_TRUE(Overlaps("p", "p1")); + ASSERT_TRUE(Overlaps("p", "q")); + ASSERT_TRUE(Overlaps("p", "z")); + ASSERT_TRUE(Overlaps("p1", "p2")); + ASSERT_TRUE(Overlaps("p1", "z")); + ASSERT_TRUE(Overlaps("q", "q")); + ASSERT_TRUE(Overlaps("q", "q1")); + + ASSERT_TRUE(! Overlaps(nullptr, "j")); + ASSERT_TRUE(! Overlaps("r", nullptr)); + ASSERT_TRUE(Overlaps(nullptr, "p")); + ASSERT_TRUE(Overlaps(nullptr, "p1")); + ASSERT_TRUE(Overlaps("q", nullptr)); + ASSERT_TRUE(Overlaps(nullptr, nullptr)); +} + + +TEST(FindFileTest, Multiple) { + Add("150", "200"); + Add("200", "250"); + Add("300", "350"); + Add("400", "450"); + ASSERT_EQ(0, Find("100")); + ASSERT_EQ(0, Find("150")); + ASSERT_EQ(0, Find("151")); + ASSERT_EQ(0, Find("199")); + ASSERT_EQ(0, Find("200")); + ASSERT_EQ(1, Find("201")); + ASSERT_EQ(1, Find("249")); + ASSERT_EQ(1, Find("250")); + ASSERT_EQ(2, Find("251")); + ASSERT_EQ(2, Find("299")); + ASSERT_EQ(2, Find("300")); + ASSERT_EQ(2, Find("349")); + ASSERT_EQ(2, Find("350")); + ASSERT_EQ(3, Find("351")); + ASSERT_EQ(3, Find("400")); + ASSERT_EQ(3, Find("450")); + ASSERT_EQ(4, Find("451")); + + ASSERT_TRUE(! Overlaps("100", "149")); + ASSERT_TRUE(! Overlaps("251", "299")); + ASSERT_TRUE(! Overlaps("451", "500")); + ASSERT_TRUE(! Overlaps("351", "399")); + + ASSERT_TRUE(Overlaps("100", "150")); + ASSERT_TRUE(Overlaps("100", "200")); + ASSERT_TRUE(Overlaps("100", "300")); + ASSERT_TRUE(Overlaps("100", "400")); + ASSERT_TRUE(Overlaps("100", "500")); + ASSERT_TRUE(Overlaps("375", "400")); + ASSERT_TRUE(Overlaps("450", "450")); + ASSERT_TRUE(Overlaps("450", "500")); +} + +TEST(FindFileTest, MultipleNullBoundaries) { + Add("150", "200"); + Add("200", "250"); + Add("300", "350"); + Add("400", "450"); + ASSERT_TRUE(! Overlaps(nullptr, "149")); + ASSERT_TRUE(! Overlaps("451", nullptr)); + ASSERT_TRUE(Overlaps(nullptr, nullptr)); + ASSERT_TRUE(Overlaps(nullptr, "150")); + ASSERT_TRUE(Overlaps(nullptr, "199")); + ASSERT_TRUE(Overlaps(nullptr, "200")); + ASSERT_TRUE(Overlaps(nullptr, "201")); + ASSERT_TRUE(Overlaps(nullptr, "400")); + ASSERT_TRUE(Overlaps(nullptr, "800")); + ASSERT_TRUE(Overlaps("100", nullptr)); + ASSERT_TRUE(Overlaps("200", nullptr)); + ASSERT_TRUE(Overlaps("449", nullptr)); + ASSERT_TRUE(Overlaps("450", nullptr)); +} + +TEST(FindFileTest, OverlapSequenceChecks) { + Add("200", "200", 5000, 3000); + ASSERT_TRUE(! Overlaps("199", "199")); + ASSERT_TRUE(! Overlaps("201", "300")); + ASSERT_TRUE(Overlaps("200", "200")); + ASSERT_TRUE(Overlaps("190", "200")); + ASSERT_TRUE(Overlaps("200", "210")); +} + +TEST(FindFileTest, OverlappingFiles) { + Add("150", "600"); + Add("400", "500"); + disjoint_sorted_files_ = false; + ASSERT_TRUE(! Overlaps("100", "149")); + ASSERT_TRUE(! Overlaps("601", "700")); + ASSERT_TRUE(Overlaps("100", "150")); + ASSERT_TRUE(Overlaps("100", "200")); + ASSERT_TRUE(Overlaps("100", "300")); + ASSERT_TRUE(Overlaps("100", "400")); + ASSERT_TRUE(Overlaps("100", "500")); + ASSERT_TRUE(Overlaps("375", "400")); + ASSERT_TRUE(Overlaps("450", "450")); + ASSERT_TRUE(Overlaps("450", "500")); + ASSERT_TRUE(Overlaps("450", "700")); + ASSERT_TRUE(Overlaps("600", "700")); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/db/write_batch.cc b/db/write_batch.cc new file mode 100644 index 00000000..33f4a425 --- /dev/null +++ b/db/write_batch.cc @@ -0,0 +1,147 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// WriteBatch::rep_ := +// sequence: fixed64 +// count: fixed32 +// data: record[count] +// record := +// kTypeValue varstring varstring | +// kTypeDeletion varstring +// varstring := +// len: varint32 +// data: uint8[len] + +#include "leveldb/write_batch.h" + +#include "leveldb/db.h" +#include "db/dbformat.h" +#include "db/memtable.h" +#include "db/write_batch_internal.h" +#include "util/coding.h" + +namespace leveldb { + +// WriteBatch header has an 8-byte sequence number followed by a 4-byte count. +static const size_t kHeader = 12; + +WriteBatch::WriteBatch() { + Clear(); +} + +WriteBatch::~WriteBatch() { } + +WriteBatch::Handler::~Handler() { } + +void WriteBatch::Clear() { + rep_.clear(); + rep_.resize(kHeader); +} + +Status WriteBatch::Iterate(Handler* handler) const { + Slice input(rep_); + if (input.size() < kHeader) { + return Status::Corruption("malformed WriteBatch (too small)"); + } + + input.remove_prefix(kHeader); + Slice key, value; + int found = 0; + while (!input.empty()) { + found++; + char tag = input[0]; + input.remove_prefix(1); + switch (tag) { + case kTypeValue: + if (GetLengthPrefixedSlice(&input, &key) && + GetLengthPrefixedSlice(&input, &value)) { + handler->Put(key, value); + } else { + return Status::Corruption("bad WriteBatch Put"); + } + break; + case kTypeDeletion: + if (GetLengthPrefixedSlice(&input, &key)) { + handler->Delete(key); + } else { + return Status::Corruption("bad WriteBatch Delete"); + } + break; + default: + return Status::Corruption("unknown WriteBatch tag"); + } + } + if (found != WriteBatchInternal::Count(this)) { + return Status::Corruption("WriteBatch has wrong count"); + } else { + return Status::OK(); + } +} + +int WriteBatchInternal::Count(const WriteBatch* b) { + return DecodeFixed32(b->rep_.data() + 8); +} + +void WriteBatchInternal::SetCount(WriteBatch* b, int n) { + EncodeFixed32(&b->rep_[8], n); +} + +SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) { + return SequenceNumber(DecodeFixed64(b->rep_.data())); +} + +void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) { + EncodeFixed64(&b->rep_[0], seq); +} + +void WriteBatch::Put(const Slice& key, const Slice& value) { + WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); + rep_.push_back(static_cast(kTypeValue)); + PutLengthPrefixedSlice(&rep_, key); + PutLengthPrefixedSlice(&rep_, value); +} + +void WriteBatch::Delete(const Slice& key) { + WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); + rep_.push_back(static_cast(kTypeDeletion)); + PutLengthPrefixedSlice(&rep_, key); +} + +namespace { +class MemTableInserter : public WriteBatch::Handler { + public: + SequenceNumber sequence_; + MemTable* mem_; + + virtual void Put(const Slice& key, const Slice& value) { + mem_->Add(sequence_, kTypeValue, key, value); + sequence_++; + } + virtual void Delete(const Slice& key) { + mem_->Add(sequence_, kTypeDeletion, key, Slice()); + sequence_++; + } +}; +} // namespace + +Status WriteBatchInternal::InsertInto(const WriteBatch* b, + MemTable* memtable) { + MemTableInserter inserter; + inserter.sequence_ = WriteBatchInternal::Sequence(b); + inserter.mem_ = memtable; + return b->Iterate(&inserter); +} + +void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) { + assert(contents.size() >= kHeader); + b->rep_.assign(contents.data(), contents.size()); +} + +void WriteBatchInternal::Append(WriteBatch* dst, const WriteBatch* src) { + SetCount(dst, Count(dst) + Count(src)); + assert(src->rep_.size() >= kHeader); + dst->rep_.append(src->rep_.data() + kHeader, src->rep_.size() - kHeader); +} + +} // namespace leveldb diff --git a/db/write_batch_internal.h b/db/write_batch_internal.h new file mode 100644 index 00000000..eb37733c --- /dev/null +++ b/db/write_batch_internal.h @@ -0,0 +1,50 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_ +#define STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_ + +#include "leveldb/types.h" +#include "leveldb/write_batch.h" + +namespace leveldb { + +class MemTable; + +// WriteBatchInternal provides static methods for manipulating a +// WriteBatch that we don't want in the public WriteBatch interface. +class WriteBatchInternal { + public: + // Return the number of entries in the batch. + static int Count(const WriteBatch* batch); + + // Set the count for the number of entries in the batch. + static void SetCount(WriteBatch* batch, int n); + + // Return the seqeunce number for the start of this batch. + static SequenceNumber Sequence(const WriteBatch* batch); + + // Store the specified number as the seqeunce number for the start of + // this batch. + static void SetSequence(WriteBatch* batch, SequenceNumber seq); + + static Slice Contents(const WriteBatch* batch) { + return Slice(batch->rep_); + } + + static size_t ByteSize(const WriteBatch* batch) { + return batch->rep_.size(); + } + + static void SetContents(WriteBatch* batch, const Slice& contents); + + static Status InsertInto(const WriteBatch* batch, MemTable* memtable); + + static void Append(WriteBatch* dst, const WriteBatch* src); +}; + +} // namespace leveldb + + +#endif // STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_ diff --git a/db/write_batch_test.cc b/db/write_batch_test.cc new file mode 100644 index 00000000..71a5e89c --- /dev/null +++ b/db/write_batch_test.cc @@ -0,0 +1,121 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/db.h" + +#include "db/memtable.h" +#include "db/write_batch_internal.h" +#include "leveldb/env.h" +#include "util/logging.h" +#include "util/testharness.h" + +namespace leveldb { + +static std::string PrintContents(WriteBatch* b) { + InternalKeyComparator cmp(BytewiseComparator()); + MemTable* mem = new MemTable(cmp); + mem->Ref(); + std::string state; + Status s = WriteBatchInternal::InsertInto(b, mem); + int count = 0; + Iterator* iter = mem->NewIterator(); + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + ParsedInternalKey ikey; + memset((void *)&ikey, 0, sizeof(ikey)); + ASSERT_TRUE(ParseInternalKey(iter->key(), &ikey)); + switch (ikey.type) { + case kTypeValue: + state.append("Put("); + state.append(ikey.user_key.ToString()); + state.append(", "); + state.append(iter->value().ToString()); + state.append(")"); + count++; + break; + case kTypeDeletion: + state.append("Delete("); + state.append(ikey.user_key.ToString()); + state.append(")"); + count++; + break; + } + state.append("@"); + state.append(NumberToString(ikey.sequence)); + } + delete iter; + if (!s.ok()) { + state.append("ParseError()"); + } else if (count != WriteBatchInternal::Count(b)) { + state.append("CountMismatch()"); + } + mem->Unref(); + return state; +} + +class WriteBatchTest { }; + +TEST(WriteBatchTest, Empty) { + WriteBatch batch; + ASSERT_EQ("", PrintContents(&batch)); + ASSERT_EQ(0, WriteBatchInternal::Count(&batch)); +} + +TEST(WriteBatchTest, Multiple) { + WriteBatch batch; + batch.Put(Slice("foo"), Slice("bar")); + batch.Delete(Slice("box")); + batch.Put(Slice("baz"), Slice("boo")); + WriteBatchInternal::SetSequence(&batch, 100); + ASSERT_EQ(100U, WriteBatchInternal::Sequence(&batch)); + ASSERT_EQ(3, WriteBatchInternal::Count(&batch)); + ASSERT_EQ("Put(baz, boo)@102" + "Delete(box)@101" + "Put(foo, bar)@100", + PrintContents(&batch)); +} + +TEST(WriteBatchTest, Corruption) { + WriteBatch batch; + batch.Put(Slice("foo"), Slice("bar")); + batch.Delete(Slice("box")); + WriteBatchInternal::SetSequence(&batch, 200); + Slice contents = WriteBatchInternal::Contents(&batch); + WriteBatchInternal::SetContents(&batch, + Slice(contents.data(),contents.size()-1)); + ASSERT_EQ("Put(foo, bar)@200" + "ParseError()", + PrintContents(&batch)); +} + +TEST(WriteBatchTest, Append) { + WriteBatch b1, b2; + WriteBatchInternal::SetSequence(&b1, 200); + WriteBatchInternal::SetSequence(&b2, 300); + WriteBatchInternal::Append(&b1, &b2); + ASSERT_EQ("", + PrintContents(&b1)); + b2.Put("a", "va"); + WriteBatchInternal::Append(&b1, &b2); + ASSERT_EQ("Put(a, va)@200", + PrintContents(&b1)); + b2.Clear(); + b2.Put("b", "vb"); + WriteBatchInternal::Append(&b1, &b2); + ASSERT_EQ("Put(a, va)@200" + "Put(b, vb)@201", + PrintContents(&b1)); + b2.Delete("foo"); + WriteBatchInternal::Append(&b1, &b2); + ASSERT_EQ("Put(a, va)@200" + "Put(b, vb)@202" + "Put(b, vb)@201" + "Delete(foo)@203", + PrintContents(&b1)); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/doc/bench/db_bench_sqlite3.cc b/doc/bench/db_bench_sqlite3.cc new file mode 100644 index 00000000..256793a9 --- /dev/null +++ b/doc/bench/db_bench_sqlite3.cc @@ -0,0 +1,718 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include +#include "util/histogram.h" +#include "util/random.h" +#include "util/testutil.h" + +// Comma-separated list of operations to run in the specified order +// Actual benchmarks: +// +// fillseq -- write N values in sequential key order in async mode +// fillseqsync -- write N/100 values in sequential key order in sync mode +// fillseqbatch -- batch write N values in sequential key order in async mode +// fillrandom -- write N values in random key order in async mode +// fillrandsync -- write N/100 values in random key order in sync mode +// fillrandbatch -- batch write N values in sequential key order in async mode +// overwrite -- overwrite N values in random key order in async mode +// fillrand100K -- write N/1000 100K values in random order in async mode +// fillseq100K -- write N/1000 100K values in sequential order in async mode +// readseq -- read N times sequentially +// readrandom -- read N times in random order +// readrand100K -- read N/1000 100K values in sequential order in async mode +static const char* FLAGS_benchmarks = + "fillseq," + "fillseqsync," + "fillseqbatch," + "fillrandom," + "fillrandsync," + "fillrandbatch," + "overwrite," + "overwritebatch," + "readrandom," + "readseq," + "fillrand100K," + "fillseq100K," + "readseq," + "readrand100K," + ; + +// Number of key/values to place in database +static int FLAGS_num = 1000000; + +// Number of read operations to do. If negative, do FLAGS_num reads. +static int FLAGS_reads = -1; + +// Size of each value +static int FLAGS_value_size = 100; + +// Print histogram of operation timings +static bool FLAGS_histogram = false; + +// Arrange to generate values that shrink to this fraction of +// their original size after compression +static double FLAGS_compression_ratio = 0.5; + +// Page size. Default 1 KB. +static int FLAGS_page_size = 1024; + +// Number of pages. +// Default cache size = FLAGS_page_size * FLAGS_num_pages = 4 MB. +static int FLAGS_num_pages = 4096; + +// If true, do not destroy the existing database. If you set this +// flag and also specify a benchmark that wants a fresh database, that +// benchmark will fail. +static bool FLAGS_use_existing_db = false; + +// If true, we allow batch writes to occur +static bool FLAGS_transaction = true; + +// If true, we enable Write-Ahead Logging +static bool FLAGS_WAL_enabled = true; + +// Use the db with the following name. +static const char* FLAGS_db = NULL; + +inline +static void ExecErrorCheck(int status, char *err_msg) { + if (status != SQLITE_OK) { + fprintf(stderr, "SQL error: %s\n", err_msg); + sqlite3_free(err_msg); + exit(1); + } +} + +inline +static void StepErrorCheck(int status) { + if (status != SQLITE_DONE) { + fprintf(stderr, "SQL step error: status = %d\n", status); + exit(1); + } +} + +inline +static void ErrorCheck(int status) { + if (status != SQLITE_OK) { + fprintf(stderr, "sqlite3 error: status = %d\n", status); + exit(1); + } +} + +inline +static void WalCheckpoint(sqlite3* db_) { + // Flush all writes to disk + if (FLAGS_WAL_enabled) { + sqlite3_wal_checkpoint_v2(db_, NULL, SQLITE_CHECKPOINT_FULL, NULL, NULL); + } +} + +namespace leveldb { + +// Helper for quickly generating random data. +namespace { +class RandomGenerator { + private: + std::string data_; + int pos_; + + public: + RandomGenerator() { + // We use a limited amount of data over and over again and ensure + // that it is larger than the compression window (32KB), and also + // large enough to serve all typical value sizes we want to write. + Random rnd(301); + std::string piece; + while (data_.size() < 1048576) { + // Add a short fragment that is as compressible as specified + // by FLAGS_compression_ratio. + test::CompressibleString(&rnd, FLAGS_compression_ratio, 100, &piece); + data_.append(piece); + } + pos_ = 0; + } + + Slice Generate(int len) { + if (pos_ + len > data_.size()) { + pos_ = 0; + assert(len < data_.size()); + } + pos_ += len; + return Slice(data_.data() + pos_ - len, len); + } +}; + +static Slice TrimSpace(Slice s) { + int start = 0; + while (start < s.size() && isspace(s[start])) { + start++; + } + int limit = s.size(); + while (limit > start && isspace(s[limit-1])) { + limit--; + } + return Slice(s.data() + start, limit - start); +} + +} // namespace + +class Benchmark { + private: + sqlite3* db_; + int db_num_; + int num_; + int reads_; + double start_; + double last_op_finish_; + int64_t bytes_; + std::string message_; + Histogram hist_; + RandomGenerator gen_; + Random rand_; + + // State kept for progress messages + int done_; + int next_report_; // When to report next + + void PrintHeader() { + const int kKeySize = 16; + PrintEnvironment(); + fprintf(stdout, "Keys: %d bytes each\n", kKeySize); + fprintf(stdout, "Values: %d bytes each\n", FLAGS_value_size); + fprintf(stdout, "Entries: %d\n", num_); + fprintf(stdout, "RawSize: %.1f MB (estimated)\n", + ((static_cast(kKeySize + FLAGS_value_size) * num_) + / 1048576.0)); + PrintWarnings(); + fprintf(stdout, "------------------------------------------------\n"); + } + + void PrintWarnings() { +#if defined(__GNUC__) && !defined(__OPTIMIZE__) + fprintf(stdout, + "WARNING: Optimization is disabled: benchmarks unnecessarily slow\n" + ); +#endif +#ifndef NDEBUG + fprintf(stdout, + "WARNING: Assertions are enabled; benchmarks unnecessarily slow\n"); +#endif + } + + void PrintEnvironment() { + fprintf(stderr, "SQLite: version %s\n", SQLITE_VERSION); + +#if defined(__linux) + time_t now = time(NULL); + fprintf(stderr, "Date: %s", ctime(&now)); // ctime() adds newline + + FILE* cpuinfo = fopen("/proc/cpuinfo", "r"); + if (cpuinfo != NULL) { + char line[1000]; + int num_cpus = 0; + std::string cpu_type; + std::string cache_size; + while (fgets(line, sizeof(line), cpuinfo) != NULL) { + const char* sep = strchr(line, ':'); + if (sep == NULL) { + continue; + } + Slice key = TrimSpace(Slice(line, sep - 1 - line)); + Slice val = TrimSpace(Slice(sep + 1)); + if (key == "model name") { + ++num_cpus; + cpu_type = val.ToString(); + } else if (key == "cache size") { + cache_size = val.ToString(); + } + } + fclose(cpuinfo); + fprintf(stderr, "CPU: %d * %s\n", num_cpus, cpu_type.c_str()); + fprintf(stderr, "CPUCache: %s\n", cache_size.c_str()); + } +#endif + } + + void Start() { + start_ = Env::Default()->NowMicros() * 1e-6; + bytes_ = 0; + message_.clear(); + last_op_finish_ = start_; + hist_.Clear(); + done_ = 0; + next_report_ = 100; + } + + void FinishedSingleOp() { + if (FLAGS_histogram) { + double now = Env::Default()->NowMicros() * 1e-6; + double micros = (now - last_op_finish_) * 1e6; + hist_.Add(micros); + if (micros > 20000) { + fprintf(stderr, "long op: %.1f micros%30s\r", micros, ""); + fflush(stderr); + } + last_op_finish_ = now; + } + + done_++; + if (done_ >= next_report_) { + if (next_report_ < 1000) next_report_ += 100; + else if (next_report_ < 5000) next_report_ += 500; + else if (next_report_ < 10000) next_report_ += 1000; + else if (next_report_ < 50000) next_report_ += 5000; + else if (next_report_ < 100000) next_report_ += 10000; + else if (next_report_ < 500000) next_report_ += 50000; + else next_report_ += 100000; + fprintf(stderr, "... finished %d ops%30s\r", done_, ""); + fflush(stderr); + } + } + + void Stop(const Slice& name) { + double finish = Env::Default()->NowMicros() * 1e-6; + + // Pretend at least one op was done in case we are running a benchmark + // that does not call FinishedSingleOp(). + if (done_ < 1) done_ = 1; + + if (bytes_ > 0) { + char rate[100]; + snprintf(rate, sizeof(rate), "%6.1f MB/s", + (bytes_ / 1048576.0) / (finish - start_)); + if (!message_.empty()) { + message_ = std::string(rate) + " " + message_; + } else { + message_ = rate; + } + } + + fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n", + name.ToString().c_str(), + (finish - start_) * 1e6 / done_, + (message_.empty() ? "" : " "), + message_.c_str()); + if (FLAGS_histogram) { + fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str()); + } + fflush(stdout); + } + + public: + enum Order { + SEQUENTIAL, + RANDOM + }; + enum DBState { + FRESH, + EXISTING + }; + + Benchmark() + : db_(NULL), + db_num_(0), + num_(FLAGS_num), + reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads), + bytes_(0), + rand_(301) { + std::vector files; + std::string test_dir; + Env::Default()->GetTestDirectory(&test_dir); + Env::Default()->GetChildren(test_dir, &files); + if (!FLAGS_use_existing_db) { + for (int i = 0; i < files.size(); i++) { + if (Slice(files[i]).starts_with("dbbench_sqlite3")) { + std::string file_name(test_dir); + file_name += "/"; + file_name += files[i]; + Env::Default()->DeleteFile(file_name.c_str()); + } + } + } + } + + ~Benchmark() { + int status = sqlite3_close(db_); + ErrorCheck(status); + } + + void Run() { + PrintHeader(); + Open(); + + const char* benchmarks = FLAGS_benchmarks; + while (benchmarks != NULL) { + const char* sep = strchr(benchmarks, ','); + Slice name; + if (sep == NULL) { + name = benchmarks; + benchmarks = NULL; + } else { + name = Slice(benchmarks, sep - benchmarks); + benchmarks = sep + 1; + } + + bytes_ = 0; + Start(); + + bool known = true; + bool write_sync = false; + if (name == Slice("fillseq")) { + Write(write_sync, SEQUENTIAL, FRESH, num_, FLAGS_value_size, 1); + WalCheckpoint(db_); + } else if (name == Slice("fillseqbatch")) { + Write(write_sync, SEQUENTIAL, FRESH, num_, FLAGS_value_size, 1000); + WalCheckpoint(db_); + } else if (name == Slice("fillrandom")) { + Write(write_sync, RANDOM, FRESH, num_, FLAGS_value_size, 1); + WalCheckpoint(db_); + } else if (name == Slice("fillrandbatch")) { + Write(write_sync, RANDOM, FRESH, num_, FLAGS_value_size, 1000); + WalCheckpoint(db_); + } else if (name == Slice("overwrite")) { + Write(write_sync, RANDOM, EXISTING, num_, FLAGS_value_size, 1); + WalCheckpoint(db_); + } else if (name == Slice("overwritebatch")) { + Write(write_sync, RANDOM, EXISTING, num_, FLAGS_value_size, 1000); + WalCheckpoint(db_); + } else if (name == Slice("fillrandsync")) { + write_sync = true; + Write(write_sync, RANDOM, FRESH, num_ / 100, FLAGS_value_size, 1); + WalCheckpoint(db_); + } else if (name == Slice("fillseqsync")) { + write_sync = true; + Write(write_sync, SEQUENTIAL, FRESH, num_ / 100, FLAGS_value_size, 1); + WalCheckpoint(db_); + } else if (name == Slice("fillrand100K")) { + Write(write_sync, RANDOM, FRESH, num_ / 1000, 100 * 1000, 1); + WalCheckpoint(db_); + } else if (name == Slice("fillseq100K")) { + Write(write_sync, SEQUENTIAL, FRESH, num_ / 1000, 100 * 1000, 1); + WalCheckpoint(db_); + } else if (name == Slice("readseq")) { + ReadSequential(); + } else if (name == Slice("readrandom")) { + Read(RANDOM, 1); + } else if (name == Slice("readrand100K")) { + int n = reads_; + reads_ /= 1000; + Read(RANDOM, 1); + reads_ = n; + } else { + known = false; + if (name != Slice()) { // No error message for empty name + fprintf(stderr, "unknown benchmark '%s'\n", name.ToString().c_str()); + } + } + if (known) { + Stop(name); + } + } + } + + void Open() { + assert(db_ == NULL); + + int status; + char file_name[100]; + char* err_msg = NULL; + db_num_++; + + // Open database + std::string tmp_dir; + Env::Default()->GetTestDirectory(&tmp_dir); + snprintf(file_name, sizeof(file_name), + "%s/dbbench_sqlite3-%d.db", + tmp_dir.c_str(), + db_num_); + status = sqlite3_open(file_name, &db_); + if (status) { + fprintf(stderr, "open error: %s\n", sqlite3_errmsg(db_)); + exit(1); + } + + // Change SQLite cache size + char cache_size[100]; + snprintf(cache_size, sizeof(cache_size), "PRAGMA cache_size = %d", + FLAGS_num_pages); + status = sqlite3_exec(db_, cache_size, NULL, NULL, &err_msg); + ExecErrorCheck(status, err_msg); + + // FLAGS_page_size is defaulted to 1024 + if (FLAGS_page_size != 1024) { + char page_size[100]; + snprintf(page_size, sizeof(page_size), "PRAGMA page_size = %d", + FLAGS_page_size); + status = sqlite3_exec(db_, page_size, NULL, NULL, &err_msg); + ExecErrorCheck(status, err_msg); + } + + // Change journal mode to WAL if WAL enabled flag is on + if (FLAGS_WAL_enabled) { + std::string WAL_stmt = "PRAGMA journal_mode = WAL"; + + // LevelDB's default cache size is a combined 4 MB + std::string WAL_checkpoint = "PRAGMA wal_autocheckpoint = 4096"; + status = sqlite3_exec(db_, WAL_stmt.c_str(), NULL, NULL, &err_msg); + ExecErrorCheck(status, err_msg); + status = sqlite3_exec(db_, WAL_checkpoint.c_str(), NULL, NULL, &err_msg); + ExecErrorCheck(status, err_msg); + } + + // Change locking mode to exclusive and create tables/index for database + std::string locking_stmt = "PRAGMA locking_mode = EXCLUSIVE"; + std::string create_stmt = + "CREATE TABLE test (key blob, value blob, PRIMARY KEY(key))"; + std::string stmt_array[] = { locking_stmt, create_stmt }; + int stmt_array_length = sizeof(stmt_array) / sizeof(std::string); + for (int i = 0; i < stmt_array_length; i++) { + status = sqlite3_exec(db_, stmt_array[i].c_str(), NULL, NULL, &err_msg); + ExecErrorCheck(status, err_msg); + } + } + + void Write(bool write_sync, Order order, DBState state, + int num_entries, int value_size, int entries_per_batch) { + // Create new database if state == FRESH + if (state == FRESH) { + if (FLAGS_use_existing_db) { + message_ = "skipping (--use_existing_db is true)"; + return; + } + sqlite3_close(db_); + db_ = NULL; + Open(); + Start(); + } + + if (num_entries != num_) { + char msg[100]; + snprintf(msg, sizeof(msg), "(%d ops)", num_entries); + message_ = msg; + } + + char* err_msg = NULL; + int status; + + sqlite3_stmt *replace_stmt, *begin_trans_stmt, *end_trans_stmt; + std::string replace_str = "REPLACE INTO test (key, value) VALUES (?, ?)"; + std::string begin_trans_str = "BEGIN TRANSACTION;"; + std::string end_trans_str = "END TRANSACTION;"; + + // Check for synchronous flag in options + std::string sync_stmt = (write_sync) ? "PRAGMA synchronous = FULL" : + "PRAGMA synchronous = OFF"; + status = sqlite3_exec(db_, sync_stmt.c_str(), NULL, NULL, &err_msg); + ExecErrorCheck(status, err_msg); + + // Preparing sqlite3 statements + status = sqlite3_prepare_v2(db_, replace_str.c_str(), -1, + &replace_stmt, NULL); + ErrorCheck(status); + status = sqlite3_prepare_v2(db_, begin_trans_str.c_str(), -1, + &begin_trans_stmt, NULL); + ErrorCheck(status); + status = sqlite3_prepare_v2(db_, end_trans_str.c_str(), -1, + &end_trans_stmt, NULL); + ErrorCheck(status); + + bool transaction = (entries_per_batch > 1); + for (int i = 0; i < num_entries; i += entries_per_batch) { + // Begin write transaction + if (FLAGS_transaction && transaction) { + status = sqlite3_step(begin_trans_stmt); + StepErrorCheck(status); + status = sqlite3_reset(begin_trans_stmt); + ErrorCheck(status); + } + + // Create and execute SQL statements + for (int j = 0; j < entries_per_batch; j++) { + const char* value = gen_.Generate(value_size).data(); + + // Create values for key-value pair + const int k = (order == SEQUENTIAL) ? i + j : + (rand_.Next() % num_entries); + char key[100]; + snprintf(key, sizeof(key), "%016d", k); + + // Bind KV values into replace_stmt + status = sqlite3_bind_blob(replace_stmt, 1, key, 16, SQLITE_STATIC); + ErrorCheck(status); + status = sqlite3_bind_blob(replace_stmt, 2, value, + value_size, SQLITE_STATIC); + ErrorCheck(status); + + // Execute replace_stmt + bytes_ += value_size + strlen(key); + status = sqlite3_step(replace_stmt); + StepErrorCheck(status); + + // Reset SQLite statement for another use + status = sqlite3_clear_bindings(replace_stmt); + ErrorCheck(status); + status = sqlite3_reset(replace_stmt); + ErrorCheck(status); + + FinishedSingleOp(); + } + + // End write transaction + if (FLAGS_transaction && transaction) { + status = sqlite3_step(end_trans_stmt); + StepErrorCheck(status); + status = sqlite3_reset(end_trans_stmt); + ErrorCheck(status); + } + } + + status = sqlite3_finalize(replace_stmt); + ErrorCheck(status); + status = sqlite3_finalize(begin_trans_stmt); + ErrorCheck(status); + status = sqlite3_finalize(end_trans_stmt); + ErrorCheck(status); + } + + void Read(Order order, int entries_per_batch) { + int status; + sqlite3_stmt *read_stmt, *begin_trans_stmt, *end_trans_stmt; + + std::string read_str = "SELECT * FROM test WHERE key = ?"; + std::string begin_trans_str = "BEGIN TRANSACTION;"; + std::string end_trans_str = "END TRANSACTION;"; + + // Preparing sqlite3 statements + status = sqlite3_prepare_v2(db_, begin_trans_str.c_str(), -1, + &begin_trans_stmt, NULL); + ErrorCheck(status); + status = sqlite3_prepare_v2(db_, end_trans_str.c_str(), -1, + &end_trans_stmt, NULL); + ErrorCheck(status); + status = sqlite3_prepare_v2(db_, read_str.c_str(), -1, &read_stmt, NULL); + ErrorCheck(status); + + bool transaction = (entries_per_batch > 1); + for (int i = 0; i < reads_; i += entries_per_batch) { + // Begin read transaction + if (FLAGS_transaction && transaction) { + status = sqlite3_step(begin_trans_stmt); + StepErrorCheck(status); + status = sqlite3_reset(begin_trans_stmt); + ErrorCheck(status); + } + + // Create and execute SQL statements + for (int j = 0; j < entries_per_batch; j++) { + // Create key value + char key[100]; + int k = (order == SEQUENTIAL) ? i + j : (rand_.Next() % reads_); + snprintf(key, sizeof(key), "%016d", k); + + // Bind key value into read_stmt + status = sqlite3_bind_blob(read_stmt, 1, key, 16, SQLITE_STATIC); + ErrorCheck(status); + + // Execute read statement + while ((status = sqlite3_step(read_stmt)) == SQLITE_ROW); + StepErrorCheck(status); + + // Reset SQLite statement for another use + status = sqlite3_clear_bindings(read_stmt); + ErrorCheck(status); + status = sqlite3_reset(read_stmt); + ErrorCheck(status); + FinishedSingleOp(); + } + + // End read transaction + if (FLAGS_transaction && transaction) { + status = sqlite3_step(end_trans_stmt); + StepErrorCheck(status); + status = sqlite3_reset(end_trans_stmt); + ErrorCheck(status); + } + } + + status = sqlite3_finalize(read_stmt); + ErrorCheck(status); + status = sqlite3_finalize(begin_trans_stmt); + ErrorCheck(status); + status = sqlite3_finalize(end_trans_stmt); + ErrorCheck(status); + } + + void ReadSequential() { + int status; + sqlite3_stmt *pStmt; + std::string read_str = "SELECT * FROM test ORDER BY key"; + + status = sqlite3_prepare_v2(db_, read_str.c_str(), -1, &pStmt, NULL); + ErrorCheck(status); + for (int i = 0; i < reads_ && SQLITE_ROW == sqlite3_step(pStmt); i++) { + bytes_ += sqlite3_column_bytes(pStmt, 1) + sqlite3_column_bytes(pStmt, 2); + FinishedSingleOp(); + } + + status = sqlite3_finalize(pStmt); + ErrorCheck(status); + } + +}; + +} // namespace leveldb + +int main(int argc, char** argv) { + std::string default_db_path; + for (int i = 1; i < argc; i++) { + double d; + int n; + char junk; + if (leveldb::Slice(argv[i]).starts_with("--benchmarks=")) { + FLAGS_benchmarks = argv[i] + strlen("--benchmarks="); + } else if (sscanf(argv[i], "--histogram=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_histogram = n; + } else if (sscanf(argv[i], "--compression_ratio=%lf%c", &d, &junk) == 1) { + FLAGS_compression_ratio = d; + } else if (sscanf(argv[i], "--use_existing_db=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_use_existing_db = n; + } else if (sscanf(argv[i], "--num=%d%c", &n, &junk) == 1) { + FLAGS_num = n; + } else if (sscanf(argv[i], "--reads=%d%c", &n, &junk) == 1) { + FLAGS_reads = n; + } else if (sscanf(argv[i], "--value_size=%d%c", &n, &junk) == 1) { + FLAGS_value_size = n; + } else if (leveldb::Slice(argv[i]) == leveldb::Slice("--no_transaction")) { + FLAGS_transaction = false; + } else if (sscanf(argv[i], "--page_size=%d%c", &n, &junk) == 1) { + FLAGS_page_size = n; + } else if (sscanf(argv[i], "--num_pages=%d%c", &n, &junk) == 1) { + FLAGS_num_pages = n; + } else if (sscanf(argv[i], "--WAL_enabled=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_WAL_enabled = n; + } else if (strncmp(argv[i], "--db=", 5) == 0) { + FLAGS_db = argv[i] + 5; + } else { + fprintf(stderr, "Invalid flag '%s'\n", argv[i]); + exit(1); + } + } + + // Choose a location for the test database if none given with --db= + if (FLAGS_db == NULL) { + leveldb::Env::Default()->GetTestDirectory(&default_db_path); + default_db_path += "/dbbench"; + FLAGS_db = default_db_path.c_str(); + } + + leveldb::Benchmark benchmark; + benchmark.Run(); + return 0; +} diff --git a/doc/bench/db_bench_tree_db.cc b/doc/bench/db_bench_tree_db.cc new file mode 100644 index 00000000..ed86f031 --- /dev/null +++ b/doc/bench/db_bench_tree_db.cc @@ -0,0 +1,528 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include +#include "util/histogram.h" +#include "util/random.h" +#include "util/testutil.h" + +// Comma-separated list of operations to run in the specified order +// Actual benchmarks: +// +// fillseq -- write N values in sequential key order in async mode +// fillrandom -- write N values in random key order in async mode +// overwrite -- overwrite N values in random key order in async mode +// fillseqsync -- write N/100 values in sequential key order in sync mode +// fillrandsync -- write N/100 values in random key order in sync mode +// fillrand100K -- write N/1000 100K values in random order in async mode +// fillseq100K -- write N/1000 100K values in seq order in async mode +// readseq -- read N times sequentially +// readseq100K -- read N/1000 100K values in sequential order in async mode +// readrand100K -- read N/1000 100K values in sequential order in async mode +// readrandom -- read N times in random order +static const char* FLAGS_benchmarks = + "fillseq," + "fillseqsync," + "fillrandsync," + "fillrandom," + "overwrite," + "readrandom," + "readseq," + "fillrand100K," + "fillseq100K," + "readseq100K," + "readrand100K," + ; + +// Number of key/values to place in database +static int FLAGS_num = 1000000; + +// Number of read operations to do. If negative, do FLAGS_num reads. +static int FLAGS_reads = -1; + +// Size of each value +static int FLAGS_value_size = 100; + +// Arrange to generate values that shrink to this fraction of +// their original size after compression +static double FLAGS_compression_ratio = 0.5; + +// Print histogram of operation timings +static bool FLAGS_histogram = false; + +// Cache size. Default 4 MB +static int FLAGS_cache_size = 4194304; + +// Page size. Default 1 KB +static int FLAGS_page_size = 1024; + +// If true, do not destroy the existing database. If you set this +// flag and also specify a benchmark that wants a fresh database, that +// benchmark will fail. +static bool FLAGS_use_existing_db = false; + +// Compression flag. If true, compression is on. If false, compression +// is off. +static bool FLAGS_compression = true; + +// Use the db with the following name. +static const char* FLAGS_db = NULL; + +inline +static void DBSynchronize(kyotocabinet::TreeDB* db_) +{ + // Synchronize will flush writes to disk + if (!db_->synchronize()) { + fprintf(stderr, "synchronize error: %s\n", db_->error().name()); + } +} + +namespace leveldb { + +// Helper for quickly generating random data. +namespace { +class RandomGenerator { + private: + std::string data_; + int pos_; + + public: + RandomGenerator() { + // We use a limited amount of data over and over again and ensure + // that it is larger than the compression window (32KB), and also + // large enough to serve all typical value sizes we want to write. + Random rnd(301); + std::string piece; + while (data_.size() < 1048576) { + // Add a short fragment that is as compressible as specified + // by FLAGS_compression_ratio. + test::CompressibleString(&rnd, FLAGS_compression_ratio, 100, &piece); + data_.append(piece); + } + pos_ = 0; + } + + Slice Generate(int len) { + if (pos_ + len > data_.size()) { + pos_ = 0; + assert(len < data_.size()); + } + pos_ += len; + return Slice(data_.data() + pos_ - len, len); + } +}; + +static Slice TrimSpace(Slice s) { + int start = 0; + while (start < s.size() && isspace(s[start])) { + start++; + } + int limit = s.size(); + while (limit > start && isspace(s[limit-1])) { + limit--; + } + return Slice(s.data() + start, limit - start); +} + +} // namespace + +class Benchmark { + private: + kyotocabinet::TreeDB* db_; + int db_num_; + int num_; + int reads_; + double start_; + double last_op_finish_; + int64_t bytes_; + std::string message_; + Histogram hist_; + RandomGenerator gen_; + Random rand_; + kyotocabinet::LZOCompressor comp_; + + // State kept for progress messages + int done_; + int next_report_; // When to report next + + void PrintHeader() { + const int kKeySize = 16; + PrintEnvironment(); + fprintf(stdout, "Keys: %d bytes each\n", kKeySize); + fprintf(stdout, "Values: %d bytes each (%d bytes after compression)\n", + FLAGS_value_size, + static_cast(FLAGS_value_size * FLAGS_compression_ratio + 0.5)); + fprintf(stdout, "Entries: %d\n", num_); + fprintf(stdout, "RawSize: %.1f MB (estimated)\n", + ((static_cast(kKeySize + FLAGS_value_size) * num_) + / 1048576.0)); + fprintf(stdout, "FileSize: %.1f MB (estimated)\n", + (((kKeySize + FLAGS_value_size * FLAGS_compression_ratio) * num_) + / 1048576.0)); + PrintWarnings(); + fprintf(stdout, "------------------------------------------------\n"); + } + + void PrintWarnings() { +#if defined(__GNUC__) && !defined(__OPTIMIZE__) + fprintf(stdout, + "WARNING: Optimization is disabled: benchmarks unnecessarily slow\n" + ); +#endif +#ifndef NDEBUG + fprintf(stdout, + "WARNING: Assertions are enabled; benchmarks unnecessarily slow\n"); +#endif + } + + void PrintEnvironment() { + fprintf(stderr, "Kyoto Cabinet: version %s, lib ver %d, lib rev %d\n", + kyotocabinet::VERSION, kyotocabinet::LIBVER, kyotocabinet::LIBREV); + +#if defined(__linux) + time_t now = time(NULL); + fprintf(stderr, "Date: %s", ctime(&now)); // ctime() adds newline + + FILE* cpuinfo = fopen("/proc/cpuinfo", "r"); + if (cpuinfo != NULL) { + char line[1000]; + int num_cpus = 0; + std::string cpu_type; + std::string cache_size; + while (fgets(line, sizeof(line), cpuinfo) != NULL) { + const char* sep = strchr(line, ':'); + if (sep == NULL) { + continue; + } + Slice key = TrimSpace(Slice(line, sep - 1 - line)); + Slice val = TrimSpace(Slice(sep + 1)); + if (key == "model name") { + ++num_cpus; + cpu_type = val.ToString(); + } else if (key == "cache size") { + cache_size = val.ToString(); + } + } + fclose(cpuinfo); + fprintf(stderr, "CPU: %d * %s\n", num_cpus, cpu_type.c_str()); + fprintf(stderr, "CPUCache: %s\n", cache_size.c_str()); + } +#endif + } + + void Start() { + start_ = Env::Default()->NowMicros() * 1e-6; + bytes_ = 0; + message_.clear(); + last_op_finish_ = start_; + hist_.Clear(); + done_ = 0; + next_report_ = 100; + } + + void FinishedSingleOp() { + if (FLAGS_histogram) { + double now = Env::Default()->NowMicros() * 1e-6; + double micros = (now - last_op_finish_) * 1e6; + hist_.Add(micros); + if (micros > 20000) { + fprintf(stderr, "long op: %.1f micros%30s\r", micros, ""); + fflush(stderr); + } + last_op_finish_ = now; + } + + done_++; + if (done_ >= next_report_) { + if (next_report_ < 1000) next_report_ += 100; + else if (next_report_ < 5000) next_report_ += 500; + else if (next_report_ < 10000) next_report_ += 1000; + else if (next_report_ < 50000) next_report_ += 5000; + else if (next_report_ < 100000) next_report_ += 10000; + else if (next_report_ < 500000) next_report_ += 50000; + else next_report_ += 100000; + fprintf(stderr, "... finished %d ops%30s\r", done_, ""); + fflush(stderr); + } + } + + void Stop(const Slice& name) { + double finish = Env::Default()->NowMicros() * 1e-6; + + // Pretend at least one op was done in case we are running a benchmark + // that does not call FinishedSingleOp(). + if (done_ < 1) done_ = 1; + + if (bytes_ > 0) { + char rate[100]; + snprintf(rate, sizeof(rate), "%6.1f MB/s", + (bytes_ / 1048576.0) / (finish - start_)); + if (!message_.empty()) { + message_ = std::string(rate) + " " + message_; + } else { + message_ = rate; + } + } + + fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n", + name.ToString().c_str(), + (finish - start_) * 1e6 / done_, + (message_.empty() ? "" : " "), + message_.c_str()); + if (FLAGS_histogram) { + fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str()); + } + fflush(stdout); + } + + public: + enum Order { + SEQUENTIAL, + RANDOM + }; + enum DBState { + FRESH, + EXISTING + }; + + Benchmark() + : db_(NULL), + num_(FLAGS_num), + reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads), + bytes_(0), + rand_(301) { + std::vector files; + std::string test_dir; + Env::Default()->GetTestDirectory(&test_dir); + Env::Default()->GetChildren(test_dir.c_str(), &files); + if (!FLAGS_use_existing_db) { + for (int i = 0; i < files.size(); i++) { + if (Slice(files[i]).starts_with("dbbench_polyDB")) { + std::string file_name(test_dir); + file_name += "/"; + file_name += files[i]; + Env::Default()->DeleteFile(file_name.c_str()); + } + } + } + } + + ~Benchmark() { + if (!db_->close()) { + fprintf(stderr, "close error: %s\n", db_->error().name()); + } + } + + void Run() { + PrintHeader(); + Open(false); + + const char* benchmarks = FLAGS_benchmarks; + while (benchmarks != NULL) { + const char* sep = strchr(benchmarks, ','); + Slice name; + if (sep == NULL) { + name = benchmarks; + benchmarks = NULL; + } else { + name = Slice(benchmarks, sep - benchmarks); + benchmarks = sep + 1; + } + + Start(); + + bool known = true; + bool write_sync = false; + if (name == Slice("fillseq")) { + Write(write_sync, SEQUENTIAL, FRESH, num_, FLAGS_value_size, 1); + + } else if (name == Slice("fillrandom")) { + Write(write_sync, RANDOM, FRESH, num_, FLAGS_value_size, 1); + DBSynchronize(db_); + } else if (name == Slice("overwrite")) { + Write(write_sync, RANDOM, EXISTING, num_, FLAGS_value_size, 1); + DBSynchronize(db_); + } else if (name == Slice("fillrandsync")) { + write_sync = true; + Write(write_sync, RANDOM, FRESH, num_ / 100, FLAGS_value_size, 1); + DBSynchronize(db_); + } else if (name == Slice("fillseqsync")) { + write_sync = true; + Write(write_sync, SEQUENTIAL, FRESH, num_ / 100, FLAGS_value_size, 1); + DBSynchronize(db_); + } else if (name == Slice("fillrand100K")) { + Write(write_sync, RANDOM, FRESH, num_ / 1000, 100 * 1000, 1); + DBSynchronize(db_); + } else if (name == Slice("fillseq100K")) { + Write(write_sync, SEQUENTIAL, FRESH, num_ / 1000, 100 * 1000, 1); + DBSynchronize(db_); + } else if (name == Slice("readseq")) { + ReadSequential(); + } else if (name == Slice("readrandom")) { + ReadRandom(); + } else if (name == Slice("readrand100K")) { + int n = reads_; + reads_ /= 1000; + ReadRandom(); + reads_ = n; + } else if (name == Slice("readseq100K")) { + int n = reads_; + reads_ /= 1000; + ReadSequential(); + reads_ = n; + } else { + known = false; + if (name != Slice()) { // No error message for empty name + fprintf(stderr, "unknown benchmark '%s'\n", name.ToString().c_str()); + } + } + if (known) { + Stop(name); + } + } + } + + private: + void Open(bool sync) { + assert(db_ == NULL); + + // Initialize db_ + db_ = new kyotocabinet::TreeDB(); + char file_name[100]; + db_num_++; + std::string test_dir; + Env::Default()->GetTestDirectory(&test_dir); + snprintf(file_name, sizeof(file_name), + "%s/dbbench_polyDB-%d.kct", + test_dir.c_str(), + db_num_); + + // Create tuning options and open the database + int open_options = kyotocabinet::PolyDB::OWRITER | + kyotocabinet::PolyDB::OCREATE; + int tune_options = kyotocabinet::TreeDB::TSMALL | + kyotocabinet::TreeDB::TLINEAR; + if (FLAGS_compression) { + tune_options |= kyotocabinet::TreeDB::TCOMPRESS; + db_->tune_compressor(&comp_); + } + db_->tune_options(tune_options); + db_->tune_page_cache(FLAGS_cache_size); + db_->tune_page(FLAGS_page_size); + db_->tune_map(256LL<<20); + if (sync) { + open_options |= kyotocabinet::PolyDB::OAUTOSYNC; + } + if (!db_->open(file_name, open_options)) { + fprintf(stderr, "open error: %s\n", db_->error().name()); + } + } + + void Write(bool sync, Order order, DBState state, + int num_entries, int value_size, int entries_per_batch) { + // Create new database if state == FRESH + if (state == FRESH) { + if (FLAGS_use_existing_db) { + message_ = "skipping (--use_existing_db is true)"; + return; + } + delete db_; + db_ = NULL; + Open(sync); + Start(); // Do not count time taken to destroy/open + } + + if (num_entries != num_) { + char msg[100]; + snprintf(msg, sizeof(msg), "(%d ops)", num_entries); + message_ = msg; + } + + // Write to database + for (int i = 0; i < num_entries; i++) + { + const int k = (order == SEQUENTIAL) ? i : (rand_.Next() % num_entries); + char key[100]; + snprintf(key, sizeof(key), "%016d", k); + bytes_ += value_size + strlen(key); + std::string cpp_key = key; + if (!db_->set(cpp_key, gen_.Generate(value_size).ToString())) { + fprintf(stderr, "set error: %s\n", db_->error().name()); + } + FinishedSingleOp(); + } + } + + void ReadSequential() { + kyotocabinet::DB::Cursor* cur = db_->cursor(); + cur->jump(); + std::string ckey, cvalue; + while (cur->get(&ckey, &cvalue, true)) { + bytes_ += ckey.size() + cvalue.size(); + FinishedSingleOp(); + } + delete cur; + } + + void ReadRandom() { + std::string value; + for (int i = 0; i < reads_; i++) { + char key[100]; + const int k = rand_.Next() % reads_; + snprintf(key, sizeof(key), "%016d", k); + db_->get(key, &value); + FinishedSingleOp(); + } + } +}; + +} // namespace leveldb + +int main(int argc, char** argv) { + std::string default_db_path; + for (int i = 1; i < argc; i++) { + double d; + int n; + char junk; + if (leveldb::Slice(argv[i]).starts_with("--benchmarks=")) { + FLAGS_benchmarks = argv[i] + strlen("--benchmarks="); + } else if (sscanf(argv[i], "--compression_ratio=%lf%c", &d, &junk) == 1) { + FLAGS_compression_ratio = d; + } else if (sscanf(argv[i], "--histogram=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_histogram = n; + } else if (sscanf(argv[i], "--num=%d%c", &n, &junk) == 1) { + FLAGS_num = n; + } else if (sscanf(argv[i], "--reads=%d%c", &n, &junk) == 1) { + FLAGS_reads = n; + } else if (sscanf(argv[i], "--value_size=%d%c", &n, &junk) == 1) { + FLAGS_value_size = n; + } else if (sscanf(argv[i], "--cache_size=%d%c", &n, &junk) == 1) { + FLAGS_cache_size = n; + } else if (sscanf(argv[i], "--page_size=%d%c", &n, &junk) == 1) { + FLAGS_page_size = n; + } else if (sscanf(argv[i], "--compression=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_compression = (n == 1) ? true : false; + } else if (strncmp(argv[i], "--db=", 5) == 0) { + FLAGS_db = argv[i] + 5; + } else { + fprintf(stderr, "Invalid flag '%s'\n", argv[i]); + exit(1); + } + } + + // Choose a location for the test database if none given with --db= + if (FLAGS_db == NULL) { + leveldb::Env::Default()->GetTestDirectory(&default_db_path); + default_db_path += "/dbbench"; + FLAGS_db = default_db_path.c_str(); + } + + leveldb::Benchmark benchmark; + benchmark.Run(); + return 0; +} diff --git a/doc/benchmark.html b/doc/benchmark.html new file mode 100644 index 00000000..c4639772 --- /dev/null +++ b/doc/benchmark.html @@ -0,0 +1,459 @@ + + + +LevelDB Benchmarks + + + + +

LevelDB Benchmarks

+

Google, July 2011

+
+ +

In order to test LevelDB's performance, we benchmark it against other well-established database implementations. We compare LevelDB (revision 39) against SQLite3 (version 3.7.6.3) and Kyoto Cabinet's (version 1.2.67) TreeDB (a B+Tree based key-value store). We would like to acknowledge Scott Hess and Mikio Hirabayashi for their suggestions and contributions to the SQLite3 and Kyoto Cabinet benchmarks, respectively.

+ +

Benchmarks were all performed on a six-core Intel(R) Xeon(R) CPU X5650 @ 2.67GHz, with 12288 KB of total L3 cache and 12 GB of DDR3 RAM at 1333 MHz. (Note that LevelDB uses at most two CPUs since the benchmarks are single threaded: one to run the benchmark, and one for background compactions.) We ran the benchmarks on two machines (with identical processors), one with an Ext3 file system and one with an Ext4 file system. The machine with the Ext3 file system has a SATA Hitachi HDS721050CLA362 hard drive. The machine with the Ext4 file system has a SATA Samsung HD502HJ hard drive. Both hard drives spin at 7200 RPM and have hard drive write-caching enabled (using `hdparm -W 1 [device]`). The numbers reported below are the median of three measurements.

+ +

Benchmark Source Code

+

We wrote benchmark tools for SQLite and Kyoto TreeDB based on LevelDB's db_bench. The code for each of the benchmarks resides here:

+ + +

Custom Build Specifications

+
    +
  • LevelDB: LevelDB was compiled with the tcmalloc library and the Snappy compression library (revision 33). Assertions were disabled.
  • +
  • TreeDB: TreeDB was compiled using the LZO compression library (version 2.03). Furthermore, we enabled the TSMALL and TLINEAR options when opening the database in order to reduce the footprint of each record.
  • +
  • SQLite: We tuned SQLite's performance, by setting its locking mode to exclusive. We also enabled SQLite's write-ahead logging.
  • +
+ +

1. Baseline Performance

+

This section gives the baseline performance of all the +databases. Following sections show how performance changes as various +parameters are varied. For the baseline:

+
    +
  • Each database is allowed 4 MB of cache memory.
  • +
  • Databases are opened in asynchronous write mode. + (LevelDB's sync option, TreeDB's OAUTOSYNC option, and + SQLite3's synchronous options are all turned off). I.e., + every write is pushed to the operating system, but the + benchmark does not wait for the write to reach the disk.
  • +
  • Keys are 16 bytes each.
  • +
  • Value are 100 bytes each (with enough redundancy so that + a simple compressor shrinks them to 50% of their original + size).
  • +
  • Sequential reads/writes traverse the key space in increasing order.
  • +
  • Random reads/writes traverse the key space in random order.
  • +
+ +

A. Sequential Reads

+
+ + + + + + + + + +
LevelDB4,030,000 ops/sec
 
Kyoto TreeDB1,010,000 ops/sec
 
SQLite3383,000 ops/sec
 
+

B. Random Reads

+ + + + + + + + + + +
LevelDB129,000 ops/sec
 
Kyoto TreeDB151,000 ops/sec
 
SQLite3134,000 ops/sec
 
+

C. Sequential Writes

+ + + + + + + + + + +
LevelDB779,000 ops/sec
 
Kyoto TreeDB342,000 ops/sec
 
SQLite348,600 ops/sec
 
+

D. Random Writes

+ + + + + + + + + + +
LevelDB164,000 ops/sec
 
Kyoto TreeDB88,500 ops/sec
 
SQLite39,860 ops/sec
 
+ +

LevelDB outperforms both SQLite3 and TreeDB in sequential and random write operations and sequential read operations. Kyoto Cabinet has the fastest random read operations.

+ +

2. Write Performance under Different Configurations

+

A. Large Values

+

For this benchmark, we start with an empty database, and write 100,000 byte values (~50% compressible). To keep the benchmark running time reasonable, we stop after writing 1000 values.

+

Sequential Writes

+ + + + + + + + + + +
LevelDB1,100 ops/sec
 
Kyoto TreeDB1,000 ops/sec
 
SQLite31,600 ops/sec
 
+

Random Writes

+ + + + + + + + + + +
LevelDB480 ops/sec
 
Kyoto TreeDB1,100 ops/sec
 
SQLite31,600 ops/sec
 
+

LevelDB doesn't perform as well with large values of 100,000 bytes each. This is because LevelDB writes keys and values at least twice: first time to the transaction log, and second time (during a compaction) to a sorted file. +With larger values, LevelDB's per-operation efficiency is swamped by the +cost of extra copies of large values.

+

B. Batch Writes

+

A batch write is a set of writes that are applied atomically to the underlying database. A single batch of N writes may be significantly faster than N individual writes. The following benchmark writes one thousand batches where each batch contains one thousand 100-byte values. TreeDB does not support batch writes and is omitted from this benchmark.

+

Sequential Writes

+ + + + + + + + + +
LevelDB840,000 entries/sec
 
(1.08x baseline)
SQLite3124,000 entries/sec
 
(2.55x baseline)
+

Random Writes

+ + + + + + + + + +
LevelDB221,000 entries/sec
 
(1.35x baseline)
SQLite322,000 entries/sec
 
(2.23x baseline)
+ +

Because of the way LevelDB persistent storage is organized, batches of +random writes are not much slower (only a factor of 4x) than batches +of sequential writes.

+ +

C. Synchronous Writes

+

In the following benchmark, we enable the synchronous writing modes +of all of the databases. Since this change significantly slows down the +benchmark, we stop after 10,000 writes. For synchronous write tests, we've +disabled hard drive write-caching (using `hdparm -W 0 [device]`).

+
    +
  • For LevelDB, we set WriteOptions.sync = true.
  • +
  • In TreeDB, we enabled TreeDB's OAUTOSYNC option.
  • +
  • For SQLite3, we set "PRAGMA synchronous = FULL".
  • +
+

Sequential Writes

+ + + + + + + + + + + + + +
LevelDB100 ops/sec
 
(0.003x baseline)
Kyoto TreeDB7 ops/sec
 
(0.0004x baseline)
SQLite388 ops/sec
 
(0.002x baseline)
+

Random Writes

+ + + + + + + + + + + + + +
LevelDB100 ops/sec
 
(0.015x baseline)
Kyoto TreeDB8 ops/sec
 
(0.001x baseline)
SQLite388 ops/sec
 
(0.009x baseline)
+ +

Also see the ext4 performance numbers below +since synchronous writes behave significantly differently +on ext3 and ext4.

+ +

D. Turning Compression Off

+ +

In the baseline measurements, LevelDB and TreeDB were using +light-weight compression +(Snappy for LevelDB, +and LZO for +TreeDB). SQLite3, by default does not use compression. The +experiments below show what happens when compression is disabled in +all of the databases (the SQLite3 numbers are just a copy of +its baseline measurements):

+ +

Sequential Writes

+ + + + + + + + + + + + + +
LevelDB594,000 ops/sec
 
(0.76x baseline)
Kyoto TreeDB485,000 ops/sec
 
(1.42x baseline)
SQLite348,600 ops/sec
 
(1.00x baseline)
+

Random Writes

+ + + + + + + + + + + + + +
LevelDB135,000 ops/sec
 
(0.82x baseline)
Kyoto TreeDB159,000 ops/sec
 
(1.80x baseline)
SQLite39,860 ops/sec
 
(1.00x baseline)
+ +

LevelDB's write performance is better with compression than without +since compression decreases the amount of data that has to be written +to disk. Therefore LevelDB users can leave compression enabled in +most scenarios without having worry about a tradeoff between space +usage and performance. TreeDB's performance on the other hand is +better without compression than with compression. Presumably this is +because TreeDB's compression library (LZO) is more expensive than +LevelDB's compression library (Snappy).

+ +

E. Using More Memory

+

We increased the overall cache size for each database to 128 MB. For LevelDB, we partitioned 128 MB into a 120 MB write buffer and 8 MB of cache (up from 2 MB of write buffer and 2 MB of cache). For SQLite3, we kept the page size at 1024 bytes, but increased the number of pages to 131,072 (up from 4096). For TreeDB, we also kept the page size at 1024 bytes, but increased the cache size to 128 MB (up from 4 MB).

+

Sequential Writes

+ + + + + + + + + + + + + +
LevelDB812,000 ops/sec
 
(1.04x baseline)
Kyoto TreeDB321,000 ops/sec
 
(0.94x baseline)
SQLite348,500 ops/sec
 
(1.00x baseline)
+

Random Writes

+ + + + + + + + + + + + + +
LevelDB355,000 ops/sec
 
(2.16x baseline)
Kyoto TreeDB284,000 ops/sec
 
(3.21x baseline)
SQLite39,670 ops/sec
 
(0.98x baseline)
+ +

SQLite's performance does not change substantially when compared to +the baseline, but the random write performance for both LevelDB and +TreeDB increases significantly. LevelDB's performance improves +because a larger write buffer reduces the need to merge sorted files +(since it creates a smaller number of larger sorted files). TreeDB's +performance goes up because the entire database is available in memory +for fast in-place updates.

+ +

3. Read Performance under Different Configurations

+

A. Larger Caches

+

We increased the overall memory usage to 128 MB for each database. +For LevelDB, we allocated 8 MB to LevelDB's write buffer and 120 MB +to LevelDB's cache. The other databases don't differentiate between a +write buffer and a cache, so we simply set their cache size to 128 +MB.

+

Sequential Reads

+ + + + + + + + + + + + + +
LevelDB5,210,000 ops/sec
 
(1.29x baseline)
Kyoto TreeDB1,070,000 ops/sec
 
(1.06x baseline)
SQLite3609,000 ops/sec
 
(1.59x baseline)
+ +

Random Reads

+ + + + + + + + + + + + + +
LevelDB190,000 ops/sec
 
(1.47x baseline)
Kyoto TreeDB463,000 ops/sec
 
(3.07x baseline)
SQLite3186,000 ops/sec
 
(1.39x baseline)
+ +

As expected, the read performance of all of the databases increases +when the caches are enlarged. In particular, TreeDB seems to make +very effective use of a cache that is large enough to hold the entire +database.

+ +

B. No Compression Reads

+

For this benchmark, we populated a database with 1 million entries consisting of 16 byte keys and 100 byte values. We compiled LevelDB and Kyoto Cabinet without compression support, so results that are read out from the database are already uncompressed. We've listed the SQLite3 baseline read performance as a point of comparison.

+

Sequential Reads

+ + + + + + + + + + + + + +
LevelDB4,880,000 ops/sec
 
(1.21x baseline)
Kyoto TreeDB1,230,000 ops/sec
 
(3.60x baseline)
SQLite3383,000 ops/sec
 
(1.00x baseline)
+

Random Reads

+ + + + + + + + + + + + + +
LevelDB149,000 ops/sec
 
(1.16x baseline)
Kyoto TreeDB175,000 ops/sec
 
(1.16x baseline)
SQLite3134,000 ops/sec
 
(1.00x baseline)
+ +

Performance of both LevelDB and TreeDB improves a small amount when +compression is disabled. Note however that under different workloads, +performance may very well be better with compression if it allows more +of the working set to fit in memory.

+ +

Note about Ext4 Filesystems

+

The preceding numbers are for an ext3 file system. Synchronous writes are much slower under ext4 (LevelDB drops to ~31 writes / second and TreeDB drops to ~5 writes / second; SQLite3's synchronous writes do not noticeably drop) due to ext4's different handling of fsync / msync calls. Even LevelDB's asynchronous write performance drops somewhat since it spreads its storage across multiple files and issues fsync calls when switching to a new file.

+ +

Acknowledgements

+

Jeff Dean and Sanjay Ghemawat wrote LevelDB. Kevin Tseng wrote and compiled these benchmarks. Mikio Hirabayashi, Scott Hess, and Gabor Cselle provided help and advice.

+ + diff --git a/doc/doc.css b/doc/doc.css new file mode 100644 index 00000000..700c564e --- /dev/null +++ b/doc/doc.css @@ -0,0 +1,89 @@ +body { + margin-left: 0.5in; + margin-right: 0.5in; + background: white; + color: black; +} + +h1 { + margin-left: -0.2in; + font-size: 14pt; +} +h2 { + margin-left: -0in; + font-size: 12pt; +} +h3 { + margin-left: -0in; +} +h4 { + margin-left: -0in; +} +hr { + margin-left: -0in; +} + +/* Definition lists: definition term bold */ +dt { + font-weight: bold; +} + +address { + text-align: center; +} +code,samp,var { + color: blue; +} +kbd { + color: #600000; +} +div.note p { + float: right; + width: 3in; + margin-right: 0%; + padding: 1px; + border: 2px solid #6060a0; + background-color: #fffff0; +} + +ul { + margin-top: -0em; + margin-bottom: -0em; +} + +ol { + margin-top: -0em; + margin-bottom: -0em; +} + +UL.nobullets { + list-style-type: none; + list-style-image: none; + margin-left: -1em; +} + +p { + margin: 1em 0 1em 0; + padding: 0 0 0 0; +} + +pre { + line-height: 1.3em; + padding: 0.4em 0 0.8em 0; + margin: 0 0 0 0; + border: 0 0 0 0; + color: blue; +} + +.datatable { + margin-left: auto; + margin-right: auto; + margin-top: 2em; + margin-bottom: 2em; + border: 1px solid; +} + +.datatable td,th { + padding: 0 0.5em 0 0.5em; + text-align: right; +} diff --git a/doc/impl.html b/doc/impl.html new file mode 100644 index 00000000..e870795d --- /dev/null +++ b/doc/impl.html @@ -0,0 +1,213 @@ + + + + +Leveldb file layout and compactions + + + + +

Files

+ +The implementation of leveldb is similar in spirit to the +representation of a single + +Bigtable tablet (section 5.3). +However the organization of the files that make up the representation +is somewhat different and is explained below. + +

+Each database is represented by a set of files stored in a directory. +There are several different types of files as documented below: +

+

Log files

+

+A log file (*.log) stores a sequence of recent updates. Each update +is appended to the current log file. When the log file reaches a +pre-determined size (approximately 4MB by default), it is converted +to a sorted table (see below) and a new log file is created for future +updates. +

+A copy of the current log file is kept in an in-memory structure (the +memtable). This copy is consulted on every read so that read +operations reflect all logged updates. +

+

Sorted tables

+

+A sorted table (*.sst) stores a sequence of entries sorted by key. +Each entry is either a value for the key, or a deletion marker for the +key. (Deletion markers are kept around to hide obsolete values +present in older sorted tables). +

+The set of sorted tables are organized into a sequence of levels. The +sorted table generated from a log file is placed in a special young +level (also called level-0). When the number of young files exceeds a +certain threshold (currently four), all of the young files are merged +together with all of the overlapping level-1 files to produce a +sequence of new level-1 files (we create a new level-1 file for every +2MB of data.) +

+Files in the young level may contain overlapping keys. However files +in other levels have distinct non-overlapping key ranges. Consider +level number L where L >= 1. When the combined size of files in +level-L exceeds (10^L) MB (i.e., 10MB for level-1, 100MB for level-2, +...), one file in level-L, and all of the overlapping files in +level-(L+1) are merged to form a set of new files for level-(L+1). +These merges have the effect of gradually migrating new updates from +the young level to the largest level using only bulk reads and writes +(i.e., minimizing expensive seeks). + +

Manifest

+

+A MANIFEST file lists the set of sorted tables that make up each +level, the corresponding key ranges, and other important metadata. +A new MANIFEST file (with a new number embedded in the file name) +is created whenever the database is reopened. The MANIFEST file is +formatted as a log, and changes made to the serving state (as files +are added or removed) are appended to this log. +

+

Current

+

+CURRENT is a simple text file that contains the name of the latest +MANIFEST file. +

+

Info logs

+

+Informational messages are printed to files named LOG and LOG.old. +

+

Others

+

+Other files used for miscellaneous purposes may also be present +(LOCK, *.dbtmp). + +

Level 0

+When the log file grows above a certain size (1MB by default): +
    +
  • Create a brand new memtable and log file and direct future updates here +
  • In the background: +
      +
    • Write the contents of the previous memtable to an sstable +
    • Discard the memtable +
    • Delete the old log file and the old memtable +
    • Add the new sstable to the young (level-0) level. +
    +
+ +

Compactions

+ +

+When the size of level L exceeds its limit, we compact it in a +background thread. The compaction picks a file from level L and all +overlapping files from the next level L+1. Note that if a level-L +file overlaps only part of a level-(L+1) file, the entire file at +level-(L+1) is used as an input to the compaction and will be +discarded after the compaction. Aside: because level-0 is special +(files in it may overlap each other), we treat compactions from +level-0 to level-1 specially: a level-0 compaction may pick more than +one level-0 file in case some of these files overlap each other. + +

+A compaction merges the contents of the picked files to produce a +sequence of level-(L+1) files. We switch to producing a new +level-(L+1) file after the current output file has reached the target +file size (2MB). We also switch to a new output file when the key +range of the current output file has grown enough to overlap more then +ten level-(L+2) files. This last rule ensures that a later compaction +of a level-(L+1) file will not pick up too much data from level-(L+2). + +

+The old files are discarded and the new files are added to the serving +state. + +

+Compactions for a particular level rotate through the key space. In +more detail, for each level L, we remember the ending key of the last +compaction at level L. The next compaction for level L will pick the +first file that starts after this key (wrapping around to the +beginning of the key space if there is no such file). + +

+Compactions drop overwritten values. They also drop deletion markers +if there are no higher numbered levels that contain a file whose range +overlaps the current key. + +

Timing

+ +Level-0 compactions will read up to four 1MB files from level-0, and +at worst all the level-1 files (10MB). I.e., we will read 14MB and +write 14MB. + +

+Other than the special level-0 compactions, we will pick one 2MB file +from level L. In the worst case, this will overlap ~ 12 files from +level L+1 (10 because level-(L+1) is ten times the size of level-L, +and another two at the boundaries since the file ranges at level-L +will usually not be aligned with the file ranges at level-L+1). The +compaction will therefore read 26MB and write 26MB. Assuming a disk +IO rate of 100MB/s (ballpark range for modern drives), the worst +compaction cost will be approximately 0.5 second. + +

+If we throttle the background writing to something small, say 10% of +the full 100MB/s speed, a compaction may take up to 5 seconds. If the +user is writing at 10MB/s, we might build up lots of level-0 files +(~50 to hold the 5*10MB). This may signficantly increase the cost of +reads due to the overhead of merging more files together on every +read. + +

+Solution 1: To reduce this problem, we might want to increase the log +switching threshold when the number of level-0 files is large. Though +the downside is that the larger this threshold, the more memory we will +need to hold the corresponding memtable. + +

+Solution 2: We might want to decrease write rate artificially when the +number of level-0 files goes up. + +

+Solution 3: We work on reducing the cost of very wide merges. +Perhaps most of the level-0 files will have their blocks sitting +uncompressed in the cache and we will only need to worry about the +O(N) complexity in the merging iterator. + +

Number of files

+ +Instead of always making 2MB files, we could make larger files for +larger levels to reduce the total file count, though at the expense of +more bursty compactions. Alternatively, we could shard the set of +files into multiple directories. + +

+An experiment on an ext3 filesystem on Feb 04, 2011 shows +the following timings to do 100K file opens in directories with +varying number of files: + + + + + +
Files in directoryMicroseconds to open a file
10009
1000010
10000016
+So maybe even the sharding is not necessary on modern filesystems? + +

Recovery

+ +
    +
  • Read CURRENT to find name of the latest committed MANIFEST +
  • Read the named MANIFEST file +
  • Clean up stale files +
  • We could open all sstables here, but it is probably better to be lazy... +
  • Convert log chunk to a new level-0 sstable +
  • Start directing new writes to a new log file with recovered sequence# +
+ +

Garbage collection of files

+ +DeleteObsoleteFiles() is called at the end of every +compaction and at the end of recovery. It finds the names of all +files in the database. It deletes all log files that are not the +current log file. It deletes all table files that are not referenced +from some level and are not the output of an active compaction. + + + diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 00000000..521d2baf --- /dev/null +++ b/doc/index.html @@ -0,0 +1,549 @@ + + + + +Leveldb + + + +

Leveldb

+
Jeff Dean, Sanjay Ghemawat
+

+The leveldb library provides a persistent key value store. Keys and +values are arbitrary byte arrays. The keys are ordered within the key +value store according to a user-specified comparator function. + +

+

Opening A Database

+

+A leveldb database has a name which corresponds to a file system +directory. All of the contents of database are stored in this +directory. The following example shows how to open a database, +creating it if necessary: +

+

+  #include <assert>
+  #include "leveldb/db.h"
+
+  leveldb::DB* db;
+  leveldb::Options options;
+  options.create_if_missing = true;
+  leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &db);
+  assert(status.ok());
+  ...
+
+If you want to raise an error if the database already exists, add +the following line before the leveldb::DB::Open call: +
+  options.error_if_exists = true;
+
+

Status

+

+You may have noticed the leveldb::Status type above. Values of this +type are returned by most functions in leveldb that may encounter an +error. You can check if such a result is ok, and also print an +associated error message: +

+

+   leveldb::Status s = ...;
+   if (!s.ok()) cerr << s.ToString() << endl;
+
+

Closing A Database

+

+When you are done with a database, just delete the database object. +Example: +

+

+  ... open the db as described above ...
+  ... do something with db ...
+  delete db;
+
+

Reads And Writes

+

+The database provides Put, Delete, and Get methods to +modify/query the database. For example, the following code +moves the value stored under key1 to key2. +

+  std::string value;
+  leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value);
+  if (s.ok()) s = db->Put(leveldb::WriteOptions(), key2, value);
+  if (s.ok()) s = db->Delete(leveldb::WriteOptions(), key1);
+
+ +

Atomic Updates

+

+Note that if the process dies after the Put of key2 but before the +delete of key1, the same value may be left stored under multiple keys. +Such problems can be avoided by using the WriteBatch class to +atomically apply a set of updates: +

+

+  #include "leveldb/write_batch.h"
+  ...
+  std::string value;
+  leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value);
+  if (s.ok()) {
+    leveldb::WriteBatch batch;
+    batch.Delete(key1);
+    batch.Put(key2, value);
+    s = db->Write(leveldb::WriteOptions(), &batch);
+  }
+
+The WriteBatch holds a sequence of edits to be made to the database, +and these edits within the batch are applied in order. Note that we +called Delete before Put so that if key1 is identical to key2, +we do not end up erroneously dropping the value entirely. +

+Apart from its atomicity benefits, WriteBatch may also be used to +speed up bulk updates by placing lots of individual mutations into the +same batch. + +

Synchronous Writes

+By default, each write to leveldb is asynchronous: it +returns after pushing the write from the process into the operating +system. The transfer from operating system memory to the underlying +persistent storage happens asynchronously. The sync flag +can be turned on for a particular write to make the write operation +not return until the data being written has been pushed all the way to +persistent storage. (On Posix systems, this is implemented by calling +either fsync(...) or fdatasync(...) or +msync(..., MS_SYNC) before the write operation returns.) +
+  leveldb::WriteOptions write_options;
+  write_options.sync = true;
+  db->Put(write_options, ...);
+
+Asynchronous writes are often more than a thousand times as fast as +synchronous writes. The downside of asynchronous writes is that a +crash of the machine may cause the last few updates to be lost. Note +that a crash of just the writing process (i.e., not a reboot) will not +cause any loss since even when sync is false, an update +is pushed from the process memory into the operating system before it +is considered done. + +

+Asynchronous writes can often be used safely. For example, when +loading a large amount of data into the database you can handle lost +updates by restarting the bulk load after a crash. A hybrid scheme is +also possible where every Nth write is synchronous, and in the event +of a crash, the bulk load is restarted just after the last synchronous +write finished by the previous run. (The synchronous write can update +a marker that describes where to restart on a crash.) + +

+WriteBatch provides an alternative to asynchronous writes. +Multiple updates may be placed in the same WriteBatch and +applied together using a synchronous write (i.e., +write_options.sync is set to true). The extra cost of +the synchronous write will be amortized across all of the writes in +the batch. + +

+

Concurrency

+

+A database may only be opened by one process at a time. +The leveldb implementation acquires a lock from the +operating system to prevent misuse. Within a single process, the +same leveldb::DB object may be safely shared by multiple +concurrent threads. I.e., different threads may write into or fetch +iterators or call Get on the same database without any +external synchronization (the leveldb implementation will +automatically do the required synchronization). However other objects +(like Iterator and WriteBatch) may require external synchronization. +If two threads share such an object, they must protect access to it +using their own locking protocol. More details are available in +the public header files. +

+

Iteration

+

+The following example demonstrates how to print all key,value pairs +in a database. +

+

+  leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
+  for (it->SeekToFirst(); it->Valid(); it->Next()) {
+    cout << it->key().ToString() << ": "  << it->value().ToString() << endl;
+  }
+  assert(it->status().ok());  // Check for any errors found during the scan
+  delete it;
+
+The following variation shows how to process just the keys in the +range [start,limit): +

+

+  for (it->Seek(start);
+       it->Valid() && it->key().ToString() < limit;
+       it->Next()) {
+    ...
+  }
+
+You can also process entries in reverse order. (Caveat: reverse +iteration may be somewhat slower than forward iteration.) +

+

+  for (it->SeekToLast(); it->Valid(); it->Prev()) {
+    ...
+  }
+
+

Snapshots

+

+Snapshots provide consistent read-only views over the entire state of +the key-value store. ReadOptions::snapshot may be non-NULL to indicate +that a read should operate on a particular version of the DB state. +If ReadOptions::snapshot is NULL, the read will operate on an +implicit snapshot of the current state. +

+Snapshots are created by the DB::GetSnapshot() method: +

+

+  leveldb::ReadOptions options;
+  options.snapshot = db->GetSnapshot();
+  ... apply some updates to db ...
+  leveldb::Iterator* iter = db->NewIterator(options);
+  ... read using iter to view the state when the snapshot was created ...
+  delete iter;
+  db->ReleaseSnapshot(options.snapshot);
+
+Note that when a snapshot is no longer needed, it should be released +using the DB::ReleaseSnapshot interface. This allows the +implementation to get rid of state that was being maintained just to +support reading as of that snapshot. +

Slice

+

+The return value of the it->key() and it->value() calls above +are instances of the leveldb::Slice type. Slice is a simple +structure that contains a length and a pointer to an external byte +array. Returning a Slice is a cheaper alternative to returning a +std::string since we do not need to copy potentially large keys and +values. In addition, leveldb methods do not return null-terminated +C-style strings since leveldb keys and values are allowed to +contain '\0' bytes. +

+C++ strings and null-terminated C-style strings can be easily converted +to a Slice: +

+

+   leveldb::Slice s1 = "hello";
+
+   std::string str("world");
+   leveldb::Slice s2 = str;
+
+A Slice can be easily converted back to a C++ string: +
+   std::string str = s1.ToString();
+   assert(str == std::string("hello"));
+
+Be careful when using Slices since it is up to the caller to ensure that +the external byte array into which the Slice points remains live while +the Slice is in use. For example, the following is buggy: +

+

+   leveldb::Slice slice;
+   if (...) {
+     std::string str = ...;
+     slice = str;
+   }
+   Use(slice);
+
+When the if statement goes out of scope, str will be destroyed and the +backing storage for slice will disappear. +

+

Comparators

+

+The preceding examples used the default ordering function for key, +which orders bytes lexicographically. You can however supply a custom +comparator when opening a database. For example, suppose each +database key consists of two numbers and we should sort by the first +number, breaking ties by the second number. First, define a proper +subclass of leveldb::Comparator that expresses these rules: +

+

+  class TwoPartComparator : public leveldb::Comparator {
+   public:
+    // Three-way comparison function:
+    //   if a < b: negative result
+    //   if a > b: positive result
+    //   else: zero result
+    int Compare(const leveldb::Slice& a, const leveldb::Slice& b) const {
+      int a1, a2, b1, b2;
+      ParseKey(a, &a1, &a2);
+      ParseKey(b, &b1, &b2);
+      if (a1 < b1) return -1;
+      if (a1 > b1) return +1;
+      if (a2 < b2) return -1;
+      if (a2 > b2) return +1;
+      return 0;
+    }
+
+    // Ignore the following methods for now:
+    const char* Name() const { return "TwoPartComparator"; }
+    void FindShortestSeparator(std::string*, const leveldb::Slice&) const { }
+    void FindShortSuccessor(std::string*) const { }
+  };
+
+Now create a database using this custom comparator: +

+

+  TwoPartComparator cmp;
+  leveldb::DB* db;
+  leveldb::Options options;
+  options.create_if_missing = true;
+  options.comparator = &cmp;
+  leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &db);
+  ...
+
+

Backwards compatibility

+

+The result of the comparator's Name method is attached to the +database when it is created, and is checked on every subsequent +database open. If the name changes, the leveldb::DB::Open call will +fail. Therefore, change the name if and only if the new key format +and comparison function are incompatible with existing databases, and +it is ok to discard the contents of all existing databases. +

+You can however still gradually evolve your key format over time with +a little bit of pre-planning. For example, you could store a version +number at the end of each key (one byte should suffice for most uses). +When you wish to switch to a new key format (e.g., adding an optional +third part to the keys processed by TwoPartComparator), +(a) keep the same comparator name (b) increment the version number +for new keys (c) change the comparator function so it uses the +version numbers found in the keys to decide how to interpret them. +

+

Performance

+

+Performance can be tuned by changing the default values of the +types defined in include/leveldb/options.h. + +

+

Block size

+

+leveldb groups adjacent keys together into the same block and such a +block is the unit of transfer to and from persistent storage. The +default block size is approximately 4096 uncompressed bytes. +Applications that mostly do bulk scans over the contents of the +database may wish to increase this size. Applications that do a lot +of point reads of small values may wish to switch to a smaller block +size if performance measurements indicate an improvement. There isn't +much benefit in using blocks smaller than one kilobyte, or larger than +a few megabytes. Also note that compression will be more effective +with larger block sizes. +

+

Compression

+

+Each block is individually compressed before being written to +persistent storage. Compression is on by default since the default +compression method is very fast, and is automatically disabled for +uncompressible data. In rare cases, applications may want to disable +compression entirely, but should only do so if benchmarks show a +performance improvement: +

+

+  leveldb::Options options;
+  options.compression = leveldb::kNoCompression;
+  ... leveldb::DB::Open(options, name, ...) ....
+
+

Cache

+

+The contents of the database are stored in a set of files in the +filesystem and each file stores a sequence of compressed blocks. If +options.cache is non-NULL, it is used to cache frequently used +uncompressed block contents. +

+

+  #include "leveldb/cache.h"
+
+  leveldb::Options options;
+  options.cache = leveldb::NewLRUCache(100 * 1048576);  // 100MB cache
+  leveldb::DB* db;
+  leveldb::DB::Open(options, name, &db);
+  ... use the db ...
+  delete db
+  delete options.cache;
+
+Note that the cache holds uncompressed data, and therefore it should +be sized according to application level data sizes, without any +reduction from compression. (Caching of compressed blocks is left to +the operating system buffer cache, or any custom Env +implementation provided by the client.) +

+When performing a bulk read, the application may wish to disable +caching so that the data processed by the bulk read does not end up +displacing most of the cached contents. A per-iterator option can be +used to achieve this: +

+

+  leveldb::ReadOptions options;
+  options.fill_cache = false;
+  leveldb::Iterator* it = db->NewIterator(options);
+  for (it->SeekToFirst(); it->Valid(); it->Next()) {
+    ...
+  }
+
+

Key Layout

+

+Note that the unit of disk transfer and caching is a block. Adjacent +keys (according to the database sort order) will usually be placed in +the same block. Therefore the application can improve its performance +by placing keys that are accessed together near each other and placing +infrequently used keys in a separate region of the key space. +

+For example, suppose we are implementing a simple file system on top +of leveldb. The types of entries we might wish to store are: +

+

+   filename -> permission-bits, length, list of file_block_ids
+   file_block_id -> data
+
+We might want to prefix filename keys with one letter (say '/') and the +file_block_id keys with a different letter (say '0') so that scans +over just the metadata do not force us to fetch and cache bulky file +contents. +

+

Filters

+

+Because of the way leveldb data is organized on disk, +a single Get() call may involve multiple reads from disk. +The optional FilterPolicy mechanism can be used to reduce +the number of disk reads substantially. +

+   leveldb::Options options;
+   options.filter_policy = NewBloomFilter(10);
+   leveldb::DB* db;
+   leveldb::DB::Open(options, "/tmp/testdb", &db);
+   ... use the database ...
+   delete db;
+   delete options.filter_policy;
+
+The preceding code associates a +Bloom filter +based filtering policy with the database. Bloom filter based +filtering relies on keeping some number of bits of data in memory per +key (in this case 10 bits per key since that is the argument we passed +to NewBloomFilter). This filter will reduce the number of unnecessary +disk reads needed for Get() calls by a factor of +approximately a 100. Increasing the bits per key will lead to a +larger reduction at the cost of more memory usage. We recommend that +applications whose working set does not fit in memory and that do a +lot of random reads set a filter policy. +

+If you are using a custom comparator, you should ensure that the filter +policy you are using is compatible with your comparator. For example, +consider a comparator that ignores trailing spaces when comparing keys. +NewBloomFilter must not be used with such a comparator. +Instead, the application should provide a custom filter policy that +also ignores trailing spaces. For example: +

+  class CustomFilterPolicy : public leveldb::FilterPolicy {
+   private:
+    FilterPolicy* builtin_policy_;
+   public:
+    CustomFilterPolicy() : builtin_policy_(NewBloomFilter(10)) { }
+    ~CustomFilterPolicy() { delete builtin_policy_; }
+
+    const char* Name() const { return "IgnoreTrailingSpacesFilter"; }
+
+    void CreateFilter(const Slice* keys, int n, std::string* dst) const {
+      // Use builtin bloom filter code after removing trailing spaces
+      std::vector<Slice> trimmed(n);
+      for (int i = 0; i < n; i++) {
+        trimmed[i] = RemoveTrailingSpaces(keys[i]);
+      }
+      return builtin_policy_->CreateFilter(&trimmed[i], n, dst);
+    }
+
+    bool KeyMayMatch(const Slice& key, const Slice& filter) const {
+      // Use builtin bloom filter code after removing trailing spaces
+      return builtin_policy_->KeyMayMatch(RemoveTrailingSpaces(key), filter);
+    }
+  };
+
+

+Advanced applications may provide a filter policy that does not use +a bloom filter but uses some other mechanism for summarizing a set +of keys. See leveldb/filter_policy.h for detail. +

+

Checksums

+

+leveldb associates checksums with all data it stores in the file system. +There are two separate controls provided over how aggressively these +checksums are verified: +

+

    +
  • ReadOptions::verify_checksums may be set to true to force + checksum verification of all data that is read from the file system on + behalf of a particular read. By default, no such verification is + done. +

    +

  • Options::paranoid_checks may be set to true before opening a + database to make the database implementation raise an error as soon as + it detects an internal corruption. Depending on which portion of the + database has been corrupted, the error may be raised when the database + is opened, or later by another database operation. By default, + paranoid checking is off so that the database can be used even if + parts of its persistent storage have been corrupted. +

    + If a database is corrupted (perhaps it cannot be opened when + paranoid checking is turned on), the leveldb::RepairDB function + may be used to recover as much of the data as possible +

    +

+

Approximate Sizes

+

+The GetApproximateSizes method can used to get the approximate +number of bytes of file system space used by one or more key ranges. +

+

+   leveldb::Range ranges[2];
+   ranges[0] = leveldb::Range("a", "c");
+   ranges[1] = leveldb::Range("x", "z");
+   uint64_t sizes[2];
+   leveldb::Status s = db->GetApproximateSizes(ranges, 2, sizes);
+
+The preceding call will set sizes[0] to the approximate number of +bytes of file system space used by the key range [a..c) and +sizes[1] to the approximate number of bytes used by the key range +[x..z). +

+

Environment

+

+All file operations (and other operating system calls) issued by the +leveldb implementation are routed through a leveldb::Env object. +Sophisticated clients may wish to provide their own Env +implementation to get better control. For example, an application may +introduce artificial delays in the file IO paths to limit the impact +of leveldb on other activities in the system. +

+

+  class SlowEnv : public leveldb::Env {
+    .. implementation of the Env interface ...
+  };
+
+  SlowEnv env;
+  leveldb::Options options;
+  options.env = &env;
+  Status s = leveldb::DB::Open(options, ...);
+
+

Porting

+

+leveldb may be ported to a new platform by providing platform +specific implementations of the types/methods/functions exported by +leveldb/port/port.h. See leveldb/port/port_example.h for more +details. +

+In addition, the new platform may need a new default leveldb::Env +implementation. See leveldb/util/env_posix.h for an example. + +

Other Information

+ +

+Details about the leveldb implementation may be found in +the following documents: +

+ + + diff --git a/doc/log_format.txt b/doc/log_format.txt new file mode 100644 index 00000000..3a0414b6 --- /dev/null +++ b/doc/log_format.txt @@ -0,0 +1,75 @@ +The log file contents are a sequence of 32KB blocks. The only +exception is that the tail of the file may contain a partial block. + +Each block consists of a sequence of records: + block := record* trailer? + record := + checksum: uint32 // crc32c of type and data[] + length: uint16 + type: uint8 // One of FULL, FIRST, MIDDLE, LAST + data: uint8[length] + +A record never starts within the last six bytes of a block (since it +won't fit). Any leftover bytes here form the trailer, which must +consist entirely of zero bytes and must be skipped by readers. + +Aside: if exactly seven bytes are left in the current block, and a new +non-zero length record is added, the writer must emit a FIRST record +(which contains zero bytes of user data) to fill up the trailing seven +bytes of the block and then emit all of the user data in subsequent +blocks. + +More types may be added in the future. Some Readers may skip record +types they do not understand, others may report that some data was +skipped. + +FULL == 1 +FIRST == 2 +MIDDLE == 3 +LAST == 4 + +The FULL record contains the contents of an entire user record. + +FIRST, MIDDLE, LAST are types used for user records that have been +split into multiple fragments (typically because of block boundaries). +FIRST is the type of the first fragment of a user record, LAST is the +type of the last fragment of a user record, and MID is the type of all +interior fragments of a user record. + +Example: consider a sequence of user records: + A: length 1000 + B: length 97270 + C: length 8000 +A will be stored as a FULL record in the first block. + +B will be split into three fragments: first fragment occupies the rest +of the first block, second fragment occupies the entirety of the +second block, and the third fragment occupies a prefix of the third +block. This will leave six bytes free in the third block, which will +be left empty as the trailer. + +C will be stored as a FULL record in the fourth block. + +=================== + +Some benefits over the recordio format: + +(1) We do not need any heuristics for resyncing - just go to next +block boundary and scan. If there is a corruption, skip to the next +block. As a side-benefit, we do not get confused when part of the +contents of one log file are embedded as a record inside another log +file. + +(2) Splitting at approximate boundaries (e.g., for mapreduce) is +simple: find the next block boundary and skip records until we +hit a FULL or FIRST record. + +(3) We do not need extra buffering for large records. + +Some downsides compared to recordio format: + +(1) No packing of tiny records. This could be fixed by adding a new +record type, so it is a shortcoming of the current implementation, +not necessarily the format. + +(2) No compression. Again, this could be fixed by adding new record types. diff --git a/doc/table_format.txt b/doc/table_format.txt new file mode 100644 index 00000000..d0f3065e --- /dev/null +++ b/doc/table_format.txt @@ -0,0 +1,102 @@ +File format +=========== + + + [data block 1] + [data block 2] + ... + [data block N] + [meta block 1] + ... + [meta block K] + [metaindex block] + [index block] + [Footer] (fixed size; starts at file_size - sizeof(Footer)) + + +The file contains internal pointers. Each such pointer is called +a BlockHandle and contains the following information: + offset: varint64 + size: varint64 + +(1) The sequence of key/value pairs in the file are stored in sorted +order and partitioned into a sequence of data blocks. These blocks +come one after another at the beginning of the file. Each data block +is formatted according to the code in block_builder.cc, and then +optionally compressed. + +(2) After the data blocks we store a bunch of meta blocks. The +supported meta block types are described below. More meta block types +may be added in the future. Each meta block is again formatted using +block_builder.cc and then optionally compressed. + +(3) A "metaindex" block. It contains one entry for every other meta +block where the key is the name of the meta block and the value is a +BlockHandle pointing to that meta block. + +(4) An "index" block. This block contains one entry per data block, +where the key is a string >= last key in that data block and before +the first key in the successive data block. The value is the +BlockHandle for the data block. + +(6) At the very end of the file is a fixed length footer that contains +the BlockHandle of the metaindex and index blocks as well as a magic number. + metaindex_handle: char[p]; // Block handle for metaindex + index_handle: char[q]; // Block handle for index + padding: char[40-p-q]; // 0 bytes to make fixed length + // (40==2*BlockHandle::kMaxEncodedLength) + magic: fixed64; // == 0xdb4775248b80fb57 + +"filter" Meta Block +------------------- + +If a "FilterPolicy" was specified when the database was opened, a +filter block is stored in each table. The "metaindex" block contains +an entry that maps from "filter." to the BlockHandle for the filter +block where "" is the string returned by the filter policy's +"Name()" method. + +The filter block stores a sequence of filters, where filter i contains +the output of FilterPolicy::CreateFilter() on all keys that are stored +in a block whose file offset falls within the range + + [ i*base ... (i+1)*base-1 ] + +Currently, "base" is 2KB. So for example, if blocks X and Y start in +the range [ 0KB .. 2KB-1 ], all of the keys in X and Y will be +converted to a filter by calling FilterPolicy::CreateFilter(), and the +resulting filter will be stored as the first filter in the filter +block. + +The filter block is formatted as follows: + + [filter 0] + [filter 1] + [filter 2] + ... + [filter N-1] + + [offset of filter 0] : 4 bytes + [offset of filter 1] : 4 bytes + [offset of filter 2] : 4 bytes + ... + [offset of filter N-1] : 4 bytes + + [offset of beginning of offset array] : 4 bytes + lg(base) : 1 byte + +The offset array at the end of the filter block allows efficient +mapping from a data block offset to the corresponding filter. + +"stats" Meta Block +------------------ + +This meta block contains a bunch of stats. The key is the name +of the statistic. The value contains the statistic. +TODO(postrelease): record following stats. + data size + index size + key size (uncompressed) + value size (uncompressed) + number of entries + number of data blocks diff --git a/fbcode.clang31.sh b/fbcode.clang31.sh new file mode 100644 index 00000000..bcedad20 --- /dev/null +++ b/fbcode.clang31.sh @@ -0,0 +1,50 @@ +#!/bin/sh +# +# Set environment variables so that we can compile leveldb using +# fbcode settings. It uses the latest g++ compiler and also +# uses jemalloc + +TOOLCHAIN_REV=f365dbeae46a30414a2874a6f45e73e10f1caf7d +TOOLCHAIN_EXECUTABLES="/mnt/gvfs/third-party/$TOOLCHAIN_REV/centos5.2-native" +TOOLCHAIN_LIB_BASE="/mnt/gvfs/third-party/$TOOLCHAIN_REV/gcc-4.7.1-glibc-2.14.1" +TOOL_JEMALLOC=jemalloc-3.0.0/2f45f3a +GLIBC_RUNTIME_PATH=/usr/local/fbcode/gcc-4.7.1-glibc-2.14.1 + +# location of snappy headers and libraries +SNAPPY_INCLUDE=" -I $TOOLCHAIN_LIB_BASE/snappy/snappy-1.0.3/7518bbe/include" +SNAPPY_LIBS=" $TOOLCHAIN_LIB_BASE/snappy/snappy-1.0.3/7518bbe/lib/libsnappy.a" + +# location of boost headers and libraries +THRIFT_INCLUDE=" -I $TOOLCHAIN_LIB_BASE/boost/boost-1.48.0/bef9365/include -std=gnu++0x" +THRIFT_INCLUDE+=" -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp" +THRIFT_LIBS=" -L $TOOLCHAIN_LIB_BASE/boost/boost-1.48.0/bef9365/lib" + +# location of libevent +LIBEVENT_INCLUDE=" -I $TOOLCHAIN_LIB_BASE/libevent/libevent-1.4.14b/91ddd43/include" +LIBEVENT_LIBS=" -L $TOOLCHAIN_LIB_BASE/libevent/libevent-1.4.14b/91ddd43/lib" + +# use Intel SSE support for checksum calculations +export USE_SSE=" -msse -msse4.2 " + +CC="$TOOLCHAIN_EXECUTABLES/clang/clang-3.1/6ca8a59/bin/clang $CLANG_INCLUDES" +CXX="$TOOLCHAIN_EXECUTABLES/clang/clang-3.1/6ca8a59/bin/clang++ $CLANG_INCLUDES $JINCLUDE $SNAPPY_INCLUDE $THRIFT_INCLUDE $LIBEVENT_INCLUDE" +AR=$TOOLCHAIN_EXECUTABLES/binutils/binutils-2.21.1/da39a3e/bin/ar +RANLIB=$TOOLCHAIN_EXECUTABLES/binutils/binutils-2.21.1/da39a3e/bin/ranlib + +CFLAGS="-B$TOOLCHAIN_EXECUTABLES/binutils/binutils-2.21.1/da39a3e/bin -nostdlib -nostdinc -isystem $TOOLCHAIN_LIB_BASE/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1 -isystem $TOOLCHAIN_LIB_BASE/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/x86_64-facebook-linux -isystem $TOOLCHAIN_LIB_BASE/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/backward -isystem $TOOLCHAIN_LIB_BASE/glibc/glibc-2.14.1/99df8fc/include -isystem $TOOLCHAIN_LIB_BASE/clang/clang-3.1/c8f7279/lib/clang/3.1/include -isystem $TOOLCHAIN_LIB_BASE/kernel-headers/kernel-headers-3.2.18_70_fbk11_00129_gc8882d0/da39a3e/include/linux -isystem $TOOLCHAIN_LIB_BASE/kernel-headers/kernel-headers-3.2.18_70_fbk11_00129_gc8882d0/da39a3e/include -Wall -Wno-sign-compare -Wno-unused-variable -Winvalid-pch -Wno-deprecated -Woverloaded-virtual" +CXXFLAGS="$CFLAGS -nostdinc++ -std=gnu++0x" + +CFLAGS+=" -I $TOOLCHAIN_LIB_BASE/jemalloc/$TOOL_JEMALLOC/include -DHAVE_JEMALLOC" + +EXEC_LDFLAGS=" -Wl,--whole-archive $TOOLCHAIN_LIB_BASE/jemalloc/$TOOL_JEMALLOC/lib/libjemalloc.a" +EXEC_LDFLAGS+=" -Wl,--no-whole-archive $TOOLCHAIN_LIB_BASE/libunwind/libunwind-1.0.1/91ddd43/lib/libunwind.a" +EXEC_LDFLAGS+=" $HDFSLIB $SNAPPY_LIBS $THRIFT_LIBS $LIBEVENT_LIBS" +EXEC_LDFLAGS+=" -Wl,--dynamic-linker,$GLIBC_RUNTIME_PATH/lib/ld-linux-x86-64.so.2" +EXEC_LDFLAGS+=" -B$TOOLCHAIN_EXECUTABLES/binutils/binutils-2.21.1/da39a3e/bin" + +PLATFORM_LDFLAGS="-L$TOOLCHAIN_LIB_BASE/libgcc/libgcc-4.7.1/afc21dc/lib -L$TOOLCHAIN_LIB_BASE/glibc/glibc-2.14.1/99df8fc/lib" + +EXEC_LDFLAGS_SHARED="$SNAPPY_LIBS" +SNAPPY_LDFLAGS="$SNAPPY_LIBS" + +export CC CXX AR RANLIB CFLAGS EXEC_LDFLAGS EXEC_LDFLAGS_SHARED SNAPPY_LDFLAGS diff --git a/fbcode.gcc471.sh b/fbcode.gcc471.sh new file mode 100644 index 00000000..5a20dce0 --- /dev/null +++ b/fbcode.gcc471.sh @@ -0,0 +1,59 @@ +#!/bin/sh +# +# Set environment variables so that we can compile leveldb using +# fbcode settings. It uses the latest g++ compiler and also +# uses jemalloc + +TOOLCHAIN_REV=20d3328ac30f633840ce819ad03019f415267a86 +TOOLCHAIN_EXECUTABLES="/mnt/gvfs/third-party/$TOOLCHAIN_REV/centos5.2-native" +TOOLCHAIN_LIB_BASE="/mnt/gvfs/third-party/$TOOLCHAIN_REV/gcc-4.7.1-glibc-2.14.1" +TOOL_JEMALLOC=jemalloc-3.0.0/69dc57c + +# location of libhdfs libraries +if test "$USE_HDFS"; then + JAVA_HOME="/usr/local/jdk-6u22-64" + JINCLUDE="-I$JAVA_HOME/include -I$JAVA_HOME/include/linux" + GLIBC_RUNTIME_PATH="/usr/local/fbcode/gcc-4.7.1-glibc-2.14.1" + HDFSLIB=" -Wl,--no-whole-archive hdfs/libhdfs.a -L$JAVA_HOME/jre/lib/amd64 " + HDFSLIB+=" -L$JAVA_HOME/jre/lib/amd64/server -L$GLIBC_RUNTIME_PATH/lib " + HDFSLIB+=" -ldl -lverify -ljava -ljvm " +fi + +# location of snappy headers and libraries +SNAPPY_INCLUDE=" -I $TOOLCHAIN_LIB_BASE/snappy/snappy-1.0.3/7518bbe/include" +SNAPPY_LIBS=" $TOOLCHAIN_LIB_BASE/snappy/snappy-1.0.3/7518bbe/lib/libsnappy.a" + +# location of zlib headers and libraries +ZLIB_INCLUDE=" -I $TOOLCHAIN_LIB_BASE/zlib/zlib-1.2.5/91ddd43/include" +ZLIB_LIBS=" $TOOLCHAIN_LIB_BASE/zlib/zlib-1.2.5/91ddd43/lib/libz.a" + +# location of boost headers and libraries +THRIFT_INCLUDE=" -I $TOOLCHAIN_LIB_BASE/boost/boost-1.48.0/bef9365/include -std=gnu++0x" +THRIFT_INCLUDE+=" -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp" +THRIFT_LIBS=" -L $TOOLCHAIN_LIB_BASE/boost/boost-1.48.0/bef9365/lib" + +# location of libevent +LIBEVENT_INCLUDE=" -I $TOOLCHAIN_LIB_BASE/libevent/libevent-1.4.14b/91ddd43/include" +LIBEVENT_LIBS=" -L $TOOLCHAIN_LIB_BASE/libevent/libevent-1.4.14b/91ddd43/lib" + +# use Intel SSE support for checksum calculations +export USE_SSE=" -msse -msse4.2 " + +CC="$TOOLCHAIN_EXECUTABLES/gcc/gcc-4.7.1-glibc-2.14.1/bin/gcc" +CXX="$TOOLCHAIN_EXECUTABLES/gcc/gcc-4.7.1-glibc-2.14.1/bin/g++ $JINCLUDE $SNAPPY_INCLUDE $ZLIB_INCLUDE $THRIFT_INCLUDE $LIBEVENT_INCLUDE" +AR=$TOOLCHAIN_EXECUTABLES/binutils/binutils-2.21.1/da39a3e/bin/ar +RANLIB=$TOOLCHAIN_EXECUTABLES/binutils/binutils-2.21.1/da39a3e/bin/ranlib + +CFLAGS="-B$TOOLCHAIN_EXECUTABLES/binutils/binutils-2.21.1/bin/gold -m64 -mtune=generic -fPIC" +CFLAGS+=" -I $TOOLCHAIN_LIB_BASE/jemalloc/$TOOL_JEMALLOC/include -DHAVE_JEMALLOC" + +EXEC_LDFLAGS=" -Wl,--whole-archive $TOOLCHAIN_LIB_BASE/jemalloc/$TOOL_JEMALLOC/lib/libjemalloc.a" +EXEC_LDFLAGS+=" -Wl,--no-whole-archive $TOOLCHAIN_LIB_BASE/libunwind/libunwind-20100812_experimental/91ddd43/lib/libunwind.a" +EXEC_LDFLAGS+=" $HDFSLIB $SNAPPY_LIBS $ZLIB_LIBS $THRIFT_LIBS $LIBEVENT_LIBS" + +PLATFORM_LDFLAGS="-L$TOOLCHAIN_LIB_BASE/libgcc/libgcc-4.7.1/afc21dc/lib -L$TOOLCHAIN_LIB_BASE/glibc/glibc-2.14.1/99df8fc/lib" + +EXEC_LDFLAGS_SHARED="$SNAPPY_LIBS $ZLIB_LIBS" +SNAPPY_LDFLAGS="$SNAPPY_LIBS $ZLIB_LIBS" + +export CC CXX AR RANLIB CFLAGS EXEC_LDFLAGS EXEC_LDFLAGS_SHARED SNAPPY_LDFLAGS diff --git a/hdfs/README b/hdfs/README new file mode 100644 index 00000000..2d4da29d --- /dev/null +++ b/hdfs/README @@ -0,0 +1,26 @@ +This directory contains the hdfs extensions needed to make leveldb store +files in HDFS. + +The hdfs.h file is copied from the Apache Hadoop 1.0 source code. +It defines the libhdfs library +(http://hadoop.apache.org/common/docs/r0.20.2/libhdfs.html) to access +data in HDFS. The libhdfs.a is copied from the Apache Hadoop 1.0 build. +It implements the API defined in hdfs.h. If your hadoop cluster is running +a different hadoop release, then install these two files manually from your +hadoop distribution and then recompile leveldb. + +The env_hdfs.h file defines the leveldb objects that are needed to talk to an +underlying filesystem. + +If you want to compile leveldb with hdfs support, please set the following +enviroment variables appropriately: + USE_HDFS=1 + JAVA_HOME=/usr/local/jdk-6u22-64 + LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/jdk-6u22-64/jre/lib/amd64/server:/usr/local/jdk-6u22-64/jre/lib/amd64/:./snappy/libs + make clean all db_bench + +To run dbbench, + set CLASSPATH to include your hadoop distribution + db_bench --hdfs="hdfs://hbaseudbperf001.snc1.facebook.com:9000" + + diff --git a/hdfs/env_hdfs.h b/hdfs/env_hdfs.h new file mode 100644 index 00000000..964a1cab --- /dev/null +++ b/hdfs/env_hdfs.h @@ -0,0 +1,304 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// Copyright (c) 2012 Facebook. All rights reserved. + +#ifndef LEVELDB_HDFS_FILE_H +#define LEVELDB_HDFS_FILE_H + +#include +#include +#include +#include +#include +#include "leveldb/env.h" +#include "leveldb/status.h" + +#ifdef USE_HDFS +#include "hdfs/hdfs.h" + +namespace leveldb { + +static const std::string kProto = "hdfs://"; +static const std::string pathsep = "/"; + +// Thrown during execution when there is an issue with the supplied +// arguments. +class HdfsUsageException : public std::exception { }; + +// A simple exception that indicates something went wrong that is not +// recoverable. The intention is for the message to be printed (with +// nothing else) and the process terminate. +class HdfsFatalException : public std::exception { +public: + explicit HdfsFatalException(const std::string& s) : what_(s) { } + virtual ~HdfsFatalException() throw() { } + virtual const char* what() const throw() { + return what_.c_str(); + } +private: + const std::string what_; +}; + +// +// The HDFS environment for leveldb. This class overrides all the +// file/dir access methods and delegates the thread-mgmt methods to the +// default posix environment. +// +class HdfsEnv : public Env { + + public: + HdfsEnv(const std::string& fsname) : fsname_(fsname) { + posixEnv = Env::Default(); + fileSys_ = connectToPath(fsname_); + } + + virtual ~HdfsEnv() { + fprintf(stderr, "Destroying HdfsEnv::Default()\n"); + hdfsDisconnect(fileSys_); + } + + virtual Status NewSequentialFile(const std::string& fname, + SequentialFile** result); + + virtual Status NewRandomAccessFile(const std::string& fname, + RandomAccessFile** result); + + virtual Status NewWritableFile(const std::string& fname, + WritableFile** result); + + virtual bool FileExists(const std::string& fname); + + virtual Status GetChildren(const std::string& path, + std::vector* result); + + virtual Status DeleteFile(const std::string& fname); + + virtual Status CreateDir(const std::string& name); + + virtual Status CreateDirIfMissing(const std::string& name); + + virtual Status DeleteDir(const std::string& name); + + virtual Status GetFileSize(const std::string& fname, uint64_t* size); + + virtual Status GetFileModificationTime(const std::string& fname, + uint64_t* file_mtime); + + virtual Status RenameFile(const std::string& src, const std::string& target); + + virtual Status LockFile(const std::string& fname, FileLock** lock); + + virtual Status UnlockFile(FileLock* lock); + + virtual Status NewLogger(const std::string& fname, Logger** result); + + virtual void Schedule( void (*function)(void* arg), void* arg) { + posixEnv->Schedule(function, arg); + } + + virtual void StartThread(void (*function)(void* arg), void* arg) { + posixEnv->StartThread(function, arg); + } + + virtual Status GetTestDirectory(std::string* path) { + return posixEnv->GetTestDirectory(path); + } + + virtual uint64_t NowMicros() { + return posixEnv->NowMicros(); + } + + virtual void SleepForMicroseconds(int micros) { + posixEnv->SleepForMicroseconds(micros); + } + + virtual Status GetHostName(char* name, uint64_t len) { + return posixEnv->GetHostName(name, len); + } + + virtual Status GetCurrentTime(int64_t* unix_time) { + return posixEnv->GetCurrentTime(unix_time); + } + + virtual Status GetAbsolutePath(const std::string& db_path, + std::string* output_path) { + return posixEnv->GetAbsolutePath(db_path, output_path); + } + + virtual void SetBackgroundThreads(int number) { + posixEnv->SetBackgroundThreads(number); + } + + virtual std::string TimeToString(uint64_t number) { + return posixEnv->TimeToString(number); + } + + static uint64_t gettid() { + assert(sizeof(pthread_t) <= sizeof(uint64_t)); + return (uint64_t)pthread_self(); + } + + private: + std::string fsname_; // string of the form "hdfs://hostname:port/" + hdfsFS fileSys_; // a single FileSystem object for all files + Env* posixEnv; // This object is derived from Env, but not from + // posixEnv. We have posixnv as an encapsulated + // object here so that we can use posix timers, + // posix threads, etc. + + /** + * If the URI is specified of the form hdfs://server:port/path, + * then connect to the specified cluster + * else connect to default. + */ + hdfsFS connectToPath(const std::string& uri) { + if (uri.empty()) { + return NULL; + } + if (uri.find(kProto) != 0) { + // uri doesn't start with hdfs:// -> use default:0, which is special + // to libhdfs. + return hdfsConnectNewInstance("default", 0); + } + const std::string hostport = uri.substr(kProto.length()); + + std::vector parts; + split(hostport, ':', parts); + if (parts.size() != 2) { + throw HdfsFatalException("Bad uri for hdfs " + uri); + } + // parts[0] = hosts, parts[1] = port/xxx/yyy + std::string host(parts[0]); + std::string remaining(parts[1]); + + int rem = remaining.find(pathsep); + std::string portStr = (rem == 0 ? remaining : + remaining.substr(0, rem)); + + tPort port; + port = atoi(portStr.c_str()); + if (port == 0) { + throw HdfsFatalException("Bad host-port for hdfs " + uri); + } + hdfsFS fs = hdfsConnectNewInstance(host.c_str(), port); + return fs; + } + + void split(const std::string &s, char delim, + std::vector &elems) { + elems.clear(); + size_t prev = 0; + size_t pos = s.find(delim); + while (pos != std::string::npos) { + elems.push_back(s.substr(prev, pos)); + prev = pos + 1; + pos = s.find(delim, prev); + } + elems.push_back(s.substr(prev, s.size())); + } +}; + +} // namespace leveldb + +#else // USE_HDFS + + +namespace leveldb { + +static const Status notsup; + +class HdfsEnv : public Env { + + public: + HdfsEnv(const std::string& fsname) { + fprintf(stderr, "You have not build leveldb with HDFS support\n"); + fprintf(stderr, "Please see hdfs/README for details\n"); + throw new std::exception(); + } + + virtual ~HdfsEnv() { + } + + virtual Status NewSequentialFile(const std::string& fname, + unique_ptr* result); + + virtual Status NewRandomAccessFile(const std::string& fname, + unique_ptr* result) { + return notsup; + } + + virtual Status NewWritableFile(const std::string& fname, + unique_ptr* result) { + return notsup; + } + + virtual bool FileExists(const std::string& fname){return false;} + + virtual Status GetChildren(const std::string& path, + std::vector* result){return notsup;} + + virtual Status DeleteFile(const std::string& fname){return notsup;} + + virtual Status CreateDir(const std::string& name){return notsup;} + + virtual Status CreateDirIfMissing(const std::string& name){return notsup;} + + virtual Status DeleteDir(const std::string& name){return notsup;} + + virtual Status GetFileSize(const std::string& fname, uint64_t* size){return notsup;} + + virtual Status GetFileModificationTime(const std::string& fname, + uint64_t* time) { + return notsup; + } + + virtual Status RenameFile(const std::string& src, const std::string& target){return notsup;} + + virtual Status LockFile(const std::string& fname, FileLock** lock){return notsup;} + + virtual Status UnlockFile(FileLock* lock){return notsup;} + + virtual Status NewLogger(const std::string& fname, + shared_ptr* result){return notsup;} + + virtual void Schedule( void (*function)(void* arg), void* arg) {} + + virtual void StartThread(void (*function)(void* arg), void* arg) {} + + virtual Status GetTestDirectory(std::string* path) {return notsup;} + + virtual uint64_t NowMicros() {return 0;} + + virtual void SleepForMicroseconds(int micros) {} + + virtual Status GetHostName(char* name, uint64_t len) {return notsup;} + + virtual Status GetCurrentTime(int64_t* unix_time) {return notsup;} + + virtual Status GetAbsolutePath(const std::string& db_path, + std::string* outputpath) {return notsup;} + + virtual void SetBackgroundThreads(int number) {} + + virtual std::string TimeToString(uint64_t number) { return "";} +}; +} + +#endif // USE_HDFS + +#endif // LEVELDB_HDFS_FILE_H diff --git a/hdfs/hdfs.h b/hdfs/hdfs.h new file mode 100644 index 00000000..1b113565 --- /dev/null +++ b/hdfs/hdfs.h @@ -0,0 +1,490 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBHDFS_HDFS_H +#define LIBHDFS_HDFS_H + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifndef O_RDONLY +#define O_RDONLY 1 +#endif + +#ifndef O_WRONLY +#define O_WRONLY 2 +#endif + +#ifndef EINTERNAL +#define EINTERNAL 255 +#endif + + +/** All APIs set errno to meaningful values */ +#ifdef __cplusplus +extern "C" { +#endif + + /** + * Some utility decls used in libhdfs. + */ + + typedef int32_t tSize; /// size of data for read/write io ops + typedef time_t tTime; /// time type in seconds + typedef int64_t tOffset;/// offset within the file + typedef uint16_t tPort; /// port + typedef enum tObjectKind { + kObjectKindFile = 'F', + kObjectKindDirectory = 'D', + } tObjectKind; + + + /** + * The C reflection of org.apache.org.hadoop.FileSystem . + */ + typedef void* hdfsFS; + + + /** + * The C equivalent of org.apache.org.hadoop.FSData(Input|Output)Stream . + */ + enum hdfsStreamType + { + UNINITIALIZED = 0, + INPUT = 1, + OUTPUT = 2, + }; + + + /** + * The 'file-handle' to a file in hdfs. + */ + struct hdfsFile_internal { + void* file; + enum hdfsStreamType type; + }; + typedef struct hdfsFile_internal* hdfsFile; + + + /** + * hdfsConnectAsUser - Connect to a hdfs file system as a specific user + * Connect to the hdfs. + * @param host A string containing either a host name, or an ip address + * of the namenode of a hdfs cluster. 'host' should be passed as NULL if + * you want to connect to local filesystem. 'host' should be passed as + * 'default' (and port as 0) to used the 'configured' filesystem + * (core-site/core-default.xml). + * @param port The port on which the server is listening. + * @param user the user name (this is hadoop domain user). Or NULL is equivelant to hhdfsConnect(host, port) + * @param groups the groups (these are hadoop domain groups) + * @return Returns a handle to the filesystem or NULL on error. + */ + hdfsFS hdfsConnectAsUser(const char* host, tPort port, const char *user , const char *groups[], int groups_size ); + + + /** + * hdfsConnect - Connect to a hdfs file system. + * Connect to the hdfs. + * @param host A string containing either a host name, or an ip address + * of the namenode of a hdfs cluster. 'host' should be passed as NULL if + * you want to connect to local filesystem. 'host' should be passed as + * 'default' (and port as 0) to used the 'configured' filesystem + * (core-site/core-default.xml). + * @param port The port on which the server is listening. + * @return Returns a handle to the filesystem or NULL on error. + */ + hdfsFS hdfsConnect(const char* host, tPort port); + + + /** + * This are the same as hdfsConnectAsUser except that every invocation returns a new FileSystem handle. + * Applications should call a hdfsDisconnect for every call to hdfsConnectAsUserNewInstance. + */ + hdfsFS hdfsConnectAsUserNewInstance(const char* host, tPort port, const char *user , const char *groups[], int groups_size ); + hdfsFS hdfsConnectNewInstance(const char* host, tPort port); + hdfsFS hdfsConnectPath(const char* uri); + + /** + * hdfsDisconnect - Disconnect from the hdfs file system. + * Disconnect from hdfs. + * @param fs The configured filesystem handle. + * @return Returns 0 on success, -1 on error. + */ + int hdfsDisconnect(hdfsFS fs); + + + /** + * hdfsOpenFile - Open a hdfs file in given mode. + * @param fs The configured filesystem handle. + * @param path The full path to the file. + * @param flags - an | of bits/fcntl.h file flags - supported flags are O_RDONLY, O_WRONLY (meaning create or overwrite i.e., implies O_TRUNCAT), + * O_WRONLY|O_APPEND. Other flags are generally ignored other than (O_RDWR || (O_EXCL & O_CREAT)) which return NULL and set errno equal ENOTSUP. + * @param bufferSize Size of buffer for read/write - pass 0 if you want + * to use the default configured values. + * @param replication Block replication - pass 0 if you want to use + * the default configured values. + * @param blocksize Size of block - pass 0 if you want to use the + * default configured values. + * @return Returns the handle to the open file or NULL on error. + */ + hdfsFile hdfsOpenFile(hdfsFS fs, const char* path, int flags, + int bufferSize, short replication, tSize blocksize); + + + /** + * hdfsCloseFile - Close an open file. + * @param fs The configured filesystem handle. + * @param file The file handle. + * @return Returns 0 on success, -1 on error. + */ + int hdfsCloseFile(hdfsFS fs, hdfsFile file); + + + /** + * hdfsExists - Checks if a given path exsits on the filesystem + * @param fs The configured filesystem handle. + * @param path The path to look for + * @return Returns 0 on exists, 1 on non-exists, -1/-2 on error. + */ + int hdfsExists(hdfsFS fs, const char *path); + + + /** + * hdfsSeek - Seek to given offset in file. + * This works only for files opened in read-only mode. + * @param fs The configured filesystem handle. + * @param file The file handle. + * @param desiredPos Offset into the file to seek into. + * @return Returns 0 on success, -1 on error. + */ + int hdfsSeek(hdfsFS fs, hdfsFile file, tOffset desiredPos); + + + /** + * hdfsTell - Get the current offset in the file, in bytes. + * @param fs The configured filesystem handle. + * @param file The file handle. + * @return Current offset, -1 on error. + */ + tOffset hdfsTell(hdfsFS fs, hdfsFile file); + + + /** + * hdfsRead - Read data from an open file. + * @param fs The configured filesystem handle. + * @param file The file handle. + * @param buffer The buffer to copy read bytes into. + * @param length The length of the buffer. + * @return Returns the number of bytes actually read, possibly less + * than than length;-1 on error. + */ + tSize hdfsRead(hdfsFS fs, hdfsFile file, void* buffer, tSize length); + + + /** + * hdfsPread - Positional read of data from an open file. + * @param fs The configured filesystem handle. + * @param file The file handle. + * @param position Position from which to read + * @param buffer The buffer to copy read bytes into. + * @param length The length of the buffer. + * @return Returns the number of bytes actually read, possibly less than + * than length;-1 on error. + */ + tSize hdfsPread(hdfsFS fs, hdfsFile file, tOffset position, + void* buffer, tSize length); + + + /** + * hdfsWrite - Write data into an open file. + * @param fs The configured filesystem handle. + * @param file The file handle. + * @param buffer The data. + * @param length The no. of bytes to write. + * @return Returns the number of bytes written, -1 on error. + */ + tSize hdfsWrite(hdfsFS fs, hdfsFile file, const void* buffer, + tSize length); + + + /** + * hdfsWrite - Flush the data. + * @param fs The configured filesystem handle. + * @param file The file handle. + * @return Returns 0 on success, -1 on error. + */ + int hdfsFlush(hdfsFS fs, hdfsFile file); + + /** + * hdfsSync - Sync the data to persistent store. + * @param fs The configured filesystem handle. + * @param file The file handle. + * @return Returns 0 on success, -1 on error. + */ + int hdfsSync(hdfsFS fs, hdfsFile file); + + /** + * hdfsGetNumReplicasInPipeline - get number of remaining replicas in + * pipeline + * @param fs The configured filesystem handle + * @param file the file handle + * @return returns the # of datanodes in the write pipeline; -1 on error + */ + int hdfsGetNumCurrentReplicas(hdfsFS, hdfsFile file); + + /** + * hdfsAvailable - Number of bytes that can be read from this + * input stream without blocking. + * @param fs The configured filesystem handle. + * @param file The file handle. + * @return Returns available bytes; -1 on error. + */ + int hdfsAvailable(hdfsFS fs, hdfsFile file); + + + /** + * hdfsCopy - Copy file from one filesystem to another. + * @param srcFS The handle to source filesystem. + * @param src The path of source file. + * @param dstFS The handle to destination filesystem. + * @param dst The path of destination file. + * @return Returns 0 on success, -1 on error. + */ + int hdfsCopy(hdfsFS srcFS, const char* src, hdfsFS dstFS, const char* dst); + + + /** + * hdfsMove - Move file from one filesystem to another. + * @param srcFS The handle to source filesystem. + * @param src The path of source file. + * @param dstFS The handle to destination filesystem. + * @param dst The path of destination file. + * @return Returns 0 on success, -1 on error. + */ + int hdfsMove(hdfsFS srcFS, const char* src, hdfsFS dstFS, const char* dst); + + + /** + * hdfsDelete - Delete file. + * @param fs The configured filesystem handle. + * @param path The path of the file. + * @return Returns 0 on success, -1 on error. + */ + int hdfsDelete(hdfsFS fs, const char* path); + + + /** + * hdfsRename - Rename file. + * @param fs The configured filesystem handle. + * @param oldPath The path of the source file. + * @param newPath The path of the destination file. + * @return Returns 0 on success, -1 on error. + */ + int hdfsRename(hdfsFS fs, const char* oldPath, const char* newPath); + + + /** + * hdfsGetWorkingDirectory - Get the current working directory for + * the given filesystem. + * @param fs The configured filesystem handle. + * @param buffer The user-buffer to copy path of cwd into. + * @param bufferSize The length of user-buffer. + * @return Returns buffer, NULL on error. + */ + char* hdfsGetWorkingDirectory(hdfsFS fs, char *buffer, size_t bufferSize); + + + /** + * hdfsSetWorkingDirectory - Set the working directory. All relative + * paths will be resolved relative to it. + * @param fs The configured filesystem handle. + * @param path The path of the new 'cwd'. + * @return Returns 0 on success, -1 on error. + */ + int hdfsSetWorkingDirectory(hdfsFS fs, const char* path); + + + /** + * hdfsCreateDirectory - Make the given file and all non-existent + * parents into directories. + * @param fs The configured filesystem handle. + * @param path The path of the directory. + * @return Returns 0 on success, -1 on error. + */ + int hdfsCreateDirectory(hdfsFS fs, const char* path); + + + /** + * hdfsSetReplication - Set the replication of the specified + * file to the supplied value + * @param fs The configured filesystem handle. + * @param path The path of the file. + * @return Returns 0 on success, -1 on error. + */ + int hdfsSetReplication(hdfsFS fs, const char* path, int16_t replication); + + + /** + * hdfsFileInfo - Information about a file/directory. + */ + typedef struct { + tObjectKind mKind; /* file or directory */ + char *mName; /* the name of the file */ + tTime mLastMod; /* the last modification time for the file in seconds */ + tOffset mSize; /* the size of the file in bytes */ + short mReplication; /* the count of replicas */ + tOffset mBlockSize; /* the block size for the file */ + char *mOwner; /* the owner of the file */ + char *mGroup; /* the group associated with the file */ + short mPermissions; /* the permissions associated with the file */ + tTime mLastAccess; /* the last access time for the file in seconds */ + } hdfsFileInfo; + + + /** + * hdfsListDirectory - Get list of files/directories for a given + * directory-path. hdfsFreeFileInfo should be called to deallocate memory if + * the function returns non-NULL value. + * @param fs The configured filesystem handle. + * @param path The path of the directory. + * @param numEntries Set to the number of files/directories in path. + * @return Returns a dynamically-allocated array of hdfsFileInfo + * objects; NULL if empty or on error. + * on error, numEntries will be -1. + */ + hdfsFileInfo *hdfsListDirectory(hdfsFS fs, const char* path, + int *numEntries); + + + /** + * hdfsGetPathInfo - Get information about a path as a (dynamically + * allocated) single hdfsFileInfo struct. hdfsFreeFileInfo should be + * called when the pointer is no longer needed. + * @param fs The configured filesystem handle. + * @param path The path of the file. + * @return Returns a dynamically-allocated hdfsFileInfo object; + * NULL on error. + */ + hdfsFileInfo *hdfsGetPathInfo(hdfsFS fs, const char* path); + + + /** + * hdfsFreeFileInfo - Free up the hdfsFileInfo array (including fields) + * @param hdfsFileInfo The array of dynamically-allocated hdfsFileInfo + * objects. + * @param numEntries The size of the array. + */ + void hdfsFreeFileInfo(hdfsFileInfo *hdfsFileInfo, int numEntries); + + + /** + * hdfsGetHosts - Get hostnames where a particular block (determined by + * pos & blocksize) of a file is stored. The last element in the array + * is NULL. Due to replication, a single block could be present on + * multiple hosts. + * @param fs The configured filesystem handle. + * @param path The path of the file. + * @param start The start of the block. + * @param length The length of the block. + * @return Returns a dynamically-allocated 2-d array of blocks-hosts; + * NULL on error. + */ + char*** hdfsGetHosts(hdfsFS fs, const char* path, + tOffset start, tOffset length); + + + /** + * hdfsFreeHosts - Free up the structure returned by hdfsGetHosts + * @param hdfsFileInfo The array of dynamically-allocated hdfsFileInfo + * objects. + * @param numEntries The size of the array. + */ + void hdfsFreeHosts(char ***blockHosts); + + + /** + * hdfsGetDefaultBlockSize - Get the optimum blocksize. + * @param fs The configured filesystem handle. + * @return Returns the blocksize; -1 on error. + */ + tOffset hdfsGetDefaultBlockSize(hdfsFS fs); + + + /** + * hdfsGetCapacity - Return the raw capacity of the filesystem. + * @param fs The configured filesystem handle. + * @return Returns the raw-capacity; -1 on error. + */ + tOffset hdfsGetCapacity(hdfsFS fs); + + + /** + * hdfsGetUsed - Return the total raw size of all files in the filesystem. + * @param fs The configured filesystem handle. + * @return Returns the total-size; -1 on error. + */ + tOffset hdfsGetUsed(hdfsFS fs); + + /** + * hdfsChown + * @param fs The configured filesystem handle. + * @param path the path to the file or directory + * @param owner this is a string in Hadoop land. Set to null or "" if only setting group + * @param group this is a string in Hadoop land. Set to null or "" if only setting user + * @return 0 on success else -1 + */ + int hdfsChown(hdfsFS fs, const char* path, const char *owner, const char *group); + + /** + * hdfsChmod + * @param fs The configured filesystem handle. + * @param path the path to the file or directory + * @param mode the bitmask to set it to + * @return 0 on success else -1 + */ + int hdfsChmod(hdfsFS fs, const char* path, short mode); + + /** + * hdfsUtime + * @param fs The configured filesystem handle. + * @param path the path to the file or directory + * @param mtime new modification time or 0 for only set access time in seconds + * @param atime new access time or 0 for only set modification time in seconds + * @return 0 on success else -1 + */ + int hdfsUtime(hdfsFS fs, const char* path, tTime mtime, tTime atime); + +#ifdef __cplusplus +} +#endif + +#endif /*LIBHDFS_HDFS_H*/ + +/** + * vim: ts=4: sw=4: et + */ diff --git a/hdfs/libhdfs.a b/hdfs/libhdfs.a new file mode 100644 index 00000000..4d1f19f0 Binary files /dev/null and b/hdfs/libhdfs.a differ diff --git a/helpers/memenv/memenv.cc b/helpers/memenv/memenv.cc new file mode 100644 index 00000000..3ca0be28 --- /dev/null +++ b/helpers/memenv/memenv.cc @@ -0,0 +1,383 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "helpers/memenv/memenv.h" + +#include "leveldb/env.h" +#include "leveldb/status.h" +#include "port/port.h" +#include "util/mutexlock.h" +#include +#include +#include +#include + +namespace leveldb { + +namespace { + +class FileState { + public: + // FileStates are reference counted. The initial reference count is zero + // and the caller must call Ref() at least once. + FileState() : refs_(0), size_(0) {} + + // Increase the reference count. + void Ref() { + MutexLock lock(&refs_mutex_); + ++refs_; + } + + // Decrease the reference count. Delete if this is the last reference. + void Unref() { + bool do_delete = false; + + { + MutexLock lock(&refs_mutex_); + --refs_; + assert(refs_ >= 0); + if (refs_ <= 0) { + do_delete = true; + } + } + + if (do_delete) { + delete this; + } + } + + uint64_t Size() const { return size_; } + + Status Read(uint64_t offset, size_t n, Slice* result, char* scratch) const { + if (offset > size_) { + return Status::IOError("Offset greater than file size."); + } + const uint64_t available = size_ - offset; + if (n > available) { + n = available; + } + if (n == 0) { + *result = Slice(); + return Status::OK(); + } + + size_t block = offset / kBlockSize; + size_t block_offset = offset % kBlockSize; + + if (n <= kBlockSize - block_offset) { + // The requested bytes are all in the first block. + *result = Slice(blocks_[block] + block_offset, n); + return Status::OK(); + } + + size_t bytes_to_copy = n; + char* dst = scratch; + + while (bytes_to_copy > 0) { + size_t avail = kBlockSize - block_offset; + if (avail > bytes_to_copy) { + avail = bytes_to_copy; + } + memcpy(dst, blocks_[block] + block_offset, avail); + + bytes_to_copy -= avail; + dst += avail; + block++; + block_offset = 0; + } + + *result = Slice(scratch, n); + return Status::OK(); + } + + Status Append(const Slice& data) { + const char* src = data.data(); + size_t src_len = data.size(); + + while (src_len > 0) { + size_t avail; + size_t offset = size_ % kBlockSize; + + if (offset != 0) { + // There is some room in the last block. + avail = kBlockSize - offset; + } else { + // No room in the last block; push new one. + blocks_.push_back(new char[kBlockSize]); + avail = kBlockSize; + } + + if (avail > src_len) { + avail = src_len; + } + memcpy(blocks_.back() + offset, src, avail); + src_len -= avail; + src += avail; + size_ += avail; + } + + return Status::OK(); + } + + private: + // Private since only Unref() should be used to delete it. + ~FileState() { + for (std::vector::iterator i = blocks_.begin(); i != blocks_.end(); + ++i) { + delete [] *i; + } + } + + // No copying allowed. + FileState(const FileState&); + void operator=(const FileState&); + + port::Mutex refs_mutex_; + int refs_; // Protected by refs_mutex_; + + // The following fields are not protected by any mutex. They are only mutable + // while the file is being written, and concurrent access is not allowed + // to writable files. + std::vector blocks_; + uint64_t size_; + + enum { kBlockSize = 8 * 1024 }; +}; + +class SequentialFileImpl : public SequentialFile { + public: + explicit SequentialFileImpl(FileState* file) : file_(file), pos_(0) { + file_->Ref(); + } + + ~SequentialFileImpl() { + file_->Unref(); + } + + virtual Status Read(size_t n, Slice* result, char* scratch) { + Status s = file_->Read(pos_, n, result, scratch); + if (s.ok()) { + pos_ += result->size(); + } + return s; + } + + virtual Status Skip(uint64_t n) { + if (pos_ > file_->Size()) { + return Status::IOError("pos_ > file_->Size()"); + } + const size_t available = file_->Size() - pos_; + if (n > available) { + n = available; + } + pos_ += n; + return Status::OK(); + } + + private: + FileState* file_; + size_t pos_; +}; + +class RandomAccessFileImpl : public RandomAccessFile { + public: + explicit RandomAccessFileImpl(FileState* file) : file_(file) { + file_->Ref(); + } + + ~RandomAccessFileImpl() { + file_->Unref(); + } + + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const { + return file_->Read(offset, n, result, scratch); + } + + private: + FileState* file_; +}; + +class WritableFileImpl : public WritableFile { + public: + WritableFileImpl(FileState* file) : file_(file) { + file_->Ref(); + } + + ~WritableFileImpl() { + file_->Unref(); + } + + virtual Status Append(const Slice& data) { + return file_->Append(data); + } + + virtual Status Close() { return Status::OK(); } + virtual Status Flush() { return Status::OK(); } + virtual Status Sync() { return Status::OK(); } + + private: + FileState* file_; +}; + +class InMemoryEnv : public EnvWrapper { + public: + explicit InMemoryEnv(Env* base_env) : EnvWrapper(base_env) { } + + virtual ~InMemoryEnv() { + for (FileSystem::iterator i = file_map_.begin(); i != file_map_.end(); ++i){ + i->second->Unref(); + } + } + + // Partial implementation of the Env interface. + virtual Status NewSequentialFile(const std::string& fname, + unique_ptr* result) { + MutexLock lock(&mutex_); + if (file_map_.find(fname) == file_map_.end()) { + *result = NULL; + return Status::IOError(fname, "File not found"); + } + + result->reset(new SequentialFileImpl(file_map_[fname])); + return Status::OK(); + } + + virtual Status NewRandomAccessFile(const std::string& fname, + unique_ptr* result) { + MutexLock lock(&mutex_); + if (file_map_.find(fname) == file_map_.end()) { + *result = NULL; + return Status::IOError(fname, "File not found"); + } + + result->reset(new RandomAccessFileImpl(file_map_[fname])); + return Status::OK(); + } + + virtual Status NewWritableFile(const std::string& fname, + unique_ptr* result) { + MutexLock lock(&mutex_); + if (file_map_.find(fname) != file_map_.end()) { + DeleteFileInternal(fname); + } + + FileState* file = new FileState(); + file->Ref(); + file_map_[fname] = file; + + result->reset(new WritableFileImpl(file)); + return Status::OK(); + } + + virtual bool FileExists(const std::string& fname) { + MutexLock lock(&mutex_); + return file_map_.find(fname) != file_map_.end(); + } + + virtual Status GetChildren(const std::string& dir, + std::vector* result) { + MutexLock lock(&mutex_); + result->clear(); + + for (FileSystem::iterator i = file_map_.begin(); i != file_map_.end(); ++i){ + const std::string& filename = i->first; + + if (filename.size() >= dir.size() + 1 && filename[dir.size()] == '/' && + Slice(filename).starts_with(Slice(dir))) { + result->push_back(filename.substr(dir.size() + 1)); + } + } + + return Status::OK(); + } + + void DeleteFileInternal(const std::string& fname) { + if (file_map_.find(fname) == file_map_.end()) { + return; + } + + file_map_[fname]->Unref(); + file_map_.erase(fname); + } + + virtual Status DeleteFile(const std::string& fname) { + MutexLock lock(&mutex_); + if (file_map_.find(fname) == file_map_.end()) { + return Status::IOError(fname, "File not found"); + } + + DeleteFileInternal(fname); + return Status::OK(); + } + + virtual Status CreateDir(const std::string& dirname) { + return Status::OK(); + } + + virtual Status CreateDirIfMissing(const std::string& dirname) { + return Status::OK(); + } + + virtual Status DeleteDir(const std::string& dirname) { + return Status::OK(); + } + + virtual Status GetFileSize(const std::string& fname, uint64_t* file_size) { + MutexLock lock(&mutex_); + if (file_map_.find(fname) == file_map_.end()) { + return Status::IOError(fname, "File not found"); + } + + *file_size = file_map_[fname]->Size(); + return Status::OK(); + } + + virtual Status GetFileModificationTime(const std::string& fname, + uint64_t* time) { + return Status::NotSupported("getFileMTime", "Not supported in MemEnv"); + } + + virtual Status RenameFile(const std::string& src, + const std::string& target) { + MutexLock lock(&mutex_); + if (file_map_.find(src) == file_map_.end()) { + return Status::IOError(src, "File not found"); + } + + DeleteFileInternal(target); + file_map_[target] = file_map_[src]; + file_map_.erase(src); + return Status::OK(); + } + + virtual Status LockFile(const std::string& fname, FileLock** lock) { + *lock = new FileLock; + return Status::OK(); + } + + virtual Status UnlockFile(FileLock* lock) { + delete lock; + return Status::OK(); + } + + virtual Status GetTestDirectory(std::string* path) { + *path = "/test"; + return Status::OK(); + } + + private: + // Map from filenames to FileState objects, representing a simple file system. + typedef std::map FileSystem; + port::Mutex mutex_; + FileSystem file_map_; // Protected by mutex_. +}; + +} // namespace + +Env* NewMemEnv(Env* base_env) { + return new InMemoryEnv(base_env); +} + +} // namespace leveldb diff --git a/helpers/memenv/memenv.h b/helpers/memenv/memenv.h new file mode 100644 index 00000000..03b88de7 --- /dev/null +++ b/helpers/memenv/memenv.h @@ -0,0 +1,20 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_HELPERS_MEMENV_MEMENV_H_ +#define STORAGE_LEVELDB_HELPERS_MEMENV_MEMENV_H_ + +namespace leveldb { + +class Env; + +// Returns a new environment that stores its data in memory and delegates +// all non-file-storage tasks to base_env. The caller must delete the result +// when it is no longer needed. +// *base_env must remain live while the result is in use. +Env* NewMemEnv(Env* base_env); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_HELPERS_MEMENV_MEMENV_H_ diff --git a/helpers/memenv/memenv_test.cc b/helpers/memenv/memenv_test.cc new file mode 100644 index 00000000..4a482166 --- /dev/null +++ b/helpers/memenv/memenv_test.cc @@ -0,0 +1,230 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "helpers/memenv/memenv.h" + +#include "db/db_impl.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "util/testharness.h" +#include +#include +#include + +namespace leveldb { + +class MemEnvTest { + public: + Env* env_; + + MemEnvTest() + : env_(NewMemEnv(Env::Default())) { + } + ~MemEnvTest() { + delete env_; + } +}; + +TEST(MemEnvTest, Basics) { + uint64_t file_size; + unique_ptr writable_file; + std::vector children; + + ASSERT_OK(env_->CreateDir("/dir")); + + // Check that the directory is empty. + ASSERT_TRUE(!env_->FileExists("/dir/non_existent")); + ASSERT_TRUE(!env_->GetFileSize("/dir/non_existent", &file_size).ok()); + ASSERT_OK(env_->GetChildren("/dir", &children)); + ASSERT_EQ(0U, children.size()); + + // Create a file. + ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file)); + writable_file.reset(); + + // Check that the file exists. + ASSERT_TRUE(env_->FileExists("/dir/f")); + ASSERT_OK(env_->GetFileSize("/dir/f", &file_size)); + ASSERT_EQ(0U, file_size); + ASSERT_OK(env_->GetChildren("/dir", &children)); + ASSERT_EQ(1U, children.size()); + ASSERT_EQ("f", children[0]); + + // Write to the file. + ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file)); + ASSERT_OK(writable_file->Append("abc")); + writable_file.reset(); + + // Check for expected size. + ASSERT_OK(env_->GetFileSize("/dir/f", &file_size)); + ASSERT_EQ(3U, file_size); + + // Check that renaming works. + ASSERT_TRUE(!env_->RenameFile("/dir/non_existent", "/dir/g").ok()); + ASSERT_OK(env_->RenameFile("/dir/f", "/dir/g")); + ASSERT_TRUE(!env_->FileExists("/dir/f")); + ASSERT_TRUE(env_->FileExists("/dir/g")); + ASSERT_OK(env_->GetFileSize("/dir/g", &file_size)); + ASSERT_EQ(3U, file_size); + + // Check that opening non-existent file fails. + unique_ptr seq_file; + unique_ptr rand_file; + ASSERT_TRUE(!env_->NewSequentialFile("/dir/non_existent", &seq_file).ok()); + ASSERT_TRUE(!seq_file); + ASSERT_TRUE(!env_->NewRandomAccessFile("/dir/non_existent", &rand_file).ok()); + ASSERT_TRUE(!rand_file); + + // Check that deleting works. + ASSERT_TRUE(!env_->DeleteFile("/dir/non_existent").ok()); + ASSERT_OK(env_->DeleteFile("/dir/g")); + ASSERT_TRUE(!env_->FileExists("/dir/g")); + ASSERT_OK(env_->GetChildren("/dir", &children)); + ASSERT_EQ(0U, children.size()); + ASSERT_OK(env_->DeleteDir("/dir")); +} + +TEST(MemEnvTest, ReadWrite) { + unique_ptr writable_file; + unique_ptr seq_file; + unique_ptr rand_file; + Slice result; + char scratch[100]; + + ASSERT_OK(env_->CreateDir("/dir")); + + ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file)); + ASSERT_OK(writable_file->Append("hello ")); + ASSERT_OK(writable_file->Append("world")); + writable_file.reset(); + + // Read sequentially. + ASSERT_OK(env_->NewSequentialFile("/dir/f", &seq_file)); + ASSERT_OK(seq_file->Read(5, &result, scratch)); // Read "hello". + ASSERT_EQ(0, result.compare("hello")); + ASSERT_OK(seq_file->Skip(1)); + ASSERT_OK(seq_file->Read(1000, &result, scratch)); // Read "world". + ASSERT_EQ(0, result.compare("world")); + ASSERT_OK(seq_file->Read(1000, &result, scratch)); // Try reading past EOF. + ASSERT_EQ(0U, result.size()); + ASSERT_OK(seq_file->Skip(100)); // Try to skip past end of file. + ASSERT_OK(seq_file->Read(1000, &result, scratch)); + ASSERT_EQ(0U, result.size()); + + // Random reads. + ASSERT_OK(env_->NewRandomAccessFile("/dir/f", &rand_file)); + ASSERT_OK(rand_file->Read(6, 5, &result, scratch)); // Read "world". + ASSERT_EQ(0, result.compare("world")); + ASSERT_OK(rand_file->Read(0, 5, &result, scratch)); // Read "hello". + ASSERT_EQ(0, result.compare("hello")); + ASSERT_OK(rand_file->Read(10, 100, &result, scratch)); // Read "d". + ASSERT_EQ(0, result.compare("d")); + + // Too high offset. + ASSERT_TRUE(!rand_file->Read(1000, 5, &result, scratch).ok()); +} + +TEST(MemEnvTest, Locks) { + FileLock* lock; + + // These are no-ops, but we test they return success. + ASSERT_OK(env_->LockFile("some file", &lock)); + ASSERT_OK(env_->UnlockFile(lock)); +} + +TEST(MemEnvTest, Misc) { + std::string test_dir; + ASSERT_OK(env_->GetTestDirectory(&test_dir)); + ASSERT_TRUE(!test_dir.empty()); + + unique_ptr writable_file; + ASSERT_OK(env_->NewWritableFile("/a/b", &writable_file)); + + // These are no-ops, but we test they return success. + ASSERT_OK(writable_file->Sync()); + ASSERT_OK(writable_file->Flush()); + ASSERT_OK(writable_file->Close()); + writable_file.reset(); +} + +TEST(MemEnvTest, LargeWrite) { + const size_t kWriteSize = 300 * 1024; + char* scratch = new char[kWriteSize * 2]; + + std::string write_data; + for (size_t i = 0; i < kWriteSize; ++i) { + write_data.append(1, static_cast(i)); + } + + unique_ptr writable_file; + ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file)); + ASSERT_OK(writable_file->Append("foo")); + ASSERT_OK(writable_file->Append(write_data)); + writable_file.reset(); + + unique_ptr seq_file; + Slice result; + ASSERT_OK(env_->NewSequentialFile("/dir/f", &seq_file)); + ASSERT_OK(seq_file->Read(3, &result, scratch)); // Read "foo". + ASSERT_EQ(0, result.compare("foo")); + + size_t read = 0; + std::string read_data; + while (read < kWriteSize) { + ASSERT_OK(seq_file->Read(kWriteSize - read, &result, scratch)); + read_data.append(result.data(), result.size()); + read += result.size(); + } + ASSERT_TRUE(write_data == read_data); + delete [] scratch; +} + +TEST(MemEnvTest, DBTest) { + Options options; + options.create_if_missing = true; + options.env = env_; + DB* db; + + const Slice keys[] = {Slice("aaa"), Slice("bbb"), Slice("ccc")}; + const Slice vals[] = {Slice("foo"), Slice("bar"), Slice("baz")}; + + ASSERT_OK(DB::Open(options, "/dir/db", &db)); + for (size_t i = 0; i < 3; ++i) { + ASSERT_OK(db->Put(WriteOptions(), keys[i], vals[i])); + } + + for (size_t i = 0; i < 3; ++i) { + std::string res; + ASSERT_OK(db->Get(ReadOptions(), keys[i], &res)); + ASSERT_TRUE(res == vals[i]); + } + + Iterator* iterator = db->NewIterator(ReadOptions()); + iterator->SeekToFirst(); + for (size_t i = 0; i < 3; ++i) { + ASSERT_TRUE(iterator->Valid()); + ASSERT_TRUE(keys[i] == iterator->key()); + ASSERT_TRUE(vals[i] == iterator->value()); + iterator->Next(); + } + ASSERT_TRUE(!iterator->Valid()); + delete iterator; + + DBImpl* dbi = reinterpret_cast(db); + ASSERT_OK(dbi->TEST_CompactMemTable()); + + for (size_t i = 0; i < 3; ++i) { + std::string res; + ASSERT_OK(db->Get(ReadOptions(), keys[i], &res)); + ASSERT_TRUE(res == vals[i]); + } + + delete db; +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/include/leveldb/c.h b/include/leveldb/c.h new file mode 100644 index 00000000..8799a5fb --- /dev/null +++ b/include/leveldb/c.h @@ -0,0 +1,281 @@ +/* Copyright (c) 2011 The LevelDB Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. See the AUTHORS file for names of contributors. + + C bindings for leveldb. May be useful as a stable ABI that can be + used by programs that keep leveldb in a shared library, or for + a JNI api. + + Does not support: + . getters for the option types + . custom comparators that implement key shortening + . capturing post-write-snapshot + . custom iter, db, env, cache implementations using just the C bindings + + Some conventions: + + (1) We expose just opaque struct pointers and functions to clients. + This allows us to change internal representations without having to + recompile clients. + + (2) For simplicity, there is no equivalent to the Slice type. Instead, + the caller has to pass the pointer and length as separate + arguments. + + (3) Errors are represented by a null-terminated c string. NULL + means no error. All operations that can raise an error are passed + a "char** errptr" as the last argument. One of the following must + be true on entry: + *errptr == NULL + *errptr points to a malloc()ed null-terminated error message + On success, a leveldb routine leaves *errptr unchanged. + On failure, leveldb frees the old value of *errptr and + set *errptr to a malloc()ed error message. + + (4) Bools have the type unsigned char (0 == false; rest == true) + + (5) All of the pointer arguments must be non-NULL. +*/ + +#ifndef STORAGE_LEVELDB_INCLUDE_C_H_ +#define STORAGE_LEVELDB_INCLUDE_C_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/* Exported types */ + +typedef struct leveldb_t leveldb_t; +typedef struct leveldb_cache_t leveldb_cache_t; +typedef struct leveldb_comparator_t leveldb_comparator_t; +typedef struct leveldb_env_t leveldb_env_t; +typedef struct leveldb_filelock_t leveldb_filelock_t; +typedef struct leveldb_filterpolicy_t leveldb_filterpolicy_t; +typedef struct leveldb_iterator_t leveldb_iterator_t; +typedef struct leveldb_logger_t leveldb_logger_t; +typedef struct leveldb_options_t leveldb_options_t; +typedef struct leveldb_randomfile_t leveldb_randomfile_t; +typedef struct leveldb_readoptions_t leveldb_readoptions_t; +typedef struct leveldb_seqfile_t leveldb_seqfile_t; +typedef struct leveldb_snapshot_t leveldb_snapshot_t; +typedef struct leveldb_writablefile_t leveldb_writablefile_t; +typedef struct leveldb_writebatch_t leveldb_writebatch_t; +typedef struct leveldb_writeoptions_t leveldb_writeoptions_t; + +/* DB operations */ + +extern leveldb_t* leveldb_open( + const leveldb_options_t* options, + const char* name, + char** errptr); + +extern void leveldb_close(leveldb_t* db); + +extern void leveldb_put( + leveldb_t* db, + const leveldb_writeoptions_t* options, + const char* key, size_t keylen, + const char* val, size_t vallen, + char** errptr); + +extern void leveldb_delete( + leveldb_t* db, + const leveldb_writeoptions_t* options, + const char* key, size_t keylen, + char** errptr); + +extern void leveldb_write( + leveldb_t* db, + const leveldb_writeoptions_t* options, + leveldb_writebatch_t* batch, + char** errptr); + +/* Returns NULL if not found. A malloc()ed array otherwise. + Stores the length of the array in *vallen. */ +extern char* leveldb_get( + leveldb_t* db, + const leveldb_readoptions_t* options, + const char* key, size_t keylen, + size_t* vallen, + char** errptr); + +extern leveldb_iterator_t* leveldb_create_iterator( + leveldb_t* db, + const leveldb_readoptions_t* options); + +extern const leveldb_snapshot_t* leveldb_create_snapshot( + leveldb_t* db); + +extern void leveldb_release_snapshot( + leveldb_t* db, + const leveldb_snapshot_t* snapshot); + +/* Returns NULL if property name is unknown. + Else returns a pointer to a malloc()-ed null-terminated value. */ +extern char* leveldb_property_value( + leveldb_t* db, + const char* propname); + +extern void leveldb_approximate_sizes( + leveldb_t* db, + int num_ranges, + const char* const* range_start_key, const size_t* range_start_key_len, + const char* const* range_limit_key, const size_t* range_limit_key_len, + uint64_t* sizes); + +extern void leveldb_compact_range( + leveldb_t* db, + const char* start_key, size_t start_key_len, + const char* limit_key, size_t limit_key_len); + +/* Management operations */ + +extern void leveldb_destroy_db( + const leveldb_options_t* options, + const char* name, + char** errptr); + +extern void leveldb_repair_db( + const leveldb_options_t* options, + const char* name, + char** errptr); + +/* Iterator */ + +extern void leveldb_iter_destroy(leveldb_iterator_t*); +extern unsigned char leveldb_iter_valid(const leveldb_iterator_t*); +extern void leveldb_iter_seek_to_first(leveldb_iterator_t*); +extern void leveldb_iter_seek_to_last(leveldb_iterator_t*); +extern void leveldb_iter_seek(leveldb_iterator_t*, const char* k, size_t klen); +extern void leveldb_iter_next(leveldb_iterator_t*); +extern void leveldb_iter_prev(leveldb_iterator_t*); +extern const char* leveldb_iter_key(const leveldb_iterator_t*, size_t* klen); +extern const char* leveldb_iter_value(const leveldb_iterator_t*, size_t* vlen); +extern void leveldb_iter_get_error(const leveldb_iterator_t*, char** errptr); + +/* Write batch */ + +extern leveldb_writebatch_t* leveldb_writebatch_create(); +extern void leveldb_writebatch_destroy(leveldb_writebatch_t*); +extern void leveldb_writebatch_clear(leveldb_writebatch_t*); +extern void leveldb_writebatch_put( + leveldb_writebatch_t*, + const char* key, size_t klen, + const char* val, size_t vlen); +extern void leveldb_writebatch_delete( + leveldb_writebatch_t*, + const char* key, size_t klen); +extern void leveldb_writebatch_iterate( + leveldb_writebatch_t*, + void* state, + void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen), + void (*deleted)(void*, const char* k, size_t klen)); + +/* Options */ + +extern leveldb_options_t* leveldb_options_create(); +extern void leveldb_options_destroy(leveldb_options_t*); +extern void leveldb_options_set_comparator( + leveldb_options_t*, + leveldb_comparator_t*); +extern void leveldb_options_set_compression_per_level( + leveldb_options_t* opt, + int* level_values, + size_t num_levels); +extern void leveldb_options_set_filter_policy( + leveldb_options_t*, + leveldb_filterpolicy_t*); +extern void leveldb_options_set_create_if_missing( + leveldb_options_t*, unsigned char); +extern void leveldb_options_set_error_if_exists( + leveldb_options_t*, unsigned char); +extern void leveldb_options_set_paranoid_checks( + leveldb_options_t*, unsigned char); +extern void leveldb_options_set_env(leveldb_options_t*, leveldb_env_t*); +extern void leveldb_options_set_info_log(leveldb_options_t*, leveldb_logger_t*); +extern void leveldb_options_set_write_buffer_size(leveldb_options_t*, size_t); +extern void leveldb_options_set_max_open_files(leveldb_options_t*, int); +extern void leveldb_options_set_cache(leveldb_options_t*, leveldb_cache_t*); +extern void leveldb_options_set_block_size(leveldb_options_t*, size_t); +extern void leveldb_options_set_block_restart_interval(leveldb_options_t*, int); +extern void leveldb_options_set_compression_options( + leveldb_options_t* opt, int w_bits, int level, int strategy); + +enum { + leveldb_no_compression = 0, + leveldb_snappy_compression = 1 +}; +extern void leveldb_options_set_compression(leveldb_options_t*, int); + +/* Comparator */ + +extern leveldb_comparator_t* leveldb_comparator_create( + void* state, + void (*destructor)(void*), + int (*compare)( + void*, + const char* a, size_t alen, + const char* b, size_t blen), + const char* (*name)(void*)); +extern void leveldb_comparator_destroy(leveldb_comparator_t*); + +/* Filter policy */ + +extern leveldb_filterpolicy_t* leveldb_filterpolicy_create( + void* state, + void (*destructor)(void*), + char* (*create_filter)( + void*, + const char* const* key_array, const size_t* key_length_array, + int num_keys, + size_t* filter_length), + unsigned char (*key_may_match)( + void*, + const char* key, size_t length, + const char* filter, size_t filter_length), + const char* (*name)(void*)); +extern void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t*); + +extern leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom( + int bits_per_key); + +/* Read options */ + +extern leveldb_readoptions_t* leveldb_readoptions_create(); +extern void leveldb_readoptions_destroy(leveldb_readoptions_t*); +extern void leveldb_readoptions_set_verify_checksums( + leveldb_readoptions_t*, + unsigned char); +extern void leveldb_readoptions_set_fill_cache( + leveldb_readoptions_t*, unsigned char); +extern void leveldb_readoptions_set_snapshot( + leveldb_readoptions_t*, + const leveldb_snapshot_t*); + +/* Write options */ + +extern leveldb_writeoptions_t* leveldb_writeoptions_create(); +extern void leveldb_writeoptions_destroy(leveldb_writeoptions_t*); +extern void leveldb_writeoptions_set_sync( + leveldb_writeoptions_t*, unsigned char); + +/* Cache */ + +extern leveldb_cache_t* leveldb_cache_create_lru(size_t capacity); +extern void leveldb_cache_destroy(leveldb_cache_t* cache); + +/* Env */ + +extern leveldb_env_t* leveldb_create_default_env(); +extern void leveldb_env_destroy(leveldb_env_t*); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* STORAGE_LEVELDB_INCLUDE_C_H_ */ diff --git a/include/leveldb/cache.h b/include/leveldb/cache.h new file mode 100644 index 00000000..8669e69d --- /dev/null +++ b/include/leveldb/cache.h @@ -0,0 +1,106 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A Cache is an interface that maps keys to values. It has internal +// synchronization and may be safely accessed concurrently from +// multiple threads. It may automatically evict entries to make room +// for new entries. Values have a specified charge against the cache +// capacity. For example, a cache where the values are variable +// length strings, may use the length of the string as the charge for +// the string. +// +// A builtin cache implementation with a least-recently-used eviction +// policy is provided. Clients may use their own implementations if +// they want something more sophisticated (like scan-resistance, a +// custom eviction policy, variable cache sizing, etc.) + +#ifndef STORAGE_LEVELDB_INCLUDE_CACHE_H_ +#define STORAGE_LEVELDB_INCLUDE_CACHE_H_ + +#include +#include +#include "leveldb/slice.h" + +namespace leveldb { + +using std::shared_ptr; + +class Cache; + +// Create a new cache with a fixed size capacity. This implementation +// of Cache uses a least-recently-used eviction policy. +extern shared_ptr NewLRUCache(size_t capacity); +extern shared_ptr NewLRUCache(size_t capacity, int numShardBits); + +class Cache { + public: + Cache() { } + + // Destroys all existing entries by calling the "deleter" + // function that was passed to the constructor. + virtual ~Cache(); + + // Opaque handle to an entry stored in the cache. + struct Handle { }; + + // Insert a mapping from key->value into the cache and assign it + // the specified charge against the total cache capacity. + // + // Returns a handle that corresponds to the mapping. The caller + // must call this->Release(handle) when the returned mapping is no + // longer needed. + // + // When the inserted entry is no longer needed, the key and + // value will be passed to "deleter". + virtual Handle* Insert(const Slice& key, void* value, size_t charge, + void (*deleter)(const Slice& key, void* value)) = 0; + + // If the cache has no mapping for "key", returns nullptr. + // + // Else return a handle that corresponds to the mapping. The caller + // must call this->Release(handle) when the returned mapping is no + // longer needed. + virtual Handle* Lookup(const Slice& key) = 0; + + // Release a mapping returned by a previous Lookup(). + // REQUIRES: handle must not have been released yet. + // REQUIRES: handle must have been returned by a method on *this. + virtual void Release(Handle* handle) = 0; + + // Return the value encapsulated in a handle returned by a + // successful Lookup(). + // REQUIRES: handle must not have been released yet. + // REQUIRES: handle must have been returned by a method on *this. + virtual void* Value(Handle* handle) = 0; + + // If the cache contains entry for key, erase it. Note that the + // underlying entry will be kept around until all existing handles + // to it have been released. + virtual void Erase(const Slice& key) = 0; + + // Return a new numeric id. May be used by multiple clients who are + // sharing the same cache to partition the key space. Typically the + // client will allocate a new id at startup and prepend the id to + // its cache keys. + virtual uint64_t NewId() = 0; + + // returns the maximum configured capacity of the cache + virtual size_t GetCapacity() = 0; + + private: + void LRU_Remove(Handle* e); + void LRU_Append(Handle* e); + void Unref(Handle* e); + + struct Rep; + Rep* rep_; + + // No copying allowed + Cache(const Cache&); + void operator=(const Cache&); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_CACHE_H_ diff --git a/include/leveldb/comparator.h b/include/leveldb/comparator.h new file mode 100644 index 00000000..556b984c --- /dev/null +++ b/include/leveldb/comparator.h @@ -0,0 +1,63 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_ +#define STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_ + +#include + +namespace leveldb { + +class Slice; + +// A Comparator object provides a total order across slices that are +// used as keys in an sstable or a database. A Comparator implementation +// must be thread-safe since leveldb may invoke its methods concurrently +// from multiple threads. +class Comparator { + public: + virtual ~Comparator(); + + // Three-way comparison. Returns value: + // < 0 iff "a" < "b", + // == 0 iff "a" == "b", + // > 0 iff "a" > "b" + virtual int Compare(const Slice& a, const Slice& b) const = 0; + + // The name of the comparator. Used to check for comparator + // mismatches (i.e., a DB created with one comparator is + // accessed using a different comparator. + // + // The client of this package should switch to a new name whenever + // the comparator implementation changes in a way that will cause + // the relative ordering of any two keys to change. + // + // Names starting with "leveldb." are reserved and should not be used + // by any clients of this package. + virtual const char* Name() const = 0; + + // Advanced functions: these are used to reduce the space requirements + // for internal data structures like index blocks. + + // If *start < limit, changes *start to a short string in [start,limit). + // Simple comparator implementations may return with *start unchanged, + // i.e., an implementation of this method that does nothing is correct. + virtual void FindShortestSeparator( + std::string* start, + const Slice& limit) const = 0; + + // Changes *key to a short string >= *key. + // Simple comparator implementations may return with *key unchanged, + // i.e., an implementation of this method that does nothing is correct. + virtual void FindShortSuccessor(std::string* key) const = 0; +}; + +// Return a builtin comparator that uses lexicographic byte-wise +// ordering. The result remains the property of this module and +// must not be deleted. +extern const Comparator* BytewiseComparator(); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_ diff --git a/include/leveldb/db.h b/include/leveldb/db.h new file mode 100644 index 00000000..6a6f6fc8 --- /dev/null +++ b/include/leveldb/db.h @@ -0,0 +1,222 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_DB_H_ +#define STORAGE_LEVELDB_INCLUDE_DB_H_ + +#include +#include +#include +#include +#include "leveldb/iterator.h" +#include "leveldb/options.h" +#include "leveldb/types.h" +#include "leveldb/transaction_log_iterator.h" + +namespace leveldb { + +using std::unique_ptr; + +// Update Makefile if you change these +static const int kMajorVersion = 1; +static const int kMinorVersion = 5; + +struct Options; +struct ReadOptions; +struct WriteOptions; +struct FlushOptions; +class WriteBatch; + +// Abstract handle to particular state of a DB. +// A Snapshot is an immutable object and can therefore be safely +// accessed from multiple threads without any external synchronization. +class Snapshot { + protected: + virtual ~Snapshot(); +}; + +// A range of keys +struct Range { + Slice start; // Included in the range + Slice limit; // Not included in the range + + Range() { } + Range(const Slice& s, const Slice& l) : start(s), limit(l) { } +}; + +// A DB is a persistent ordered map from keys to values. +// A DB is safe for concurrent access from multiple threads without +// any external synchronization. +class DB { + public: + // Open the database with the specified "name". + // Stores a pointer to a heap-allocated database in *dbptr and returns + // OK on success. + // Stores nullptr in *dbptr and returns a non-OK status on error. + // Caller should delete *dbptr when it is no longer needed. + static Status Open(const Options& options, + const std::string& name, + DB** dbptr); + + // Open the database for read only. All DB interfaces + // that modify data, like put/delete, will return error. + // If the db is opened in read only mode, then no compactions + // will happen. + static Status OpenForReadOnly(const Options& options, + const std::string& name, DB** dbptr, + bool error_if_log_file_exist = false); + + DB() { } + virtual ~DB(); + + // Set the database entry for "key" to "value". Returns OK on success, + // and a non-OK status on error. + // Note: consider setting options.sync = true. + virtual Status Put(const WriteOptions& options, + const Slice& key, + const Slice& value) = 0; + + // Remove the database entry (if any) for "key". Returns OK on + // success, and a non-OK status on error. It is not an error if "key" + // did not exist in the database. + // Note: consider setting options.sync = true. + virtual Status Delete(const WriteOptions& options, const Slice& key) = 0; + + // Apply the specified updates to the database. + // Returns OK on success, non-OK on failure. + // Note: consider setting options.sync = true. + virtual Status Write(const WriteOptions& options, WriteBatch* updates) = 0; + + // If the database contains an entry for "key" store the + // corresponding value in *value and return OK. + // + // If there is no entry for "key" leave *value unchanged and return + // a status for which Status::IsNotFound() returns true. + // + // May return some other Status on an error. + virtual Status Get(const ReadOptions& options, + const Slice& key, std::string* value) = 0; + + // Return a heap-allocated iterator over the contents of the database. + // The result of NewIterator() is initially invalid (caller must + // call one of the Seek methods on the iterator before using it). + // + // Caller should delete the iterator when it is no longer needed. + // The returned iterator should be deleted before this db is deleted. + virtual Iterator* NewIterator(const ReadOptions& options) = 0; + + // Return a handle to the current DB state. Iterators created with + // this handle will all observe a stable snapshot of the current DB + // state. The caller must call ReleaseSnapshot(result) when the + // snapshot is no longer needed. + virtual const Snapshot* GetSnapshot() = 0; + + // Release a previously acquired snapshot. The caller must not + // use "snapshot" after this call. + virtual void ReleaseSnapshot(const Snapshot* snapshot) = 0; + + // DB implementations can export properties about their state + // via this method. If "property" is a valid property understood by this + // DB implementation, fills "*value" with its current value and returns + // true. Otherwise returns false. + // + // + // Valid property names include: + // + // "leveldb.num-files-at-level" - return the number of files at level , + // where is an ASCII representation of a level number (e.g. "0"). + // "leveldb.stats" - returns a multi-line string that describes statistics + // about the internal operation of the DB. + // "leveldb.sstables" - returns a multi-line string that describes all + // of the sstables that make up the db contents. + virtual bool GetProperty(const Slice& property, std::string* value) = 0; + + // For each i in [0,n-1], store in "sizes[i]", the approximate + // file system space used by keys in "[range[i].start .. range[i].limit)". + // + // Note that the returned sizes measure file system space usage, so + // if the user data compresses by a factor of ten, the returned + // sizes will be one-tenth the size of the corresponding user data size. + // + // The results may not include the sizes of recently written data. + virtual void GetApproximateSizes(const Range* range, int n, + uint64_t* sizes) = 0; + + // Compact the underlying storage for the key range [*begin,*end]. + // In particular, deleted and overwritten versions are discarded, + // and the data is rearranged to reduce the cost of operations + // needed to access the data. This operation should typically only + // be invoked by users who understand the underlying implementation. + // + // begin==nullptr is treated as a key before all keys in the database. + // end==nullptr is treated as a key after all keys in the database. + // Therefore the following call will compact the entire database: + // db->CompactRange(nullptr, nullptr); + virtual void CompactRange(const Slice* begin, const Slice* end) = 0; + + // Number of levels used for this DB. + virtual int NumberLevels() = 0; + + // Maximum level to which a new compacted memtable is pushed if it + // does not create overlap. + virtual int MaxMemCompactionLevel() = 0; + + // Number of files in level-0 that would stop writes. + virtual int Level0StopWriteTrigger() = 0; + + // Flush all mem-table data. + virtual Status Flush(const FlushOptions& options) = 0; + + // Prevent file deletions. Compactions will continue to occur, + // but no obsolete files will be deleted. Calling this multiple + // times have the same effect as calling it once. + virtual Status DisableFileDeletions() = 0; + + // Allow compactions to delete obselete files. + virtual Status EnableFileDeletions() = 0; + + // Retrieve the list of all files in the database. The files are + // relative to the dbname and are not absolute paths. This list + // can be used to generate a backup. The valid size of the manifest + // file is returned in manifest_file_size. The manifest file is + // an ever growing file, but only the portion specified + // by manifest_file_size is valid for this snapshot. + virtual Status GetLiveFiles(std::vector&, + uint64_t* manifest_file_size) = 0; + + // The sequence number of the most recent transaction. + virtual SequenceNumber GetLatestSequenceNumber() = 0; + + // Return's an iterator for all writes since the sequence number + // Status::ok if iterator is valid. + // The iterator internally holds references to the available log files. + // It automatically takes care of closing a file with no-updates left, and + // opening the next one. + // If the sequence number is non existent. it returns an iterator at a seq_no + // just greater than the requested seq_no. + // Must set WAL_ttl_seconds to a large value to use this api. + // else the WAL files will get + // cleared aggressively and the iterator might keep getting invalid before + // an update is read. + virtual Status GetUpdatesSince(SequenceNumber seq_number, + unique_ptr* iter) = 0; + private: + // No copying allowed + DB(const DB&); + void operator=(const DB&); +}; + +// Destroy the contents of the specified database. +// Be very careful using this method. +Status DestroyDB(const std::string& name, const Options& options); + +// If a DB cannot be opened, you may attempt to call this method to +// resurrect as much of the contents of the database as possible. +// Some data may be lost, so be careful when calling this function +// on a database that contains important information. +Status RepairDB(const std::string& dbname, const Options& options); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_DB_H_ diff --git a/include/leveldb/env.h b/include/leveldb/env.h new file mode 100644 index 00000000..a8094bbe --- /dev/null +++ b/include/leveldb/env.h @@ -0,0 +1,479 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// An Env is an interface used by the leveldb implementation to access +// operating system functionality like the filesystem etc. Callers +// may wish to provide a custom Env object when opening a database to +// get fine gain control; e.g., to rate limit file system operations. +// +// All Env implementations are safe for concurrent access from +// multiple threads without any external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_ENV_H_ +#define STORAGE_LEVELDB_INCLUDE_ENV_H_ + +#include +#include +#include +#include +#include +#include "leveldb/status.h" + +namespace leveldb { + +class FileLock; +class Logger; +class RandomAccessFile; +class SequentialFile; +class Slice; +class WritableFile; + +using std::unique_ptr; +using std::shared_ptr; + +class Env { + public: + Env() { } + virtual ~Env(); + + // Return a default environment suitable for the current operating + // system. Sophisticated users may wish to provide their own Env + // implementation instead of relying on this default environment. + // + // The result of Default() belongs to leveldb and must never be deleted. + static Env* Default(); + + // Create a brand new sequentially-readable file with the specified name. + // On success, stores a pointer to the new file in *result and returns OK. + // On failure stores nullptr in *result and returns non-OK. If the file does + // not exist, returns a non-OK status. + // + // The returned file will only be accessed by one thread at a time. + virtual Status NewSequentialFile(const std::string& fname, + unique_ptr* result) = 0; + + // Create a brand new random access read-only file with the + // specified name. On success, stores a pointer to the new file in + // *result and returns OK. On failure stores nullptr in *result and + // returns non-OK. If the file does not exist, returns a non-OK + // status. + // + // The returned file may be concurrently accessed by multiple threads. + virtual Status NewRandomAccessFile(const std::string& fname, + unique_ptr* result) = 0; + + // Create an object that writes to a new file with the specified + // name. Deletes any existing file with the same name and creates a + // new file. On success, stores a pointer to the new file in + // *result and returns OK. On failure stores nullptr in *result and + // returns non-OK. + // + // The returned file will only be accessed by one thread at a time. + virtual Status NewWritableFile(const std::string& fname, + unique_ptr* result) = 0; + + // Returns true iff the named file exists. + virtual bool FileExists(const std::string& fname) = 0; + + // Store in *result the names of the children of the specified directory. + // The names are relative to "dir". + // Original contents of *results are dropped. + virtual Status GetChildren(const std::string& dir, + std::vector* result) = 0; + + // Delete the named file. + virtual Status DeleteFile(const std::string& fname) = 0; + + // Create the specified directory. Returns error if directory exists. + virtual Status CreateDir(const std::string& dirname) = 0; + + // Creates directory if missing. Return Ok if it exists, or successful in + // Creating. + virtual Status CreateDirIfMissing(const std::string& dirname) = 0; + + // Delete the specified directory. + virtual Status DeleteDir(const std::string& dirname) = 0; + + // Store the size of fname in *file_size. + virtual Status GetFileSize(const std::string& fname, uint64_t* file_size) = 0; + + // Store the last modification time of fname in *file_mtime. + virtual Status GetFileModificationTime(const std::string& fname, + uint64_t* file_mtime) = 0; + // Rename file src to target. + virtual Status RenameFile(const std::string& src, + const std::string& target) = 0; + + // Lock the specified file. Used to prevent concurrent access to + // the same db by multiple processes. On failure, stores nullptr in + // *lock and returns non-OK. + // + // On success, stores a pointer to the object that represents the + // acquired lock in *lock and returns OK. The caller should call + // UnlockFile(*lock) to release the lock. If the process exits, + // the lock will be automatically released. + // + // If somebody else already holds the lock, finishes immediately + // with a failure. I.e., this call does not wait for existing locks + // to go away. + // + // May create the named file if it does not already exist. + virtual Status LockFile(const std::string& fname, FileLock** lock) = 0; + + // Release the lock acquired by a previous successful call to LockFile. + // REQUIRES: lock was returned by a successful LockFile() call + // REQUIRES: lock has not already been unlocked. + virtual Status UnlockFile(FileLock* lock) = 0; + + // Arrange to run "(*function)(arg)" once in a background thread. + // + // "function" may run in an unspecified thread. Multiple functions + // added to the same Env may run concurrently in different threads. + // I.e., the caller may not assume that background work items are + // serialized. + virtual void Schedule( + void (*function)(void* arg), + void* arg) = 0; + + // Start a new thread, invoking "function(arg)" within the new thread. + // When "function(arg)" returns, the thread will be destroyed. + virtual void StartThread(void (*function)(void* arg), void* arg) = 0; + + // *path is set to a temporary directory that can be used for testing. It may + // or many not have just been created. The directory may or may not differ + // between runs of the same process, but subsequent calls will return the + // same directory. + virtual Status GetTestDirectory(std::string* path) = 0; + + // Create and return a log file for storing informational messages. + virtual Status NewLogger(const std::string& fname, + shared_ptr* result) = 0; + + // Returns the number of micro-seconds since some fixed point in time. Only + // useful for computing deltas of time. + virtual uint64_t NowMicros() = 0; + + // Sleep/delay the thread for the perscribed number of micro-seconds. + virtual void SleepForMicroseconds(int micros) = 0; + + // Get the current host name. + virtual Status GetHostName(char* name, uint64_t len) = 0; + + // Get the number of seconds since the Epoch, 1970-01-01 00:00:00 (UTC). + virtual Status GetCurrentTime(int64_t* unix_time) = 0; + + // Get full directory name for this db. + virtual Status GetAbsolutePath(const std::string& db_path, + std::string* output_path) = 0; + + // The number of background worker threads for this environment. + // default: 1 + virtual void SetBackgroundThreads(int number) = 0; + + // Converts seconds-since-Jan-01-1970 to a printable string + virtual std::string TimeToString(uint64_t time) = 0; + + private: + // No copying allowed + Env(const Env&); + void operator=(const Env&); +}; + +// A file abstraction for reading sequentially through a file +class SequentialFile { + public: + SequentialFile() { } + virtual ~SequentialFile(); + + // Read up to "n" bytes from the file. "scratch[0..n-1]" may be + // written by this routine. Sets "*result" to the data that was + // read (including if fewer than "n" bytes were successfully read). + // May set "*result" to point at data in "scratch[0..n-1]", so + // "scratch[0..n-1]" must be live when "*result" is used. + // If an error was encountered, returns a non-OK status. + // + // REQUIRES: External synchronization + virtual Status Read(size_t n, Slice* result, char* scratch) = 0; + + // Skip "n" bytes from the file. This is guaranteed to be no + // slower that reading the same data, but may be faster. + // + // If end of file is reached, skipping will stop at the end of the + // file, and Skip will return OK. + // + // REQUIRES: External synchronization + virtual Status Skip(uint64_t n) = 0; +}; + +// A file abstraction for randomly reading the contents of a file. +class RandomAccessFile { + public: + RandomAccessFile() { } + virtual ~RandomAccessFile(); + + // Read up to "n" bytes from the file starting at "offset". + // "scratch[0..n-1]" may be written by this routine. Sets "*result" + // to the data that was read (including if fewer than "n" bytes were + // successfully read). May set "*result" to point at data in + // "scratch[0..n-1]", so "scratch[0..n-1]" must be live when + // "*result" is used. If an error was encountered, returns a non-OK + // status. + // + // Safe for concurrent use by multiple threads. + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const = 0; + + // Tries to get an unique ID for this file that will be the same each time + // the file is opened (and will stay the same while the file is open). + // Furthermore, it tries to make this ID at most "max_size" bytes. If such an + // ID can be created this function returns the length of the ID and places it + // in "id"; otherwise, this function returns 0, in which case "id" may more + // may not have been modified. + // + // This function guarantees, for IDs from a given environment, two unique ids + // cannot be made equal to eachother by adding arbitrary bytes to one of + // them. That is, no unique ID is the prefix of another. + // + // This function guarantees that the returned ID will not be interpretable as + // a single varint. + // + // Note: these IDs are only valid for the duration of the process. + virtual size_t GetUniqueId(char* id, size_t max_size) const { + return 0; // Default implementation to prevent issues with backwards + // compatibility. + }; +}; + +// A file abstraction for sequential writing. The implementation +// must provide buffering since callers may append small fragments +// at a time to the file. +class WritableFile { + public: + WritableFile() : last_preallocated_block_(0), preallocation_block_size_ (0) { + } + virtual ~WritableFile(); + + virtual Status Append(const Slice& data) = 0; + virtual Status Close() = 0; + virtual Status Flush() = 0; + virtual Status Sync() = 0; // sync data + + /* + * Sync data and/or metadata as well. + * By default, sync only metadata. + * Override this method for environments where we need to sync + * metadata as well. + */ + virtual Status Fsync() { + return Sync(); + } + + /* + * Get the size of valid data in the file. + */ + virtual uint64_t GetFileSize() { + return 0; + } + + /* + * Get and set the default pre-allocation block size for writes to + * this file. If non-zero, then Allocate will be used to extend the + * underlying storage of a file (generally via fallocate) if the Env + * instance supports it. + */ + void SetPreallocationBlockSize(size_t size) { + preallocation_block_size_ = size; + } + + virtual void GetPreallocationStatus(size_t* block_size, + size_t* last_allocated_block) { + *last_allocated_block = last_preallocated_block_; + *block_size = preallocation_block_size_; + } + + protected: + // PrepareWrite performs any necessary preparation for a write + // before the write actually occurs. This allows for pre-allocation + // of space on devices where it can result in less file + // fragmentation and/or less waste from over-zealous filesystem + // pre-allocation. + void PrepareWrite(size_t offset, size_t len) { + if (preallocation_block_size_ == 0) { + return; + } + // If this write would cross one or more preallocation blocks, + // determine what the last preallocation block necesessary to + // cover this write would be and Allocate to that point. + const auto block_size = preallocation_block_size_; + size_t new_last_preallocated_block = + (offset + len + block_size - 1) / block_size; + if (new_last_preallocated_block > last_preallocated_block_) { + size_t num_spanned_blocks = + new_last_preallocated_block - last_preallocated_block_; + Allocate(block_size * last_preallocated_block_, + block_size * num_spanned_blocks); + last_preallocated_block_ = new_last_preallocated_block; + } + } + + /* + * Pre-allocate space for a file. + */ + virtual Status Allocate(off_t offset, off_t len) { + return Status::OK(); + } + + private: + size_t last_preallocated_block_; + size_t preallocation_block_size_; + // No copying allowed + WritableFile(const WritableFile&); + void operator=(const WritableFile&); +}; + +// An interface for writing log messages. +class Logger { + public: + enum { DO_NOT_SUPPORT_GET_LOG_FILE_SIZE = -1 }; + Logger() { } + virtual ~Logger(); + + // Write an entry to the log file with the specified format. + virtual void Logv(const char* format, va_list ap) = 0; + virtual size_t GetLogFileSize() const { + return DO_NOT_SUPPORT_GET_LOG_FILE_SIZE; + } + + private: + // No copying allowed + Logger(const Logger&); + void operator=(const Logger&); +}; + + +// Identifies a locked file. +class FileLock { + public: + FileLock() { } + virtual ~FileLock(); + private: + // No copying allowed + FileLock(const FileLock&); + void operator=(const FileLock&); +}; + +// Log the specified data to *info_log if info_log is non-nullptr. +extern void Log(const shared_ptr& info_log, const char* format, ...) +# if defined(__GNUC__) || defined(__clang__) + __attribute__((__format__ (__printf__, 2, 3))) +# endif + ; + +extern void Log(Logger* info_log, const char* format, ...) +# if defined(__GNUC__) || defined(__clang__) + __attribute__((__format__ (__printf__, 2, 3))) +# endif + ; + +// A utility routine: write "data" to the named file. +extern Status WriteStringToFile(Env* env, const Slice& data, + const std::string& fname); + +// A utility routine: read contents of named file into *data +extern Status ReadFileToString(Env* env, const std::string& fname, + std::string* data); + +// An implementation of Env that forwards all calls to another Env. +// May be useful to clients who wish to override just part of the +// functionality of another Env. +class EnvWrapper : public Env { + public: + // Initialize an EnvWrapper that delegates all calls to *t + explicit EnvWrapper(Env* t) : target_(t) { } + virtual ~EnvWrapper(); + + // Return the target to which this Env forwards all calls + Env* target() const { return target_; } + + // The following text is boilerplate that forwards all methods to target() + Status NewSequentialFile(const std::string& f, + unique_ptr* r) { + return target_->NewSequentialFile(f, r); + } + Status NewRandomAccessFile(const std::string& f, + unique_ptr* r) { + return target_->NewRandomAccessFile(f, r); + } + Status NewWritableFile(const std::string& f, unique_ptr* r) { + return target_->NewWritableFile(f, r); + } + bool FileExists(const std::string& f) { return target_->FileExists(f); } + Status GetChildren(const std::string& dir, std::vector* r) { + return target_->GetChildren(dir, r); + } + Status DeleteFile(const std::string& f) { return target_->DeleteFile(f); } + Status CreateDir(const std::string& d) { return target_->CreateDir(d); } + Status CreateDirIfMissing(const std::string& d) { + return target_->CreateDirIfMissing(d); + } + Status DeleteDir(const std::string& d) { return target_->DeleteDir(d); } + Status GetFileSize(const std::string& f, uint64_t* s) { + return target_->GetFileSize(f, s); + } + + Status GetFileModificationTime(const std::string& fname, + uint64_t* file_mtime) { + return target_->GetFileModificationTime(fname, file_mtime); + } + + Status RenameFile(const std::string& s, const std::string& t) { + return target_->RenameFile(s, t); + } + Status LockFile(const std::string& f, FileLock** l) { + return target_->LockFile(f, l); + } + Status UnlockFile(FileLock* l) { return target_->UnlockFile(l); } + void Schedule(void (*f)(void*), void* a) { + return target_->Schedule(f, a); + } + void StartThread(void (*f)(void*), void* a) { + return target_->StartThread(f, a); + } + virtual Status GetTestDirectory(std::string* path) { + return target_->GetTestDirectory(path); + } + virtual Status NewLogger(const std::string& fname, + shared_ptr* result) { + return target_->NewLogger(fname, result); + } + uint64_t NowMicros() { + return target_->NowMicros(); + } + void SleepForMicroseconds(int micros) { + target_->SleepForMicroseconds(micros); + } + Status GetHostName(char* name, uint64_t len) { + return target_->GetHostName(name, len); + } + Status GetCurrentTime(int64_t* unix_time) { + return target_->GetCurrentTime(unix_time); + } + Status GetAbsolutePath(const std::string& db_path, + std::string* output_path) { + return target_->GetAbsolutePath(db_path, output_path); + } + void SetBackgroundThreads(int num) { + return target_->SetBackgroundThreads(num); + } + std::string TimeToString(uint64_t time) { + return target_->TimeToString(time); + } + + private: + Env* target_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_ENV_H_ diff --git a/include/leveldb/filter_policy.h b/include/leveldb/filter_policy.h new file mode 100644 index 00000000..1fba0800 --- /dev/null +++ b/include/leveldb/filter_policy.h @@ -0,0 +1,70 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A database can be configured with a custom FilterPolicy object. +// This object is responsible for creating a small filter from a set +// of keys. These filters are stored in leveldb and are consulted +// automatically by leveldb to decide whether or not to read some +// information from disk. In many cases, a filter can cut down the +// number of disk seeks form a handful to a single disk seek per +// DB::Get() call. +// +// Most people will want to use the builtin bloom filter support (see +// NewBloomFilterPolicy() below). + +#ifndef STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_ +#define STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_ + +#include + +namespace leveldb { + +class Slice; + +class FilterPolicy { + public: + virtual ~FilterPolicy(); + + // Return the name of this policy. Note that if the filter encoding + // changes in an incompatible way, the name returned by this method + // must be changed. Otherwise, old incompatible filters may be + // passed to methods of this type. + virtual const char* Name() const = 0; + + // keys[0,n-1] contains a list of keys (potentially with duplicates) + // that are ordered according to the user supplied comparator. + // Append a filter that summarizes keys[0,n-1] to *dst. + // + // Warning: do not change the initial contents of *dst. Instead, + // append the newly constructed filter to *dst. + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) + const = 0; + + // "filter" contains the data appended by a preceding call to + // CreateFilter() on this class. This method must return true if + // the key was in the list of keys passed to CreateFilter(). + // This method may return true or false if the key was not on the + // list, but it should aim to return false with a high probability. + virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const = 0; +}; + +// Return a new filter policy that uses a bloom filter with approximately +// the specified number of bits per key. A good value for bits_per_key +// is 10, which yields a filter with ~ 1% false positive rate. +// +// Callers must delete the result after any database that is using the +// result has been closed. +// +// Note: if you are using a custom comparator that ignores some parts +// of the keys being compared, you must not use NewBloomFilterPolicy() +// and must provide your own FilterPolicy that also ignores the +// corresponding parts of the keys. For example, if the comparator +// ignores trailing spaces, it would be incorrect to use a +// FilterPolicy (like NewBloomFilterPolicy) that does not ignore +// trailing spaces in keys. +extern const FilterPolicy* NewBloomFilterPolicy(int bits_per_key); + +} + +#endif // STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_ diff --git a/include/leveldb/iterator.h b/include/leveldb/iterator.h new file mode 100644 index 00000000..ad543eb4 --- /dev/null +++ b/include/leveldb/iterator.h @@ -0,0 +1,100 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// An iterator yields a sequence of key/value pairs from a source. +// The following class defines the interface. Multiple implementations +// are provided by this library. In particular, iterators are provided +// to access the contents of a Table or a DB. +// +// Multiple threads can invoke const methods on an Iterator without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same Iterator must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_ITERATOR_H_ +#define STORAGE_LEVELDB_INCLUDE_ITERATOR_H_ + +#include "leveldb/slice.h" +#include "leveldb/status.h" + +namespace leveldb { + +class Iterator { + public: + Iterator(); + virtual ~Iterator(); + + // An iterator is either positioned at a key/value pair, or + // not valid. This method returns true iff the iterator is valid. + virtual bool Valid() const = 0; + + // Position at the first key in the source. The iterator is Valid() + // after this call iff the source is not empty. + virtual void SeekToFirst() = 0; + + // Position at the last key in the source. The iterator is + // Valid() after this call iff the source is not empty. + virtual void SeekToLast() = 0; + + // Position at the first key in the source that at or past target + // The iterator is Valid() after this call iff the source contains + // an entry that comes at or past target. + virtual void Seek(const Slice& target) = 0; + + // Moves to the next entry in the source. After this call, Valid() is + // true iff the iterator was not positioned at the last entry in the source. + // REQUIRES: Valid() + virtual void Next() = 0; + + // Moves to the previous entry in the source. After this call, Valid() is + // true iff the iterator was not positioned at the first entry in source. + // REQUIRES: Valid() + virtual void Prev() = 0; + + // Return the key for the current entry. The underlying storage for + // the returned slice is valid only until the next modification of + // the iterator. + // REQUIRES: Valid() + virtual Slice key() const = 0; + + // Return the value for the current entry. The underlying storage for + // the returned slice is valid only until the next modification of + // the iterator. + // REQUIRES: !AtEnd() && !AtStart() + virtual Slice value() const = 0; + + // If an error has occurred, return it. Else return an ok status. + virtual Status status() const = 0; + + // Clients are allowed to register function/arg1/arg2 triples that + // will be invoked when this iterator is destroyed. + // + // Note that unlike all of the preceding methods, this method is + // not abstract and therefore clients should not override it. + typedef void (*CleanupFunction)(void* arg1, void* arg2); + void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2); + + private: + struct Cleanup { + CleanupFunction function; + void* arg1; + void* arg2; + Cleanup* next; + }; + Cleanup cleanup_; + + // No copying allowed + Iterator(const Iterator&); + void operator=(const Iterator&); +}; + +// Return an empty iterator (yields nothing). +extern Iterator* NewEmptyIterator(); + +// Return an empty iterator with the specified status. +extern Iterator* NewErrorIterator(const Status& status); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_ITERATOR_H_ diff --git a/include/leveldb/options.h b/include/leveldb/options.h new file mode 100644 index 00000000..28aaba48 --- /dev/null +++ b/include/leveldb/options.h @@ -0,0 +1,474 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_OPTIONS_H_ +#define STORAGE_LEVELDB_INCLUDE_OPTIONS_H_ + +#include +#include +#include +#include +#include +#include "leveldb/slice.h" + +namespace leveldb { + +class Cache; +class Comparator; +class Env; +class FilterPolicy; +class Logger; +class Snapshot; +class Statistics; + +using std::shared_ptr; + +// DB contents are stored in a set of blocks, each of which holds a +// sequence of key,value pairs. Each block may be compressed before +// being stored in a file. The following enum describes which +// compression method (if any) is used to compress a block. +enum CompressionType { + // NOTE: do not change the values of existing entries, as these are + // part of the persistent format on disk. + kNoCompression = 0x0, + kSnappyCompression = 0x1, + kZlibCompression = 0x2, + kBZip2Compression = 0x3 +}; + +// Compression options for different compression algorithms like Zlib +struct CompressionOptions { + int window_bits; + int level; + int strategy; + CompressionOptions():window_bits(-14), + level(-1), + strategy(0){} + CompressionOptions(int wbits, int lev, int strategy):window_bits(wbits), + level(lev), + strategy(strategy){} +}; + +// Options to control the behavior of a database (passed to DB::Open) +struct Options { + // ------------------- + // Parameters that affect behavior + + // Comparator used to define the order of keys in the table. + // Default: a comparator that uses lexicographic byte-wise ordering + // + // REQUIRES: The client must ensure that the comparator supplied + // here has the same name and orders keys *exactly* the same as the + // comparator provided to previous open calls on the same DB. + const Comparator* comparator; + + // If true, the database will be created if it is missing. + // Default: false + bool create_if_missing; + + // If true, an error is raised if the database already exists. + // Default: false + bool error_if_exists; + + // If true, the implementation will do aggressive checking of the + // data it is processing and will stop early if it detects any + // errors. This may have unforeseen ramifications: for example, a + // corruption of one DB entry may cause a large number of entries to + // become unreadable or for the entire DB to become unopenable. + // Default: false + bool paranoid_checks; + + // Use the specified object to interact with the environment, + // e.g. to read/write files, schedule background work, etc. + // Default: Env::Default() + Env* env; + + // Any internal progress/error information generated by the db will + // be written to info_log if it is non-nullptr, or to a file stored + // in the same directory as the DB contents if info_log is nullptr. + // Default: nullptr + shared_ptr info_log; + + // ------------------- + // Parameters that affect performance + + // Amount of data to build up in memory (backed by an unsorted log + // on disk) before converting to a sorted on-disk file. + // + // Larger values increase performance, especially during bulk loads. + // Up to max_write_buffer_number write buffers may be held in memory + // at the same time, + // so you may wish to adjust this parameter to control memory usage. + // Also, a larger write buffer will result in a longer recovery time + // the next time the database is opened. + // + // Default: 4MB + size_t write_buffer_size; + + // The maximum number of write buffers that are built up in memory. + // The default is 2, so that when 1 write buffer is being flushed to + // storage, new writes can continue to the other write buffer. + // Default: 2 + int max_write_buffer_number; + + // Number of open files that can be used by the DB. You may need to + // increase this if your database has a large working set (budget + // one open file per 2MB of working set). + // + // Default: 1000 + int max_open_files; + + // Control over blocks (user data is stored in a set of blocks, and + // a block is the unit of reading from disk). + + // If non-NULL use the specified cache for blocks. + // If NULL, leveldb will automatically create and use an 8MB internal cache. + // Default: nullptr + shared_ptr block_cache; + + // Approximate size of user data packed per block. Note that the + // block size specified here corresponds to uncompressed data. The + // actual size of the unit read from disk may be smaller if + // compression is enabled. This parameter can be changed dynamically. + // + // Default: 4K + size_t block_size; + + // Number of keys between restart points for delta encoding of keys. + // This parameter can be changed dynamically. Most clients should + // leave this parameter alone. + // + // Default: 16 + int block_restart_interval; + + + // Compress blocks using the specified compression algorithm. This + // parameter can be changed dynamically. + // + // Default: kSnappyCompression, which gives lightweight but fast + // compression. + // + // Typical speeds of kSnappyCompression on an Intel(R) Core(TM)2 2.4GHz: + // ~200-500MB/s compression + // ~400-800MB/s decompression + // Note that these speeds are significantly faster than most + // persistent storage speeds, and therefore it is typically never + // worth switching to kNoCompression. Even if the input data is + // incompressible, the kSnappyCompression implementation will + // efficiently detect that and will switch to uncompressed mode. + CompressionType compression; + + // Different levels can have different compression policies. There + // are cases where most lower levels would like to quick compression + // algorithm while the higher levels (which have more data) use + // compression algorithms that have better compression but could + // be slower. This array, if non nullptr, should have an entry for + // each level of the database. This array, if non nullptr, overides the + // value specified in the previous field 'compression'. The caller is + // reponsible for allocating memory and initializing the values in it + // before invoking Open(). The caller is responsible for freeing this + // array and it could be freed anytime after the return from Open(). + // This could have been a std::vector but that makes the equivalent + // java/C api hard to construct. + std::vector compression_per_level; + + //different options for compression algorithms + CompressionOptions compression_opts; + + // If non-nullptr, use the specified filter policy to reduce disk reads. + // Many applications will benefit from passing the result of + // NewBloomFilterPolicy() here. + // + // Default: nullptr + const FilterPolicy* filter_policy; + + // Number of levels for this database + int num_levels; + + // Number of files to trigger level-0 compaction. A value <0 means that + // level-0 compaction will not be triggered by number of files at all. + int level0_file_num_compaction_trigger; + + // Soft limit on number of level-0 files. We slow down writes at this point. + // A value <0 means that no writing slow down will be triggered by number + // of files in level-0. + int level0_slowdown_writes_trigger; + + // Maximum number of level-0 files. We stop writes at this point. + int level0_stop_writes_trigger; + + // Maximum level to which a new compacted memtable is pushed if it + // does not create overlap. We try to push to level 2 to avoid the + // relatively expensive level 0=>1 compactions and to avoid some + // expensive manifest file operations. We do not push all the way to + // the largest level since that can generate a lot of wasted disk + // space if the same key space is being repeatedly overwritten. + int max_mem_compaction_level; + + // Target file size for compaction. + // target_file_size_base is per-file size for level-1. + // Target file size for level L can be calculated by + // target_file_size_base * (target_file_size_multiplier ^ (L-1)) + // For example, if target_file_size_base is 2MB and + // target_file_size_multiplier is 10, then each file on level-1 will + // be 2MB, and each file on level 2 will be 20MB, + // and each file on level-3 will be 200MB. + + // by default target_file_size_base is 2MB. + int target_file_size_base; + // by default target_file_size_multiplier is 1, which means + // by default files in different levels will have similar size. + int target_file_size_multiplier; + + // Control maximum total data size for a level. + // max_bytes_for_level_base is the max total for level-1. + // Maximum number of bytes for level L can be calculated as + // (max_bytes_for_level_base) * (max_bytes_for_level_multiplier ^ (L-1)) + // For example, if max_bytes_for_level_base is 20MB, and if + // max_bytes_for_level_multiplier is 10, total data size for level-1 + // will be 20MB, total file size for level-2 will be 200MB, + // and total file size for level-3 will be 2GB. + + + // by default 'max_bytes_for_level_base' is 10MB. + uint64_t max_bytes_for_level_base; + // by default 'max_bytes_for_level_base' is 10. + int max_bytes_for_level_multiplier; + + // Maximum number of bytes in all compacted files. We avoid expanding + // the lower level file set of a compaction if it would make the + // total compaction cover more than + // (expanded_compaction_factor * targetFileSizeLevel()) many bytes. + int expanded_compaction_factor; + + // Maximum number of bytes in all source files to be compacted in a + // single compaction run. We avoid picking too many files in the + // source level so that we do not exceed the total source bytes + // for compaction to exceed + // (source_compaction_factor * targetFileSizeLevel()) many bytes. + // Default:1, i.e. pick maxfilesize amount of data as the source of + // a compaction. + int source_compaction_factor; + + // Control maximum bytes of overlaps in grandparent (i.e., level+2) before we + // stop building a single file in a level->level+1 compaction. + int max_grandparent_overlap_factor; + + // If non-null, then we should collect metrics about database operations + // Statistics objects should not be shared between DB instances as + // it does not use any locks to prevent concurrent updates. + Statistics* statistics; + + // If true, then the contents of data files are not synced + // to stable storage. Their contents remain in the OS buffers till the + // OS decides to flush them. This option is good for bulk-loading + // of data. Once the bulk-loading is complete, please issue a + // sync to the OS to flush all dirty buffesrs to stable storage. + // Default: false + bool disableDataSync; + + // If true, then every store to stable storage will issue a fsync. + // If false, then every store to stable storage will issue a fdatasync. + // This parameter should be set to true while storing data to + // filesystem like ext3 which can lose files after a reboot. + // Default: false + bool use_fsync; + + // This number controls how often a new scribe log about + // db deploy stats is written out. + // -1 indicates no logging at all. + // Default value is 1800 (half an hour). + int db_stats_log_interval; + + // This specifies the log dir. + // If it is empty, the log files will be in the same dir as data. + // If it is non empty, the log files will be in the specified dir, + // and the db data dir's absolute path will be used as the log file + // name's prefix. + std::string db_log_dir; + + // Disable compaction triggered by seek. + // With bloomfilter and fast storage, a miss on one level + // is very cheap if the file handle is cached in table cache + // (which is true if max_open_files is large). + bool disable_seek_compaction; + + // The periodicity when obsolete files get deleted. The default + // value is 0 which means that obsolete files get removed after + // every compaction run. + uint64_t delete_obsolete_files_period_micros; + + // Maximum number of concurrent background compactions. + // Default: 1 + int max_background_compactions; + + // Specify the maximal size of the info log file. If the log file + // is larger than `max_log_file_size`, a new info log file will + // be created. + // If max_log_file_size == 0, all logs will be written to one + // log file. + size_t max_log_file_size; + + // Time for the info log file to roll (in seconds). + // If specified with non-zero value, log file will be rolled + // if it has been active longer than `log_file_time_to_roll`. + // Default: 0 (disabled) + size_t log_file_time_to_roll; + + // Maximal info log files to be kept. + // Default: 1000 + size_t keep_log_file_num; + + // Puts are delayed when any level has a compaction score that + // exceeds rate_limit. This is ignored when <= 1.0. + double rate_limit; + + // Max time a put will be stalled when rate_limit is enforced + int rate_limit_delay_milliseconds; + + // manifest file is rolled over on reaching this limit. + // The older manifest file be deleted. + // The default value is MAX_INT so that roll-over does not take place. + uint64_t max_manifest_file_size; + + // Disable block cache. If this is set to false, + // then no block cache should be used, and the block_cache should + // point to a nullptr object. + bool no_block_cache; + + // Number of shards used for table cache. + int table_cache_numshardbits; + + // Create an Options object with default values for all fields. + Options(); + + void Dump(Logger* log) const; + + // Set appropriate parameters for bulk loading. + // The reason that this is a function that returns "this" instead of a + // constructure is to enable chaining of multiple similar calls in the future. + // + // All data will be in level 0 without any automatic compaction. + // It's recommended to manually call CompactRange(NULL, NULL) before reading + // from the database, because otherwise the read can be very slow. + Options* PrepareForBulkLoad(); + + // This method allows an application to modify/delete a key-value at + // the time of compaction. The compaction process invokes this + // method for every kv that is being compacted. A return value + // of false indicates that the kv should be preserved in the + // output of this compaction run and a return value of true + // indicates that this key-value should be removed from the + // output of the compaction. The application can inspect + // the existing value of the key, modify it if needed and + // return back the new value for this key. The application + // should allocate memory for the Slice object that is used to + // return the new value and the leveldb framework will + // free up that memory. + // The compaction_filter_args, if specified here, are passed + // back to the invocation of the CompactionFilter. + void* compaction_filter_args; + bool (*CompactionFilter)(void* compaction_filter_args, + int level, const Slice& key, + const Slice& existing_value, Slice** new_value); + + // Disable automatic compactions. Manual compactions can still + // be issued on this database. + bool disable_auto_compactions; + + // The number of seconds a WAL(write ahead log) should be kept after it has + // been marked as Not Live. If the value is set. The WAL files are moved to + // the archive direcotory and deleted after the given TTL. + // If set to 0, WAL files are deleted as soon as they are not required by + // the database. + // If set to std::numeric_limits::max() the WAL files will never be + // deleted. + // Default : 0 + uint64_t WAL_ttl_seconds; + + // Number of bytes to preallocate (via fallocate) the manifest + // files. Default is 4mb, which is reasonable to reduce random IO + // as well as prevent overallocation for mounts that preallocate + // large amounts of data (such as xfs's allocsize option). + size_t manifest_preallocation_size; + + // Purge duplicate/deleted keys when a memtable is flushed to storage. + // Default: true + bool purge_redundant_kvs_while_flush; +}; + +// Options that control read operations +struct ReadOptions { + // If true, all data read from underlying storage will be + // verified against corresponding checksums. + // Default: false + bool verify_checksums; + + // Should the data read for this iteration be cached in memory? + // Callers may wish to set this field to false for bulk scans. + // Default: true + bool fill_cache; + + // If "snapshot" is non-nullptr, read as of the supplied snapshot + // (which must belong to the DB that is being read and which must + // not have been released). If "snapshot" is nullptr, use an impliicit + // snapshot of the state at the beginning of this read operation. + // Default: nullptr + const Snapshot* snapshot; + + ReadOptions() + : verify_checksums(false), + fill_cache(true), + snapshot(nullptr) { + } + ReadOptions(bool cksum, bool cache) : + verify_checksums(cksum), fill_cache(cache), + snapshot(nullptr) { + } +}; + +// Options that control write operations +struct WriteOptions { + // If true, the write will be flushed from the operating system + // buffer cache (by calling WritableFile::Sync()) before the write + // is considered complete. If this flag is true, writes will be + // slower. + // + // If this flag is false, and the machine crashes, some recent + // writes may be lost. Note that if it is just the process that + // crashes (i.e., the machine does not reboot), no writes will be + // lost even if sync==false. + // + // In other words, a DB write with sync==false has similar + // crash semantics as the "write()" system call. A DB write + // with sync==true has similar crash semantics to a "write()" + // system call followed by "fsync()". + // + // Default: false + bool sync; + + // If true, writes will not first go to the write ahead log, + // and the write may got lost after a crash. + bool disableWAL; + + WriteOptions() + : sync(false), + disableWAL(false) { + } +}; + +// Options that control flush operations +struct FlushOptions { + // If true, the flush will wait until the flush is done. + // Default: true + bool wait; + + FlushOptions() + : wait(true) { + } +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_OPTIONS_H_ diff --git a/include/leveldb/slice.h b/include/leveldb/slice.h new file mode 100644 index 00000000..e0fc9aa2 --- /dev/null +++ b/include/leveldb/slice.h @@ -0,0 +1,121 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Slice is a simple structure containing a pointer into some external +// storage and a size. The user of a Slice must ensure that the slice +// is not used after the corresponding external storage has been +// deallocated. +// +// Multiple threads can invoke const methods on a Slice without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same Slice must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_SLICE_H_ +#define STORAGE_LEVELDB_INCLUDE_SLICE_H_ + +#include +#include +#include +#include + +namespace leveldb { + +class Slice { + public: + // Create an empty slice. + Slice() : data_(""), size_(0) { } + + // Create a slice that refers to d[0,n-1]. + Slice(const char* d, size_t n) : data_(d), size_(n) { } + + // Create a slice that refers to the contents of "s" + Slice(const std::string& s) : data_(s.data()), size_(s.size()) { } + + // Create a slice that refers to s[0,strlen(s)-1] + Slice(const char* s) : data_(s), size_(strlen(s)) { } + + // Return a pointer to the beginning of the referenced data + const char* data() const { return data_; } + + // Return the length (in bytes) of the referenced data + size_t size() const { return size_; } + + // Return true iff the length of the referenced data is zero + bool empty() const { return size_ == 0; } + + // Return the ith byte in the referenced data. + // REQUIRES: n < size() + char operator[](size_t n) const { + assert(n < size()); + return data_[n]; + } + + // Change this slice to refer to an empty array + void clear() { data_ = ""; size_ = 0; } + + // Drop the first "n" bytes from this slice. + void remove_prefix(size_t n) { + assert(n <= size()); + data_ += n; + size_ -= n; + } + + // Return a string that contains the copy of the referenced data. + std::string ToString(bool hex = false) const { + if (hex) { + std::string result; + char buf[10]; + for (size_t i = 0; i < size_; i++) { + snprintf(buf, 10, "%02X", (unsigned char)data_[i]); + result += buf; + } + return result; + } else { + return std::string(data_, size_); + } + } + + // Three-way comparison. Returns value: + // < 0 iff "*this" < "b", + // == 0 iff "*this" == "b", + // > 0 iff "*this" > "b" + int compare(const Slice& b) const; + + // Return true iff "x" is a prefix of "*this" + bool starts_with(const Slice& x) const { + return ((size_ >= x.size_) && + (memcmp(data_, x.data_, x.size_) == 0)); + } + + // private: make these public for leveldbjni access + const char* data_; + size_t size_; + + // Intentionally copyable +}; + +inline bool operator==(const Slice& x, const Slice& y) { + return ((x.size() == y.size()) && + (memcmp(x.data(), y.data(), x.size()) == 0)); +} + +inline bool operator!=(const Slice& x, const Slice& y) { + return !(x == y); +} + +inline int Slice::compare(const Slice& b) const { + const int min_len = (size_ < b.size_) ? size_ : b.size_; + int r = memcmp(data_, b.data_, min_len); + if (r == 0) { + if (size_ < b.size_) r = -1; + else if (size_ > b.size_) r = +1; + } + return r; +} + +} // namespace leveldb + + +#endif // STORAGE_LEVELDB_INCLUDE_SLICE_H_ diff --git a/include/leveldb/statistics.h b/include/leveldb/statistics.h new file mode 100644 index 00000000..db441c0f --- /dev/null +++ b/include/leveldb/statistics.h @@ -0,0 +1,136 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_STATISTICS_H_ +#define STORAGE_LEVELDB_INCLUDE_STATISTICS_H_ + +#include +#include +#include +#include + +namespace leveldb { + +/** + * Keep adding ticker's here. + * Any ticker should have a value less than TICKER_ENUM_MAX. + * Add a new ticker by assigning it the current value of TICKER_ENUM_MAX + * And incrementing TICKER_ENUM_MAX. + */ +enum Tickers { + BLOCK_CACHE_MISS = 0, + BLOCK_CACHE_HIT = 1, + BLOOM_FILTER_USEFUL = 2, // no. of times bloom filter has avoided file reads. + /** + * COMPACTION_KEY_DROP_* count the reasons for key drop during compaction + * There are 3 reasons currently. + */ + COMPACTION_KEY_DROP_NEWER_ENTRY = 3, // key was written with a newer value. + COMPACTION_KEY_DROP_OBSOLETE = 4, // The key is obsolete. + COMPACTION_KEY_DROP_USER = 5, // user compaction function has dropped the key. + // Number of keys written to the database via the Put and Write call's + NUMBER_KEYS_WRITTEN = 6, + // Number of Keys read, + NUMBER_KEYS_READ = 7, + // Bytes written / read + BYTES_WRITTEN = 8, + BYTES_READ = 9, + NO_FILE_CLOSES = 10, + NO_FILE_OPENS = 11, + NO_FILE_ERRORS = 12, + TICKER_ENUM_MAX = 13, +}; + + +/** + * Keep adding histogram's here. + * Any histogram whould have value less than HISTOGRAM_ENUM_MAX + * Add a new Histogram by assigning it the current value of HISTOGRAM_ENUM_MAX + * And increment HISTOGRAM_ENUM_MAX + */ +enum Histograms { + DB_GET = 0, + DB_WRITE = 1, + COMPACTION_TIME = 2, + HISTOGRAM_ENUM_MAX = 3, +}; + +struct HistogramData { + double median; + double percentile95; + double percentile99; + double average; + double standard_deviation; +}; + + +class Histogram { + public: + // clear's the histogram + virtual void Clear() = 0; + virtual ~Histogram(); + // Add a value to be recorded in the histogram. + virtual void Add(uint64_t value) = 0; + virtual void Add(double value) = 0; + + virtual std::string ToString() const = 0; + + // Get statistics + virtual double Median() const = 0; + virtual double Percentile(double p) const = 0; + virtual double Average() const = 0; + virtual double StandardDeviation() const = 0; + virtual void Data(HistogramData * const data) const = 0; + +}; + +/** + * A dumb ticker which keeps incrementing through its life time. + * Not thread safe. Locking is currently managed by external leveldb lock + */ +class Ticker { + public: + Ticker() : count_(0) { } + + inline void recordTick() { + count_++; + } + + inline void recordTick(int count) { + count_ += count; + } + + inline uint64_t getCount() { + return count_; + } + + private: + uint64_t count_; + +}; + +// Analyze the performance of a db +class Statistics { + public: + + virtual long getTickerCount(Tickers tickerType) = 0; + virtual void recordTick(Tickers tickerType, uint64_t count = 0) = 0; + virtual void measureTime(Histograms histogramType, uint64_t count) = 0; + virtual void measureTime(Histograms histogramType, double count) = 0; + + virtual void histogramData(Histograms type, HistogramData * const data) = 0; + +}; + +// Ease of Use functions +inline void RecordTick(Statistics* const statistics, + Tickers ticker, + uint64_t count = 1) { + if (statistics != nullptr) { + statistics->recordTick(ticker, count); + } +} +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_STATISTICS_H_ diff --git a/include/leveldb/status.h b/include/leveldb/status.h new file mode 100644 index 00000000..3e4573cb --- /dev/null +++ b/include/leveldb/status.h @@ -0,0 +1,112 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A Status encapsulates the result of an operation. It may indicate success, +// or it may indicate an error with an associated error message. +// +// Multiple threads can invoke const methods on a Status without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same Status must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_STATUS_H_ +#define STORAGE_LEVELDB_INCLUDE_STATUS_H_ + +#include +#include "leveldb/slice.h" + +namespace leveldb { + +class Status { + public: + // Create a success status. + Status() : state_(nullptr) { } + ~Status() { delete[] state_; } + + // Copy the specified status. + Status(const Status& s); + void operator=(const Status& s); + + // Return a success status. + static Status OK() { return Status(); } + + // Return error status of an appropriate type. + static Status NotFound(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kNotFound, msg, msg2); + } + static Status Corruption(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kCorruption, msg, msg2); + } + static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kNotSupported, msg, msg2); + } + static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kInvalidArgument, msg, msg2); + } + static Status IOError(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kIOError, msg, msg2); + } + + // Returns true iff the status indicates success. + bool ok() const { return (state_ == nullptr); } + + // Returns true iff the status indicates a NotFound error. + bool IsNotFound() const { return code() == kNotFound; } + + // Returns true iff the status indicates a Corruption error. + bool IsCorruption() const { return code() == kCorruption; } + + // Returns true iff the status indicates a NotSupported error. + bool IsNotSupported() const { return code() == kNotSupported; } + + // Returns true iff the status indicates an InvalidArgument error. + bool IsInvalidArgument() const { return code() == kInvalidArgument; } + + // Returns true iff the status indicates an IOError. + bool IsIOError() const { return code() == kIOError; } + + // Return a string representation of this status suitable for printing. + // Returns the string "OK" for success. + std::string ToString() const; + + private: + // OK status has a nullptr state_. Otherwise, state_ is a new[] array + // of the following form: + // state_[0..3] == length of message + // state_[4] == code + // state_[5..] == message + const char* state_; + + enum Code { + kOk = 0, + kNotFound = 1, + kCorruption = 2, + kNotSupported = 3, + kInvalidArgument = 4, + kIOError = 5 + }; + + Code code() const { + return (state_ == nullptr) ? kOk : static_cast(state_[4]); + } + + Status(Code code, const Slice& msg, const Slice& msg2); + static const char* CopyState(const char* s); +}; + +inline Status::Status(const Status& s) { + state_ = (s.state_ == nullptr) ? nullptr : CopyState(s.state_); +} +inline void Status::operator=(const Status& s) { + // The following condition catches both aliasing (when this == &s), + // and the common case where both s and *this are ok. + if (state_ != s.state_) { + delete[] state_; + state_ = (s.state_ == nullptr) ? nullptr : CopyState(s.state_); + } +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_STATUS_H_ diff --git a/include/leveldb/table.h b/include/leveldb/table.h new file mode 100644 index 00000000..f3f3cd92 --- /dev/null +++ b/include/leveldb/table.h @@ -0,0 +1,96 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_TABLE_H_ +#define STORAGE_LEVELDB_INCLUDE_TABLE_H_ + +#include +#include +#include "leveldb/iterator.h" + +namespace leveldb { + +class Block; +class BlockHandle; +class Footer; +struct Options; +class RandomAccessFile; +struct ReadOptions; +class TableCache; + +using std::unique_ptr; + +// A Table is a sorted map from strings to strings. Tables are +// immutable and persistent. A Table may be safely accessed from +// multiple threads without external synchronization. +class Table { + public: + // Attempt to open the table that is stored in bytes [0..file_size) + // of "file", and read the metadata entries necessary to allow + // retrieving data from the table. + // + // If successful, returns ok and sets "*table" to the newly opened + // table. The client should delete "*table" when no longer needed. + // If there was an error while initializing the table, sets "*table" + // to nullptr and returns a non-ok status. Does not take ownership of + // "*source", but the client must ensure that "source" remains live + // for the duration of the returned table's lifetime. + // + // *file must remain live while this Table is in use. + static Status Open(const Options& options, + unique_ptr&& file, + uint64_t file_size, + unique_ptr* table); + + ~Table(); + + // Returns a new iterator over the table contents. + // The result of NewIterator() is initially invalid (caller must + // call one of the Seek methods on the iterator before using it). + Iterator* NewIterator(const ReadOptions&) const; + + // Given a key, return an approximate byte offset in the file where + // the data for that key begins (or would begin if the key were + // present in the file). The returned value is in terms of file + // bytes, and so includes effects like compression of the underlying data. + // E.g., the approximate offset of the last key in the table will + // be close to the file length. + uint64_t ApproximateOffsetOf(const Slice& key) const; + + // Returns true if the block for the specified key is in cache. + // REQUIRES: key is in this table. + bool TEST_KeyInCache(const ReadOptions& options, const Slice& key); + + private: + struct Rep; + Rep* rep_; + + explicit Table(Rep* rep) { rep_ = rep; } + static Iterator* BlockReader(void*, const ReadOptions&, const Slice&); + static Iterator* BlockReader(void*, const ReadOptions&, const Slice&, + bool* didIO); + + // Calls (*handle_result)(arg, ...) with the entry found after a call + // to Seek(key). May not make such a call if filter policy says + // that key is not present. + friend class TableCache; + Status InternalGet( + const ReadOptions&, const Slice& key, + void* arg, + void (*handle_result)(void* arg, const Slice& k, const Slice& v, bool)); + + + void ReadMeta(const Footer& footer); + void ReadFilter(const Slice& filter_handle_value); + + static void SetupCacheKeyPrefix(Rep* rep); + + // No copying allowed + Table(const Table&); + void operator=(const Table&); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_TABLE_H_ diff --git a/include/leveldb/table_builder.h b/include/leveldb/table_builder.h new file mode 100644 index 00000000..6ae1ccf8 --- /dev/null +++ b/include/leveldb/table_builder.h @@ -0,0 +1,95 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// TableBuilder provides the interface used to build a Table +// (an immutable and sorted map from keys to values). +// +// Multiple threads can invoke const methods on a TableBuilder without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same TableBuilder must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_ +#define STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_ + +#include +#include "leveldb/options.h" +#include "leveldb/status.h" + +namespace leveldb { + +class BlockBuilder; +class BlockHandle; +class WritableFile; + +class TableBuilder { + public: + // Create a builder that will store the contents of the table it is + // building in *file. Does not close the file. It is up to the + // caller to close the file after calling Finish(). The output file + // will be part of level specified by 'level'. A value of -1 means + // that the caller does not know which level the output file will reside. + TableBuilder(const Options& options, WritableFile* file, int level=-1); + + // REQUIRES: Either Finish() or Abandon() has been called. + ~TableBuilder(); + + // Change the options used by this builder. Note: only some of the + // option fields can be changed after construction. If a field is + // not allowed to change dynamically and its value in the structure + // passed to the constructor is different from its value in the + // structure passed to this method, this method will return an error + // without changing any fields. + Status ChangeOptions(const Options& options); + + // Add key,value to the table being constructed. + // REQUIRES: key is after any previously added key according to comparator. + // REQUIRES: Finish(), Abandon() have not been called + void Add(const Slice& key, const Slice& value); + + // Advanced operation: flush any buffered key/value pairs to file. + // Can be used to ensure that two adjacent entries never live in + // the same data block. Most clients should not need to use this method. + // REQUIRES: Finish(), Abandon() have not been called + void Flush(); + + // Return non-ok iff some error has been detected. + Status status() const; + + // Finish building the table. Stops using the file passed to the + // constructor after this function returns. + // REQUIRES: Finish(), Abandon() have not been called + Status Finish(); + + // Indicate that the contents of this builder should be abandoned. Stops + // using the file passed to the constructor after this function returns. + // If the caller is not going to call Finish(), it must call Abandon() + // before destroying this builder. + // REQUIRES: Finish(), Abandon() have not been called + void Abandon(); + + // Number of calls to Add() so far. + uint64_t NumEntries() const; + + // Size of the file generated so far. If invoked after a successful + // Finish() call, returns the size of the final generated file. + uint64_t FileSize() const; + + private: + bool ok() const { return status().ok(); } + void WriteBlock(BlockBuilder* block, BlockHandle* handle); + void WriteRawBlock(const Slice& data, CompressionType, BlockHandle* handle); + + struct Rep; + Rep* rep_; + int level_; + + // No copying allowed + TableBuilder(const TableBuilder&); + void operator=(const TableBuilder&); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_ diff --git a/include/leveldb/transaction_log_iterator.h b/include/leveldb/transaction_log_iterator.h new file mode 100644 index 00000000..d755d829 --- /dev/null +++ b/include/leveldb/transaction_log_iterator.h @@ -0,0 +1,42 @@ +// Copyright 2008-present Facebook. All Rights Reserved. +#ifndef STORAGE_LEVELDB_INCLUDE_TRANSACTION_LOG_ITERATOR_H_ +#define STORAGE_LEVELDB_INCLUDE_TRANSACTION_LOG_ITERATOR_H_ + +#include "leveldb/status.h" +#include "leveldb/write_batch.h" + +namespace leveldb { + + +struct BatchResult { + SequenceNumber sequence; + std::unique_ptr writeBatchPtr; +}; + +// A TransactionLogIterator is used to iterate over the Transaction's in a db. +class TransactionLogIterator { + public: + TransactionLogIterator() {} + virtual ~TransactionLogIterator() {} + + // An iterator is either positioned at a WriteBatch or not valid. + // This method returns true if the iterator is valid. + // Can read data from a valid iterator. + virtual bool Valid() = 0; + + // Moves the iterator to the next WriteBatch. + // REQUIRES: Valid() to be true. + virtual void Next() = 0; + + // Return's ok if the iterator is valid. + // Return the Error when something has gone wrong. + virtual Status status() = 0; + + // If valid return's the current write_batch and the sequence number of the + // latest transaction contained in the batch. + // ONLY use if Valid() is true and status() is OK. + virtual BatchResult GetBatch() = 0; +}; +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_TRANSACTION_LOG_ITERATOR_H_ diff --git a/include/leveldb/types.h b/include/leveldb/types.h new file mode 100644 index 00000000..6ec058c2 --- /dev/null +++ b/include/leveldb/types.h @@ -0,0 +1,14 @@ +#ifndef STORAGE_LEVELDB_INCLUDE_TYPES_H_ +#define STORAGE_LEVELDB_INCLUDE_TYPES_H_ + +#include + +namespace leveldb { + +// Define all public custom types here. + +// Represents a sequence number in a WAL file. +typedef uint64_t SequenceNumber; + +} // namespace leveldb +#endif // STORAGE_LEVELDB_INCLUDE_TYPES_H_ diff --git a/include/leveldb/write_batch.h b/include/leveldb/write_batch.h new file mode 100644 index 00000000..6546cada --- /dev/null +++ b/include/leveldb/write_batch.h @@ -0,0 +1,70 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// WriteBatch holds a collection of updates to apply atomically to a DB. +// +// The updates are applied in the order in which they are added +// to the WriteBatch. For example, the value of "key" will be "v3" +// after the following batch is written: +// +// batch.Put("key", "v1"); +// batch.Delete("key"); +// batch.Put("key", "v2"); +// batch.Put("key", "v3"); +// +// Multiple threads can invoke const methods on a WriteBatch without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same WriteBatch must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ +#define STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ + +#include +#include "leveldb/status.h" + +namespace leveldb { + +class Slice; + +class WriteBatch { + public: + WriteBatch(); + ~WriteBatch(); + + // Store the mapping "key->value" in the database. + void Put(const Slice& key, const Slice& value); + + // If the database contains a mapping for "key", erase it. Else do nothing. + void Delete(const Slice& key); + + // Clear all updates buffered in this batch. + void Clear(); + + // Support for iterating over the contents of a batch. + class Handler { + public: + virtual ~Handler(); + virtual void Put(const Slice& key, const Slice& value) = 0; + virtual void Delete(const Slice& key) = 0; + }; + Status Iterate(Handler* handler) const; + + // Retrive the serialized version of this batch. + std::string Data() { return rep_; } + + // Constructor with a serialized string object + WriteBatch(std::string rep): rep_(rep) {} + + private: + friend class WriteBatchInternal; + + std::string rep_; // See comment in write_batch.cc for the format of rep_ + + // Intentionally copyable +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ diff --git a/java/README b/java/README new file mode 100644 index 00000000..931f9a21 --- /dev/null +++ b/java/README @@ -0,0 +1,20 @@ +############################################################################### +leveldb - A Java port of LevelDB (https://github.com/dain/leveldb) + +This is a Java port of LevelDB. We only need the interface part, so the +implementation part is not checked in. + +This is based on commit: c8d074b3d95f30612e573bba689b85749031d639 from +https://github.com/dain/leveldb.git + +############################################################################### + +leveldbjni - JNI Wrapper for LevelDB (https://github.com/fusesource/leveldbjni) + +Provide LevelDB implementation by using JNI wrapper. It is written using HawtJNI +which is JNI code generatori (http://hawtjni.fusesource.org/). + +This is based on commmit: 8bac93ec1bcc97a098a1eaac265ea04b766ef574 from +https://github.com/fusesource/leveldbjni.git + +############################################################################### diff --git a/java/leveldb/.gitignore b/java/leveldb/.gitignore new file mode 100644 index 00000000..67590d81 --- /dev/null +++ b/java/leveldb/.gitignore @@ -0,0 +1,22 @@ +target/ +/var +pom.xml.versionsBackup +test-output/ +/atlassian-ide-plugin.x +.idea +.*.swp +.*.swo +leveldb-c +*~ +*.swp +.idea +.idea/* +*.iml +*.ipr +*.iws +.DS_Store +.scala_dependencies +.project +.classpath +.settings +eclipse-classes diff --git a/java/leveldb/leveldb-api/pom.xml b/java/leveldb/leveldb-api/pom.xml new file mode 100644 index 00000000..c8a484df --- /dev/null +++ b/java/leveldb/leveldb-api/pom.xml @@ -0,0 +1,19 @@ + + + + 4.0.0 + + org.iq80.leveldb + leveldb-project + 0.4-SNAPSHOT + + + org.iq80.leveldb + leveldb-api + 0.4-SNAPSHOT + jar + + ${project.artifactId} + High level Java API for LevelDB + + diff --git a/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/CompressionType.java b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/CompressionType.java new file mode 100644 index 00000000..4c622dfc --- /dev/null +++ b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/CompressionType.java @@ -0,0 +1,45 @@ +/** + * Copyright (C) 2011 the original author or authors. + * See the notice.md file distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.iq80.leveldb; + +public enum CompressionType +{ + NONE(0x00), + SNAPPY(0x01); + + public static CompressionType getCompressionTypeByPersistentId(int persistentId) { + for (CompressionType compressionType : CompressionType.values()) { + if (compressionType.persistentId == persistentId) { + return compressionType; + } + } + throw new IllegalArgumentException("Unknown persistentId " + persistentId); + } + + private final int persistentId; + + CompressionType(int persistentId) + { + this.persistentId = persistentId; + } + + public int persistentId() + { + return persistentId; + } +} diff --git a/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/DB.java b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/DB.java new file mode 100644 index 00000000..9c3fbe8c --- /dev/null +++ b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/DB.java @@ -0,0 +1,62 @@ +/** + * Copyright (C) 2011 the original author or authors. + * See the notice.md file distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.iq80.leveldb; + +import java.io.Closeable; +import java.util.Map; + +/** + * @author Hiram Chirino + */ +public interface DB extends Iterable>, Closeable { + + public byte[] get(byte[] key) throws DBException; + public byte[] get(byte[] key, ReadOptions options) throws DBException; + + public DBIterator iterator(); + public DBIterator iterator(ReadOptions options); + + public void put(byte[] key, byte[] value) throws DBException; + public void delete(byte[] key) throws DBException; + public void write(WriteBatch updates) throws DBException; + + public WriteBatch createWriteBatch(); + + /** + * @return null if options.isSnapshot()==false otherwise returns a snapshot + * of the DB after this operation. + */ + public Snapshot put(byte[] key, byte[] value, WriteOptions options) throws DBException; + + /** + * @return null if options.isSnapshot()==false otherwise returns a snapshot + * of the DB after this operation. + */ + public Snapshot delete(byte[] key, WriteOptions options) throws DBException; + + /** + * @return null if options.isSnapshot()==false otherwise returns a snapshot + * of the DB after this operation. + */ + public Snapshot write(WriteBatch updates, WriteOptions options) throws DBException; + + public Snapshot getSnapshot(); + + public long[] getApproximateSizes(Range ... ranges); + public String getProperty(String name); +} diff --git a/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/DBComparator.java b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/DBComparator.java new file mode 100644 index 00000000..1a583118 --- /dev/null +++ b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/DBComparator.java @@ -0,0 +1,47 @@ +/** + * Copyright (C) 2011 the original author or authors. + * See the notice.md file distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.iq80.leveldb; + +import java.util.Comparator; + +/** + * @author Hiram Chirino + */ +public interface DBComparator extends Comparator{ + + public String name(); + + /** + * If start < limit, returns a short key in [start,limit). + * Simple comparator implementations should return start unchanged, + * + * @param start + * @param limit + * @return + */ + byte[] findShortestSeparator(byte[] start, byte[] limit); + + /** + * returns a 'short key' where the 'short key' >= key. + * Simple comparator implementations should return key unchanged, + * + * @param key + */ + byte[] findShortSuccessor(byte[] key); + +} diff --git a/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/DBException.java b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/DBException.java new file mode 100644 index 00000000..09cf5ba0 --- /dev/null +++ b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/DBException.java @@ -0,0 +1,38 @@ +/** + * Copyright (C) 2011 the original author or authors. + * See the notice.md file distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.iq80.leveldb; + +/** + * @author Hiram Chirino + */ +public class DBException extends RuntimeException { + public DBException() { + } + + public DBException(String s) { + super(s); + } + + public DBException(String s, Throwable throwable) { + super(s, throwable); + } + + public DBException(Throwable throwable) { + super(throwable); + } +} diff --git a/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/DBFactory.java b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/DBFactory.java new file mode 100644 index 00000000..d5699945 --- /dev/null +++ b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/DBFactory.java @@ -0,0 +1,34 @@ +/** + * Copyright (C) 2011 the original author or authors. + * See the notice.md file distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.iq80.leveldb; + +import java.io.File; +import java.io.IOException; + +/** + * @author Hiram Chirino + */ +public interface DBFactory { + + public DB open(File path, Options options) throws IOException; + + public void destroy(File path, Options options) throws IOException; + + public void repair(File path, Options options) throws IOException; + +} diff --git a/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/DBIterator.java b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/DBIterator.java new file mode 100644 index 00000000..2d40b62e --- /dev/null +++ b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/DBIterator.java @@ -0,0 +1,65 @@ +/** + * Copyright (C) 2011 the original author or authors. + * See the notice.md file distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.iq80.leveldb; + +import java.io.Closeable; +import java.util.Iterator; +import java.util.Map; + +/** + * @author Hiram Chirino + */ +public interface DBIterator extends Iterator>, Closeable { + + /** + * Repositions the iterator so the key of the next BlockElement + * returned greater than or equal to the specified targetKey. + */ + public void seek(byte[] key); + + /** + * Repositions the iterator so is is at the beginning of the Database. + */ + public void seekToFirst(); + + /** + * Returns the next element in the iteration, without advancing the iteration. + */ + public Map.Entry peekNext(); + + /** + * @return true if there is a previous entry in the iteration. + */ + boolean hasPrev(); + + /** + * @return the previous element in the iteration and rewinds the iteration. + */ + Map.Entry prev(); + + /** + * @return the previous element in the iteration, without rewinding the iteration. + */ + public Map.Entry peekPrev(); + + /** + * Repositions the iterator so it is at the end of of the Database. + */ + public void seekToLast(); + +} diff --git a/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/Logger.java b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/Logger.java new file mode 100644 index 00000000..0e54c3a5 --- /dev/null +++ b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/Logger.java @@ -0,0 +1,27 @@ +/** + * Copyright (C) 2011 the original author or authors. + * See the notice.md file distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.iq80.leveldb; + +/** + * @author Hiram Chirino + */ +public interface Logger { + + public void log(String message); + +} diff --git a/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/Options.java b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/Options.java new file mode 100644 index 00000000..b79d9d98 --- /dev/null +++ b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/Options.java @@ -0,0 +1,168 @@ +/** + * Copyright (C) 2011 the original author or authors. + * See the notice.md file distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.iq80.leveldb; + +public class Options { + + private boolean createIfMissing = true; + private boolean errorIfExists; + private int writeBufferSize = 4 << 20; + + private int maxOpenFiles = 1000; + + private int blockRestartInterval = 16; + private int blockSize = 4 * 1024; + private CompressionType compressionType = CompressionType.SNAPPY; + private boolean verifyChecksums = true; + private boolean paranoidChecks = false; + private DBComparator comparator; + private Logger logger = null; + private long cacheSize; + + static void checkArgNotNull(Object value, String name) { + if(value==null) { + throw new IllegalArgumentException("The "+name+" argument cannot be null"); + } + } + + public boolean createIfMissing() + { + return createIfMissing; + } + + public Options createIfMissing(boolean createIfMissing) + { + this.createIfMissing = createIfMissing; + return this; + } + + public boolean errorIfExists() + { + return errorIfExists; + } + + public Options errorIfExists(boolean errorIfExists) + { + this.errorIfExists = errorIfExists; + return this; + } + + public int writeBufferSize() + { + return writeBufferSize; + } + + public Options writeBufferSize(int writeBufferSize) + { + this.writeBufferSize = writeBufferSize; + return this; + } + + public int maxOpenFiles() + { + return maxOpenFiles; + } + + public Options maxOpenFiles(int maxOpenFiles) + { + this.maxOpenFiles = maxOpenFiles; + return this; + } + + public int blockRestartInterval() + { + return blockRestartInterval; + } + + public Options blockRestartInterval(int blockRestartInterval) + { + this.blockRestartInterval = blockRestartInterval; + return this; + } + + public int blockSize() + { + return blockSize; + } + + public Options blockSize(int blockSize) + { + this.blockSize = blockSize; + return this; + } + + public CompressionType compressionType() + { + return compressionType; + } + + public Options compressionType(CompressionType compressionType) + { + checkArgNotNull(compressionType, "compressionType"); + this.compressionType = compressionType; + return this; + } + + public boolean verifyChecksums() + { + return verifyChecksums; + } + + public Options verifyChecksums(boolean verifyChecksums) + { + this.verifyChecksums = verifyChecksums; + return this; + } + + + public long cacheSize() { + return cacheSize; + } + + public Options cacheSize(long cacheSize) { + this.cacheSize = cacheSize; + return this; + } + + public DBComparator comparator() { + return comparator; + } + + public Options comparator(DBComparator comparator) { + this.comparator = comparator; + return this; + } + + public Logger logger() { + return logger; + } + + public Options logger(Logger logger) { + this.logger = logger; + return this; + } + + public boolean paranoidChecks() { + return paranoidChecks; + } + + public Options paranoidChecks(boolean paranoidChecks) { + this.paranoidChecks = paranoidChecks; + return this; + } +} diff --git a/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/Range.java b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/Range.java new file mode 100644 index 00000000..1d0e5ebd --- /dev/null +++ b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/Range.java @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2011 the original author or authors. + * See the notice.md file distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.iq80.leveldb; + +/** + * @author Hiram Chirino + */ +public class Range { + + final private byte[] start; + final private byte[] limit; + + public byte[] limit() { + return limit; + } + + public byte[] start() { + return start; + } + + public Range(byte[] start, byte[] limit) { + Options.checkArgNotNull(start, "start"); + Options.checkArgNotNull(limit, "limit"); + this.limit = limit; + this.start = start; + } + +} diff --git a/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/ReadOptions.java b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/ReadOptions.java new file mode 100644 index 00000000..d0ea5967 --- /dev/null +++ b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/ReadOptions.java @@ -0,0 +1,54 @@ +/** + * Copyright (C) 2011 the original author or authors. + * See the notice.md file distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.iq80.leveldb; + +public class ReadOptions +{ + private boolean verifyChecksums = false; + private boolean fillCache = true; + private Snapshot snapshot; + + public Snapshot snapshot() + { + return snapshot; + } + + public ReadOptions snapshot(Snapshot snapshot) + { + this.snapshot = snapshot; + return this; + } + + public boolean fillCache() { + return fillCache; + } + + public ReadOptions fillCache(boolean fillCache) { + this.fillCache = fillCache; + return this; + } + + public boolean verifyChecksums() { + return verifyChecksums; + } + + public ReadOptions verifyChecksums(boolean verifyChecksums) { + this.verifyChecksums = verifyChecksums; + return this; + } +} diff --git a/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/Snapshot.java b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/Snapshot.java new file mode 100644 index 00000000..e1192856 --- /dev/null +++ b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/Snapshot.java @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2011 the original author or authors. + * See the notice.md file distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.iq80.leveldb; + +import java.io.Closeable; + +public interface Snapshot extends Closeable { + +} diff --git a/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/WriteBatch.java b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/WriteBatch.java new file mode 100644 index 00000000..960a5f95 --- /dev/null +++ b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/WriteBatch.java @@ -0,0 +1,29 @@ +/** + * Copyright (C) 2011 the original author or authors. + * See the notice.md file distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.iq80.leveldb; + +import java.io.Closeable; + +/** + * @author Hiram Chirino + */ +public interface WriteBatch extends Closeable { + + public WriteBatch put(byte[] key, byte[] value); + public WriteBatch delete(byte[] key); +} diff --git a/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/WriteOptions.java b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/WriteOptions.java new file mode 100644 index 00000000..2d1876c6 --- /dev/null +++ b/java/leveldb/leveldb-api/src/main/java/org/iq80/leveldb/WriteOptions.java @@ -0,0 +1,46 @@ +/** + * Copyright (C) 2011 the original author or authors. + * See the notice.md file distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.iq80.leveldb; + +public class WriteOptions +{ + private boolean sync; + private boolean snapshot; + + + public boolean sync() + { + return sync; + } + + public WriteOptions sync(boolean sync) + { + this.sync = sync; + return this; + } + + public boolean snapshot() { + return snapshot; + } + + public WriteOptions snapshot(boolean snapshot) { + this.snapshot = snapshot; + return this; + } + +} diff --git a/java/leveldb/license-header.txt b/java/leveldb/license-header.txt new file mode 100644 index 00000000..0d35f5c6 --- /dev/null +++ b/java/leveldb/license-header.txt @@ -0,0 +1,15 @@ +Copyright (C) 2011 the original author or authors. +See the notice.md file distributed with this work for additional +information regarding copyright ownership. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/java/leveldb/license.txt b/java/leveldb/license.txt new file mode 100755 index 00000000..6b0b1270 --- /dev/null +++ b/java/leveldb/license.txt @@ -0,0 +1,203 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/java/leveldb/notice.md b/java/leveldb/notice.md new file mode 100644 index 00000000..f21e1588 --- /dev/null +++ b/java/leveldb/notice.md @@ -0,0 +1,5 @@ +LevelDB Copyright Notices +========================= + +* Copyright 2011 Dain Sundstrom +* Copyright 2011 FuseSource Corp. http://fusesource.com diff --git a/java/leveldb/pom.xml b/java/leveldb/pom.xml new file mode 100644 index 00000000..22cfd877 --- /dev/null +++ b/java/leveldb/pom.xml @@ -0,0 +1,386 @@ + + + + 4.0.0 + + org.iq80.leveldb + leveldb-project + 0.4-SNAPSHOT + pom + + ${project.artifactId} + + Port of LevelDB to Java + http://github.com/dain/leveldb + + + leveldb-api + leveldb + + + 2011 + + + + Apache License 2.0 + http://www.apache.org/licenses/LICENSE-2.0.html + repo + + + + + + dain + Dain Sundstrom + dain@iq80.com + + + chirino + Hiram Chirino + hiram@hiramchirino.com + http://hiramchirino.com + -5 + + + + + UTF-8 + https://oss.sonatype.org/content/repositories/snapshots/ + + + + scm:git:git://github.com/dain/leveldb.git + scm:git:git@github.com:dain/leveldb.git + http://github.com/dain/leveldb/tree/master + + + + 3.0 + + + + + sonatype-nexus-snapshots + Sonatype Nexus Snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + + + + sonatype-nexus-snapshots + Sonatype Nexus Snapshots + ${sonatypeOssDistMgmtSnapshotsUrl} + + + sonatype-nexus-staging + Nexus Release Repository + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 1.0 + + + enforce-versions + + enforce + + + + + 3.0.0 + + + 1.6 + + + + + + + + org.apache.maven.plugins + maven-source-plugin + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.8.1 + + + + org.apache.maven.plugins + maven-source-plugin + 2.1.2 + + true + + + + create-source-jar + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + + org.codehaus.mojo + findbugs-maven-plugin + 2.3.2 + + true + true + true + + + + + org.codehaus.mojo + cobertura-maven-plugin + 2.4 + + + xml + + + + + + org.apache.maven.plugins + maven-install-plugin + 2.3.1 + + + + org.apache.maven.plugins + maven-resources-plugin + 2.4.3 + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.5 + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.7 + + + com.google.doclava + doclava + 1.0.3 + + com.google.doclava.Doclava + + ${sun.boot.class.path} + + -quiet + + + -hdf project.name "${project.name}" + -d ${project.build.directory}/apidocs + + false + + -J-Xmx1024m + + + + attach-javadocs + + jar + + + + + + + org.apache.maven.plugins + maven-release-plugin + 2.2.1 + + forked-path + false + -Psonatype-oss-release + false + true + @{project.version} + + + + + + com.mycila.maven-license-plugin + maven-license-plugin + 1.9.0 + +
license-header.txt
+ + **/README.txt + **/config.properties + **/log.properties + +
+
+ + + org.apache.maven.plugins + maven-site-plugin + 3.0 + + + attach-descriptor + + attach-descriptor + + + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.4 + + false + false + + + + index + dependencies + issue-tracking + license + mailing-list + modules + project-team + plugin-management + plugins + scm + + + + + org.apache.maven.plugins + maven-jxr-plugin + 2.3 + + + UTF-8 + UTF-8 + true + ${project.name} Source Xref (${project.version}) + ${project.name} Source Xref (${project.version}) + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.7 + + + com.google.doclava + doclava + 1.0.3 + + com.google.doclava.Doclava + + ${sun.boot.class.path} + + -quiet + + + -hdf project.name "${project.name}" + -d ${project.build.directory}/site/apidocs + + false + + -J-Xmx1024m + + + + + +
+
+
+ + + + sonatype-oss-release + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.1 + + + sign-artifacts + verify + + sign + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + + + +
diff --git a/java/leveldb/src/site/site.xml b/java/leveldb/src/site/site.xml new file mode 100644 index 00000000..e32fcc50 --- /dev/null +++ b/java/leveldb/src/site/site.xml @@ -0,0 +1,41 @@ + + + + + + com.googlecode.fluido-skin + fluido-skin + 1.3 + + + + + + + + + + + diff --git a/java/leveldbjni/.gitignore b/java/leveldbjni/.gitignore new file mode 100644 index 00000000..0f7766ed --- /dev/null +++ b/java/leveldbjni/.gitignore @@ -0,0 +1,13 @@ +*~ +*.swp +.idea +.idea/* +*.iml +*.ipr +*.iws +target +.DS_Store +.project +.classpath +.settings +eclipse-classes diff --git a/java/leveldbjni/changelog.md b/java/leveldbjni/changelog.md new file mode 100644 index 00000000..0547e933 --- /dev/null +++ b/java/leveldbjni/changelog.md @@ -0,0 +1,49 @@ +# [LevelDBJNI](https://github.com/fusesource/leveldbjni) + +## [leveldbjni 1.4][1_4], released 2012-10-31 +[1_4]: http://repo.fusesource.com/nexus/content/groups/public/org/fusesource/leveldbjni/leveldbjni/1.4 + +* Switch to leveldb-api version 0.4 +* Checking the results of autotool chain into the source tree so that folks building don't have to have the autotools installed. +* Support suspending the background compaction thread. + +## [leveldbjni 1.3][1_3], released 2012-09-24 +[1_3]: http://repo.fusesource.com/nexus/content/groups/public/org/fusesource/leveldbjni/leveldbjni/1.3 + +* Make Util.link work on windows too. +* Expose the CreateHardLinkW windows API call. +* Added Windows LevelDB Support +* Update to hawtjni 1.6. +* Support the db.compactRange method to force compaction of the leveldb files. +* Fixed bug need to get leveldbjni workin on the Zing JVM + +## [leveldbjni 1.2][1_2], released 2012-02-27 +[1_2]: http://repo.fusesource.com/nexus/content/groups/public/org/fusesource/leveldbjni/leveldbjni/1.2 + +* Document how to use the memory pools. +* Fixes issue #6 Support using a memory pool to reduce native memory allocation overhead. +* Update leveldb, hawtjni, and leveldb-api versions. +* Store the version in the factory class. +* Added a release guide. + +## [leveldbjni 1.1][1_1], released 2011-09-29 +[1_1]: http://repo.fusesource.com/nexus/content/groups/public/org/fusesource/leveldbjni/leveldbjni/1.1 + +* the all module needs at least one java file so that it produces a javadoc and src.zip +* Try to load the native lib when the JniDBFactory class is loaded. +* Fixes issue #1 : Bug on NativeBuffer offset +* Switch the license from CDDL to the New BSD license to match the license used in the leveldb project. +* Add the sonatype snapshot repo since that's where the leveldb-api is at currently. +* Pickup updates in the api module. +* Updating build instructions. +* implement repair and destroy. +* api updated +* Cleaner java package structure. We only need to expose one public class now since we are using the org.iq80.leveldb abstract api. +* Refactored so that the main user API is the abstract API defined in 'org.iq80.leveldb.api' package. + +## [leveldbjni 1.0][1_0], released 2011-08-08 +[1_0]: http://repo.fusesource.com/nexus/content/groups/public/org/fusesource/leveldbjni/leveldbjni/1.0 + +* Initial Release +* OS X Intel 32 and 64 bit support +* Linux Intel 32 and 64 bit support diff --git a/java/leveldbjni/db.h.patch b/java/leveldbjni/db.h.patch new file mode 100644 index 00000000..d1006a0a --- /dev/null +++ b/java/leveldbjni/db.h.patch @@ -0,0 +1,30 @@ +From 3f0a7d241d96e8dc40ebf8001e4c41aa4ff86472 Mon Sep 17 00:00:00 2001 +From: Abhishek Kona +Date: Tue, 11 Dec 2012 22:38:14 -0800 +Subject: [PATCH] patch to make it compilable with java + +--- + include/leveldb/db.h | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/include/leveldb/db.h b/include/leveldb/db.h +index 2cfa537..e84685b 100644 +--- a/include/leveldb/db.h ++++ b/include/leveldb/db.h +@@ -182,9 +182,12 @@ class DB { + virtual Status GetLiveFiles(std::vector&, + uint64_t* manifest_file_size) = 0; + +- // The sequence number of the most recent transaction. ++ // The sequence number of the most recent transaction. + virtual SequenceNumber GetLatestSequenceNumber() = 0; + ++ virtual void SuspendCompactions() {}; ++ virtual void ResumeCompactions() {}; ++ + // Return's an iterator for all writes since the sequence number + // Status::ok if iterator is valid. + // The iterator internally holds references to the available log files. +-- +1.7.11.1 + diff --git a/java/leveldbjni/leveldbjni-all/pom.xml b/java/leveldbjni/leveldbjni-all/pom.xml new file mode 100755 index 00000000..095b466c --- /dev/null +++ b/java/leveldbjni/leveldbjni-all/pom.xml @@ -0,0 +1,95 @@ + + + + + 4.0.0 + + org.fusesource.leveldbjni.fb + leveldbjni-project + 1.5.7 + + + org.fusesource.leveldbjni.fb + leveldbjni-all + 1.5.7 + + ${project.artifactId} + An uber jar which contains all the leveldbjni platform libraries and dependencies + + + + org.fusesource.leveldbjni.fb + leveldbjni-osx + 1.5.7 + + + org.fusesource.leveldbjni.fb + leveldbjni-linux32 + 1.5.7 + + + org.fusesource.leveldbjni.fb + leveldbjni-linux64 + 1.5.7 + + + org.fusesource.leveldbjni.fb + leveldbjni-win32 + 1.5.7 + + + org.fusesource.leveldbjni.fb + leveldbjni-win64 + 1.5.7 + + + + + + + + + org.fusesource.mvnplugins + maven-uberize-plugin + 1.15 + + + package + uberize + + + + + + + diff --git a/java/leveldbjni/leveldbjni-all/src/main/java/org/fusesource/leveldbjni/All.java b/java/leveldbjni/leveldbjni-all/src/main/java/org/fusesource/leveldbjni/All.java new file mode 100644 index 00000000..a2ca0c7c --- /dev/null +++ b/java/leveldbjni/leveldbjni-all/src/main/java/org/fusesource/leveldbjni/All.java @@ -0,0 +1,4 @@ +package org.fusesource.leveldbjni; + +public class All { +} \ No newline at end of file diff --git a/java/leveldbjni/leveldbjni-linux32/pom.xml b/java/leveldbjni/leveldbjni-linux32/pom.xml new file mode 100755 index 00000000..d4b02255 --- /dev/null +++ b/java/leveldbjni/leveldbjni-linux32/pom.xml @@ -0,0 +1,100 @@ + + + + + 4.0.0 + + org.fusesource.leveldbjni.fb + leveldbjni-project + 1.5.7 + + + org.fusesource.leveldbjni.fb + leveldbjni-linux32 + 1.5.7 + + ${project.artifactId} + The leveldbjni linux 32 native libraries + + + + org.fusesource.leveldbjni.fb + leveldbjni + 1.5.7 + + + + + ${basedir}/../leveldbjni/src/test/java + + + + org.apache.maven.plugins + maven-jar-plugin + 2.3.1 + + ${basedir}/target/generated-sources/hawtjni/lib + + + + org.fusesource.hawtjni + maven-hawtjni-plugin + ${hawtjni-version} + + + + build + + compile + + + + leveldbjni + false + + org.fusesource.leveldbjni.fb + leveldbjni + ${project.version} + native-src + zip + + + --with-leveldb=${env.LEVELDB_HOME} + --with-snappy=${env.SNAPPY_HOME} + + + + + + + diff --git a/java/leveldbjni/leveldbjni-linux64/pom.xml b/java/leveldbjni/leveldbjni-linux64/pom.xml new file mode 100755 index 00000000..11abf0e9 --- /dev/null +++ b/java/leveldbjni/leveldbjni-linux64/pom.xml @@ -0,0 +1,99 @@ + + + + + 4.0.0 + + org.fusesource.leveldbjni.fb + leveldbjni-project + 1.5.7 + + + org.fusesource.leveldbjni.fb + leveldbjni-linux64 + 1.5.7 + + ${project.artifactId} + The leveldbjni linux 64 native libraries + + + + org.fusesource.leveldbjni.fb + leveldbjni + 1.5.7 + + + + + ${basedir}/../leveldbjni/src/test/java + + + + org.apache.maven.plugins + maven-jar-plugin + 2.3.1 + + ${basedir}/target/generated-sources/hawtjni/lib + + + + org.fusesource.hawtjni + maven-hawtjni-plugin + ${hawtjni-version} + + + + build + + + + + leveldbjni + false + + org.fusesource.leveldbjni.fb + leveldbjni + ${project.version} + native-src + zip + + + --with-leveldb=${env.LEVELDB_HOME} + --with-snappy=${env.SNAPPY_HOME} + + + + + + + diff --git a/java/leveldbjni/leveldbjni-osx/pom.xml b/java/leveldbjni/leveldbjni-osx/pom.xml new file mode 100755 index 00000000..da26c80a --- /dev/null +++ b/java/leveldbjni/leveldbjni-osx/pom.xml @@ -0,0 +1,110 @@ + + + + + 4.0.0 + + org.fusesource.leveldbjni.fb + leveldbjni-project + 1.5.7 + + + org.fusesource.leveldbjni.fb + leveldbjni-osx + 1.5.7 + + ${project.artifactId} + The leveldbjni OS X universal native libraries + + + + org.fusesource.leveldbjni.fb + leveldbjni + 1.5.7 + + + + org.fusesource.leveldbjni.fb + leveldbjni + 1.5.7 + test-jar + test + + + + + ${basedir}/../leveldbjni/src/test/java + + + + org.apache.maven.plugins + maven-jar-plugin + 2.3.1 + + ${basedir}/target/generated-sources/hawtjni/lib + + + + + org.fusesource.hawtjni + maven-hawtjni-plugin + ${hawtjni-version} + + + + build + + + + + leveldbjni + false + + org.fusesource.leveldbjni.fb + leveldbjni + ${project.version} + native-src + zip + + osx + + --with-leveldb=${env.LEVELDB_HOME} + --with-snappy=${env.SNAPPY_HOME} + --with-universal + + + + + + + diff --git a/java/leveldbjni/leveldbjni-win32/pom.xml b/java/leveldbjni/leveldbjni-win32/pom.xml new file mode 100755 index 00000000..c65386ef --- /dev/null +++ b/java/leveldbjni/leveldbjni-win32/pom.xml @@ -0,0 +1,97 @@ + + + + + 4.0.0 + + org.fusesource.leveldbjni.fb + leveldbjni-project + 1.5.7 + + + org.fusesource.leveldbjni.fb + leveldbjni-win32 + 1.5.7 + + ${project.artifactId} + The leveldbjni Windows 32 bit native libraries + + + + org.fusesource.leveldbjni.fb + leveldbjni + 1.5.7 + + + + + ${basedir}/../leveldbjni/src/test/java + + + + org.apache.maven.plugins + maven-jar-plugin + 2.3.1 + + ${basedir}/target/generated-sources/hawtjni/lib + + + + org.fusesource.hawtjni + maven-hawtjni-plugin + ${hawtjni-version} + + + + build + + compile + + + + leveldbjni + false + + org.fusesource.leveldbjni.fb + leveldbjni + ${project.version} + native-src + zip + + ${basedir}/../leveldbjni/target/generated-sources/hawtjni/native-package + + + + + + diff --git a/java/leveldbjni/leveldbjni-win64/pom.xml b/java/leveldbjni/leveldbjni-win64/pom.xml new file mode 100755 index 00000000..565f43d4 --- /dev/null +++ b/java/leveldbjni/leveldbjni-win64/pom.xml @@ -0,0 +1,96 @@ + + + + + 4.0.0 + + org.fusesource.leveldbjni.fb + leveldbjni-project + 1.5.7 + + + org.fusesource.leveldbjni.fb + leveldbjni-win64 + 1.5.7 + + ${project.artifactId} + The leveldbjni Windows 64 bit native libraries + + + + org.fusesource.leveldbjni.fb + leveldbjni + 1.5.7 + + + + + ${basedir}/../leveldbjni/src/test/java + + + + org.apache.maven.plugins + maven-jar-plugin + 2.3.1 + + ${basedir}/target/generated-sources/hawtjni/lib + + + + org.fusesource.hawtjni + maven-hawtjni-plugin + ${hawtjni-version} + + + + build + + + + + leveldbjni + false + + org.fusesource.leveldbjni.fb + leveldbjni + ${project.version} + native-src + zip + + ${basedir}/../leveldbjni/target/generated-sources/hawtjni/native-package + + + + + + diff --git a/java/leveldbjni/leveldbjni/pom.xml b/java/leveldbjni/leveldbjni/pom.xml new file mode 100755 index 00000000..032f0270 --- /dev/null +++ b/java/leveldbjni/leveldbjni/pom.xml @@ -0,0 +1,180 @@ + + + + + 4.0.0 + + org.fusesource.leveldbjni.fb + leveldbjni-project + 1.5.7 + + + org.fusesource.leveldbjni.fb + leveldbjni + 1.5.7 + jar + + ${project.artifactId} + leveldbjni is a jni library for acessing leveldb. + + + false + + + + + org.fusesource.hawtjni + hawtjni-runtime + ${hawtjni-version} + + + org.iq80.leveldb + leveldb-api + ${leveldb-api-version} + + + + + + + ${project.basedir}/src/main/resources + true + + **/* + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + + + + org.fusesource.hawtjni + maven-hawtjni-plugin + ${hawtjni-version} + + + + generate + package-source + + + + + ${skipAutogen} + leveldbjni + false + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.4.3 + + true + once + -ea + false + ${project.build.directory} + + **/* + + + **/*Test.java + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + + org.apache.felix + maven-bundle-plugin + 2.0.1 + + + bundle-manifest + process-classes + + manifest + + + + !org.fusesource.leveldbjni*,!org.fusesource.hawtjni*,sun.reflect;resolution:=optional,* + + + + + + + maven-jar-plugin + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + + + + diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/JniDBFactory.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/JniDBFactory.java new file mode 100644 index 00000000..02d82a4f --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/JniDBFactory.java @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni; + +import org.fusesource.leveldbjni.internal.*; +import org.iq80.leveldb.*; + +import java.io.*; +import java.net.URL; +import java.util.concurrent.Callable; + +/** + * @author Hiram Chirino + */ +public class JniDBFactory implements DBFactory { + + public static final JniDBFactory factory = new JniDBFactory(); + static { + NativeDB.LIBRARY.load(); + } + + public static final String VERSION; + static { + String v="unknown"; + InputStream is = JniDBFactory.class.getResourceAsStream("version.txt"); + try { + v = new BufferedReader(new InputStreamReader(is, "UTF-8")).readLine(); + } catch (Throwable e) { + } finally { + try { + is.close(); + } catch (Throwable e) { + } + } + VERSION = v; + } + + public static byte[] bytes(String value) { + if( value == null) { + return null; + } + try { + return value.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + public static String asString(byte value[]) { + if( value == null) { + return null; + } + try { + return new String(value, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + static private class OptionsResourceHolder { + + NativeCache cache = null; + NativeComparator comparator=null; + NativeLogger logger=null; + NativeOptions options; + + public void init(Options value) { + + options = new NativeOptions(); + options.blockRestartInterval(value.blockRestartInterval()); + options.blockSize(value.blockSize()); + options.createIfMissing(value.createIfMissing()); + options.errorIfExists(value.errorIfExists()); + options.maxOpenFiles(value.maxOpenFiles()); + options.paranoidChecks(value.paranoidChecks()); + options.writeBufferSize(value.writeBufferSize()); + + switch(value.compressionType()) { + case NONE: + options.compression(NativeCompressionType.kNoCompression); + break; + case SNAPPY: + options.compression(NativeCompressionType.kSnappyCompression); + break; + } + + + if(value.cacheSize()>0 ) { + cache = new NativeCache(value.cacheSize()); + options.cache(cache); + } + + final DBComparator userComparator = value.comparator(); + if(userComparator!=null) { + comparator = new NativeComparator() { + @Override + public int compare(byte[] key1, byte[] key2) { + return userComparator.compare(key1, key2); + } + + @Override + public String name() { + return userComparator.name(); + } + }; + options.comparator(comparator); + } + + final Logger userLogger = value.logger(); + if(userLogger!=null) { + logger = new NativeLogger() { + @Override + public void log(String message) { + userLogger.log(message); + } + }; + options.infoLog(logger); + } + + } + public void close() { + if(cache!=null) { + cache.delete(); + } + if(comparator!=null){ + comparator.delete(); + } + if(logger!=null) { + logger.delete(); + } + } + } + + public DB open(File path, Options options) throws IOException { + NativeDB db=null; + OptionsResourceHolder holder = new OptionsResourceHolder(); + try { + holder.init(options); + db = NativeDB.open(holder.options, path); + } finally { + // if we could not open up the DB, then clean up the + // other allocated native resouces.. + if(db==null) { + holder.close(); + } + } + return new JniDB(db, holder.cache, holder.comparator, holder.logger); + } + + public void destroy(File path, Options options) throws IOException { + OptionsResourceHolder holder = new OptionsResourceHolder(); + try { + holder.init(options); + NativeDB.destroy(path, holder.options); + } finally { + holder.close(); + } + } + + public void repair(File path, Options options) throws IOException { + OptionsResourceHolder holder = new OptionsResourceHolder(); + try { + holder.init(options); + NativeDB.repair(path, holder.options); + } finally { + holder.close(); + } + } + + @Override + public String toString() { + return String.format("leveldbjni version %s", VERSION); + } + + + public static void pushMemoryPool(int size) { + NativeBuffer.pushMemoryPool(size); + } + + public static void popMemoryPool() { + NativeBuffer.popMemoryPool(); + } +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/JniDB.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/JniDB.java new file mode 100644 index 00000000..e89a9983 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/JniDB.java @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.iq80.leveldb.*; + +/** + * @author Hiram Chirino + */ +public class JniDB implements DB { + + private final NativeDB db; + private final NativeCache cache; + private final NativeComparator comparator; + private final NativeLogger logger; + + public JniDB(NativeDB db, NativeCache cache, NativeComparator comparator, NativeLogger logger) { + this.db = db; + this.cache = cache; + this.comparator = comparator; + this.logger = logger; + } + + public void close() { + db.delete(); + if(cache!=null) { + cache.delete(); + } + if(comparator!=null){ + comparator.delete(); + } + if(logger!=null) { + logger.delete(); + } + } + + + public byte[] get(byte[] key) throws DBException { + return get(key, new ReadOptions()); + } + + public byte[] get(byte[] key, ReadOptions options) throws DBException { + try { + return db.get(convert(options), key); + } catch (NativeDB.DBException e) { + if(e.isNotFound()) { + return null; + } + throw new DBException(e.getMessage(), e); + } + } + + public DBIterator iterator() { + return iterator(new ReadOptions()); + } + + public DBIterator iterator(ReadOptions options) { + return new JniDBIterator(db.iterator(convert(options))); + } + + public void put(byte[] key, byte[] value) throws DBException { + put(key, value, new WriteOptions()); + } + + public void delete(byte[] key) throws DBException { + delete(key, new WriteOptions()); + } + + public void write(WriteBatch updates) throws DBException { + write(updates, new WriteOptions()); + } + + public WriteBatch createWriteBatch() { + return new JniWriteBatch(new NativeWriteBatch()); + } + + public Snapshot put(byte[] key, byte[] value, WriteOptions options) throws DBException { + try { + db.put(convert(options), key, value); + return null; + } catch (NativeDB.DBException e) { + throw new DBException(e.getMessage(), e); + } + } + + public Snapshot delete(byte[] key, WriteOptions options) throws DBException { + try { + db.delete(convert(options), key); + return null; + } catch (NativeDB.DBException e) { + throw new DBException(e.getMessage(), e); + } + } + + public Snapshot write(WriteBatch updates, WriteOptions options) throws DBException { + try { + db.write(convert(options), ((JniWriteBatch) updates).writeBatch()); + return null; + } catch (NativeDB.DBException e) { + throw new DBException(e.getMessage(), e); + } + } + + public Snapshot getSnapshot() { + return new JniSnapshot(db, db.getSnapshot()); + } + + public long[] getApproximateSizes(Range... ranges) { + NativeRange args[] = new NativeRange[ranges.length]; + for (int i = 0; i < args.length; i++) { + args[i] = new NativeRange(ranges[i].start(), ranges[i].limit()); + } + return db.getApproximateSizes(args); + } + + public String getProperty(String name) { + return db.getProperty(name); + } + + private NativeReadOptions convert(ReadOptions options) { + if(options==null) { + return null; + } + NativeReadOptions rc = new NativeReadOptions(); + rc.fillCache(options.fillCache()); + rc.verifyChecksums(options.verifyChecksums()); + if(options.snapshot()!=null) { + rc.snapshot(((JniSnapshot) options.snapshot()).snapshot()); + } + return rc; + } + + private NativeWriteOptions convert(WriteOptions options) { + if(options==null) { + return null; + } + NativeWriteOptions rc = new NativeWriteOptions(); + rc.sync(options.sync()); + if(options.snapshot()) { + throw new UnsupportedOperationException("WriteOptions snapshot not supported"); + } + return rc; + } + + public void compactRange(byte[] begin, byte[] end) throws DBException { + db.compactRange(begin, end); + } + +// +// Using a fork of leveldb with db Suspend / Resume methods to avoid +// having to callback into java. +// + public void suspendCompactions() throws InterruptedException { + db.suspendCompactions(); + } + public void resumeCompactions() { + db.resumeCompactions(); + } + +// private static class Suspension { +// static long env = Util.EnvJNI.Default(); +// +// CountDownLatch suspended = new CountDownLatch(1); +// CountDownLatch resumed = new CountDownLatch(1); +// Callback callback = new Callback(this, "suspended", 1); +// +// public Suspension() { +// Util.EnvJNI.Schedule(env, callback.getAddress(), 0); +// } +// +// private long suspended(long arg) { +// suspended.countDown(); +// try { +// resumed.await(); +// } catch (InterruptedException e) { +// } finally { +// callback.dispose(); +// } +// return 0; +// } +// } +// +// int suspendCounter = 0; +// Suspension suspension = null; +// +// public void suspendCompactions() throws InterruptedException { +// Suspension s = null; +// synchronized (this) { +// suspendCounter++; +// if( suspendCounter==1 ) { +// suspension = new Suspension(); +// } +// s = suspension; +// } +// // Don't return until the compactions have suspended. +// s.suspended.await(); +// } +// +// synchronized public void resumeCompactions() { +// suspendCounter--; +// if( suspendCounter==0 ) { +// suspension.resumed.countDown(); +// suspension = null; +// } +// } +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/JniDBIterator.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/JniDBIterator.java new file mode 100644 index 00000000..0bfd46f6 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/JniDBIterator.java @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.fusesource.leveldbjni.internal.NativeDB; +import org.fusesource.leveldbjni.internal.NativeIterator; +import org.iq80.leveldb.DBIterator; + +import java.util.AbstractMap; +import java.util.Map; +import java.util.NoSuchElementException; + +/** + * @author Hiram Chirino + */ +public class JniDBIterator implements DBIterator { + + private final NativeIterator iterator; + + JniDBIterator(NativeIterator iterator) { + this.iterator = iterator; + } + + public void close() { + iterator.delete(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + public void seek(byte[] key) { + try { + iterator.seek(key); + } catch (NativeDB.DBException e) { + if( e.isNotFound() ) { + throw new NoSuchElementException(); + } else { + throw new RuntimeException(e); + } + } + } + + public void seekToFirst() { + iterator.seekToFirst(); + } + + public void seekToLast() { + iterator.seekToLast(); + } + + + public Map.Entry peekNext() { + if(!iterator.isValid()) { + throw new NoSuchElementException(); + } + try { + return new AbstractMap.SimpleImmutableEntry(iterator.key(), iterator.value()); + } catch (NativeDB.DBException e) { + throw new RuntimeException(e); + } + } + + public boolean hasNext() { + return iterator.isValid(); + } + + public Map.Entry next() { + Map.Entry rc = peekNext(); + try { + iterator.next(); + } catch (NativeDB.DBException e) { + throw new RuntimeException(e); + } + return rc; + } + + public boolean hasPrev() { + if( !iterator.isValid() ) + return false; + try { + iterator.prev(); + try { + return iterator.isValid(); + } finally { + iterator.next(); + } + } catch (NativeDB.DBException e) { + throw new RuntimeException(e); + } + } + + public Map.Entry peekPrev() { + try { + iterator.prev(); + try { + return peekNext(); + } finally { + iterator.next(); + } + } catch (NativeDB.DBException e) { + throw new RuntimeException(e); + } + } + + public Map.Entry prev() { + Map.Entry rc = peekPrev(); + try { + iterator.prev(); + } catch (NativeDB.DBException e) { + throw new RuntimeException(e); + } + return rc; + } + + +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/JniSnapshot.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/JniSnapshot.java new file mode 100644 index 00000000..827613f3 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/JniSnapshot.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.fusesource.leveldbjni.internal.*; +import org.iq80.leveldb.Snapshot; + +/** + * @author Hiram Chirino + */ +public class JniSnapshot implements Snapshot { + + private final NativeDB db; + private final NativeSnapshot snapshot; + + JniSnapshot(NativeDB db, NativeSnapshot snapshot) { + this.db = db; + this.snapshot = snapshot; + } + + public void close() { + db.releaseSnapshot(snapshot); + } + + NativeSnapshot snapshot() { + return snapshot; + } +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/JniWriteBatch.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/JniWriteBatch.java new file mode 100644 index 00000000..27d86d6f --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/JniWriteBatch.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.fusesource.leveldbjni.internal.NativeWriteBatch; +import org.iq80.leveldb.WriteBatch; + +/** + * @author Hiram Chirino + */ +public class JniWriteBatch implements WriteBatch { + + private final NativeWriteBatch writeBatch; + + JniWriteBatch(NativeWriteBatch writeBatch) { + this.writeBatch = writeBatch; + } + + public void close() { + writeBatch.delete(); + } + + public WriteBatch put(byte[] key, byte[] value) { + writeBatch.put(key, value); + return this; + } + + public WriteBatch delete(byte[] key) { + writeBatch.delete(key); + return this; + } + + public NativeWriteBatch writeBatch() { + return writeBatch; + } +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeBuffer.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeBuffer.java new file mode 100644 index 00000000..6eeb06f2 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeBuffer.java @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.fusesource.hawtjni.runtime.JniArg; +import org.fusesource.hawtjni.runtime.JniClass; +import org.fusesource.hawtjni.runtime.JniMethod; +import org.fusesource.hawtjni.runtime.PointerMath; + +import java.util.concurrent.Callable; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.fusesource.hawtjni.runtime.ArgFlag.*; + +/** + * A NativeBuffer allocates a native buffer on the heap. It supports + * creating sub slices/views of that buffer and manages reference tracking + * so that the the native buffer is freed once all NativeBuffer views + * are deleted. + * + * @author Hiram Chirino + */ +public class NativeBuffer extends NativeObject { + + @JniClass + static class NativeBufferJNI { + static { + NativeDB.LIBRARY.load(); + } + + @JniMethod(cast="void *") + public static final native long malloc( + @JniArg(cast="size_t") long size); + + public static final native void free( + @JniArg(cast="void *") long self); + +// public static final native void buffer_copy ( +// @JniArg(cast="const void *") long src, +// @JniArg(cast="size_t") long srcPos, +// @JniArg(cast="void *") long dest, +// @JniArg(cast="size_t") long destPos, +// @JniArg(cast="size_t") long length); + + public static final native void buffer_copy ( + @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}) byte[] src, + @JniArg(cast="size_t") long srcPos, + @JniArg(cast="void *") long dest, + @JniArg(cast="size_t") long destPos, + @JniArg(cast="size_t") long length); + + public static final native void buffer_copy ( + @JniArg(cast="const void *") long src, + @JniArg(cast="size_t") long srcPos, + @JniArg(cast="void *", flags={NO_IN, CRITICAL}) byte[] dest, + @JniArg(cast="size_t") long destPos, + @JniArg(cast="size_t") long length); + +// @JniMethod(cast="void *") +// public static final native long memset ( +// @JniArg(cast="void *") long buffer, +// int c, +// @JniArg(cast="size_t") long num); + + } + + private static class Allocation extends NativeObject { + private final AtomicInteger retained = new AtomicInteger(0); + + private Allocation(long size) { + super(NativeBufferJNI.malloc(size)); + } + + void retain() { + assertAllocated(); + retained.incrementAndGet(); + } + + void release() { + assertAllocated(); + int r = retained.decrementAndGet(); + if( r < 0 ) { + throw new Error("The object has already been deleted."); + } else if( r==0 ) { + NativeBufferJNI.free(self); + } + self = 0; + } + } + + private static class Pool { + private final NativeBuffer.Pool prev; + Allocation allocation; + long pos; + long remaining; + int chunk; + + public Pool(int chunk, Pool prev) { + this.chunk = chunk; + this.prev = prev; + } + + NativeBuffer create(long size) { + if( size >= chunk ) { + Allocation allocation = new Allocation(size); + return new NativeBuffer(allocation, allocation.self, size); + } + + if( remaining < size ) { + delete(); + } + + if( allocation == null ) { + allocate(); + } + + NativeBuffer rc = new NativeBuffer(allocation, pos, size); + pos = PointerMath.add(pos, size); + remaining -= size; + return rc; + } + + private void allocate() { + allocation = new NativeBuffer.Allocation(chunk); + allocation.retain(); + remaining = chunk; + pos = allocation.self; + } + + public void delete() { + if( allocation!=null ) { + allocation.release(); + allocation = null; + } + } + } + + private final Allocation allocation; + private final long capacity; + + static final private ThreadLocal CURRENT_POOL = new ThreadLocal(); + + static public NativeBuffer create(long capacity) { + Pool pool = CURRENT_POOL.get(); + if( pool == null ) { + Allocation allocation = new Allocation(capacity); + return new NativeBuffer(allocation, allocation.self, capacity); + } else { + return pool.create(capacity); + } + } + + + public static void pushMemoryPool(int size) { + Pool original = CURRENT_POOL.get(); + Pool next = new Pool(size, original); + CURRENT_POOL.set(next); + } + + public static void popMemoryPool() { + Pool next = CURRENT_POOL.get(); + next.delete(); + if( next.prev == null ) { + CURRENT_POOL.remove(); + } else { + CURRENT_POOL.set(next.prev); + } + } + + static public NativeBuffer create(byte[] data) { + if( data == null ) { + return null; + } else { + return create(data, 0 , data.length); + } + } + + static public NativeBuffer create(String data) { + return create(cbytes(data)); + } + + static public NativeBuffer create(byte[] data, int offset, int length) { + NativeBuffer rc = create(length); + rc.write(0, data, offset, length); + return rc; + } + + private NativeBuffer(Allocation allocation, long self, long capacity) { + super(self); + this.capacity = capacity; + this.allocation = allocation; + this.allocation.retain(); + } + + public NativeBuffer slice(long offset, long length) { + assertAllocated(); + if( length < 0 ) throw new IllegalArgumentException("length cannot be negative"); + if( offset < 0 ) throw new IllegalArgumentException("offset cannot be negative"); + if( offset+length >= capacity) throw new ArrayIndexOutOfBoundsException("offset + length exceed the length of this buffer"); + return new NativeBuffer(allocation, PointerMath.add(self, offset), length); + } + + static byte[] cbytes(String strvalue) { + byte[] value = strvalue.getBytes(); + // expand by 1 so we get a null at the end. + byte[] rc = new byte[value.length+1]; + System.arraycopy(value, 0, rc, 0, value.length); + return rc; + } + + public NativeBuffer head(long length) { + return slice(0, length); + } + + public NativeBuffer tail(long length) { + if( capacity-length < 0) throw new ArrayIndexOutOfBoundsException("capacity-length cannot be less than zero"); + return slice(capacity-length, length); + } + + public void delete() { + allocation.release(); + } + + public long capacity() { + return capacity; + } + + public void write(long at, byte []source, int offset, int length) { + assertAllocated(); + if( length < 0 ) throw new IllegalArgumentException("length cannot be negative"); + if( offset < 0 ) throw new IllegalArgumentException("offset cannot be negative"); + if( at < 0 ) throw new IllegalArgumentException("at cannot be negative"); + if( at+length > capacity ) throw new ArrayIndexOutOfBoundsException("at + length exceeds the capacity of this object"); + if( offset+length > source.length) throw new ArrayIndexOutOfBoundsException("offset + length exceed the length of the source buffer"); + NativeBufferJNI.buffer_copy(source, offset, self, at, length); + } + + public void read(long at, byte []target, int offset, int length) { + assertAllocated(); + if( length < 0 ) throw new IllegalArgumentException("length cannot be negative"); + if( offset < 0 ) throw new IllegalArgumentException("offset cannot be negative"); + if( at < 0 ) throw new IllegalArgumentException("at cannot be negative"); + if( at+length > capacity ) throw new ArrayIndexOutOfBoundsException("at + length exceeds the capacity of this object"); + if( offset+length > target.length) throw new ArrayIndexOutOfBoundsException("offset + length exceed the length of the target buffer"); + NativeBufferJNI.buffer_copy(self, at, target, offset, length); + } + + public byte[] toByteArray() { + if( capacity > Integer.MAX_VALUE ) { + throw new OutOfMemoryError("Native buffer larger than the largest allowed Java byte[]"); + } + byte [] rc = new byte[(int) capacity]; + read(0, rc, 0, rc.length); + return rc; + } +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeCache.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeCache.java new file mode 100644 index 00000000..05624976 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeCache.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.fusesource.hawtjni.runtime.JniArg; +import org.fusesource.hawtjni.runtime.JniClass; +import org.fusesource.hawtjni.runtime.JniMethod; + +import static org.fusesource.hawtjni.runtime.ClassFlag.CPP; +import static org.fusesource.hawtjni.runtime.MethodFlag.CPP_DELETE; + +/** + * Provides a java interface to the C++ leveldb::Cache class. + * + * @author Hiram Chirino + */ +public class NativeCache extends NativeObject { + + @JniClass(name="leveldb::Cache", flags={CPP}) + private static class CacheJNI { + static { + NativeDB.LIBRARY.load(); + } + + @JniMethod(cast="leveldb::Cache *", accessor="leveldb::NewLRUCache") + public static final native long NewLRUCache( + @JniArg(cast="size_t") long capacity); + + @JniMethod(flags={CPP_DELETE}) + public static final native void delete(long self); + } + + public NativeCache(long capacity) { + super(CacheJNI.NewLRUCache(capacity)); + } + + public void delete() { + assertAllocated(); + CacheJNI.delete(self); + self = 0; + } + +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeComparator.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeComparator.java new file mode 100644 index 00000000..f2f85853 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeComparator.java @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.fusesource.hawtjni.runtime.*; + +import static org.fusesource.hawtjni.runtime.FieldFlag.*; +import static org.fusesource.hawtjni.runtime.MethodFlag.*; +import static org.fusesource.hawtjni.runtime.ArgFlag.*; +import static org.fusesource.hawtjni.runtime.ClassFlag.*; + +/** + *

+ * Provides a java interface to the C++ leveldb::Comparator class. + *

+ * + * @author Hiram Chirino + */ +public abstract class NativeComparator extends NativeObject { + + @JniClass(name="JNIComparator", flags={STRUCT, CPP}) + static public class ComparatorJNI { + + static { + NativeDB.LIBRARY.load(); + init(); + } + + @JniMethod(flags={CPP_NEW}) + public static final native long create(); + @JniMethod(flags={CPP_DELETE}) + public static final native void delete(long ptr); + + public static final native void memmove ( + @JniArg(cast="void *") long dest, + @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}) ComparatorJNI src, + @JniArg(cast="size_t") long size); + + public static final native void memmove ( + @JniArg(cast="void *", flags={NO_IN, CRITICAL}) ComparatorJNI dest, + @JniArg(cast="const void *") long src, + @JniArg(cast="size_t") long size); + + @JniField(cast="jobject", flags={POINTER_FIELD}) + long target; + + @JniField(cast="jmethodID", flags={POINTER_FIELD}) + long compare_method; + + @JniField(cast="const char *") + long name; + + @JniMethod(flags={CONSTANT_INITIALIZER}) + private static final native void init(); + + @JniField(flags={CONSTANT}, accessor="sizeof(struct JNIComparator)") + static int SIZEOF; + + @JniField(flags={CONSTANT}, cast="const Comparator*", accessor="leveldb::BytewiseComparator()") + private static long BYTEWISE_COMPARATOR; + + } + + private NativeBuffer name_buffer; + private long globalRef; + + public NativeComparator() { + super(ComparatorJNI.create()); + try { + name_buffer = NativeBuffer.create(name()); + globalRef = NativeDB.DBJNI.NewGlobalRef(this); + if( globalRef==0 ) { + throw new RuntimeException("jni call failed: NewGlobalRef"); + } + ComparatorJNI struct = new ComparatorJNI(); + struct.compare_method = NativeDB.DBJNI.GetMethodID(this.getClass(), "compare", "(JJ)I"); + if( struct.compare_method==0 ) { + throw new RuntimeException("jni call failed: GetMethodID"); + } + struct.target = globalRef; + struct.name = name_buffer.pointer(); + ComparatorJNI.memmove(self, struct, ComparatorJNI.SIZEOF); + + } catch (RuntimeException e) { + delete(); + throw e; + } + } + + public static final NativeComparator BYTEWISE_COMPARATOR = new NativeComparator(ComparatorJNI.BYTEWISE_COMPARATOR) { + @Override + public void delete() { + // we won't really delete this one since it's static. + } + @Override + public int compare(byte[] key1, byte[] key2) { + throw new UnsupportedOperationException(); + } + @Override + public String name() { + throw new UnsupportedOperationException(); + } + }; + + NativeComparator(long ptr) { + super(ptr); + } + + public void delete() { + if( name_buffer!=null ) { + name_buffer.delete(); + name_buffer = null; + } + if( globalRef!=0 ) { + NativeDB.DBJNI.DeleteGlobalRef(globalRef); + globalRef = 0; + } + } + + private int compare(long ptr1, long ptr2) { + NativeSlice s1 = new NativeSlice(); + s1.read(ptr1, 0); + NativeSlice s2 = new NativeSlice(); + s2.read(ptr2, 0); + return compare(s1.toByteArray(), s2.toByteArray()); + } + + public abstract int compare(byte[] key1, byte[] key2); + public abstract String name(); + +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeCompressionType.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeCompressionType.java new file mode 100644 index 00000000..2c8b97b9 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeCompressionType.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +/** + * Provides a java interface to the C++ leveldb::CompressionType enum. + * + * @author Hiram Chirino + */ +public enum NativeCompressionType { + kNoCompression(0x0), kSnappyCompression(0x1); + + static final int t = kNoCompression.value; + final int value; + + NativeCompressionType(int value) { + this.value = value; + } +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeDB.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeDB.java new file mode 100644 index 00000000..37ed4fdb --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeDB.java @@ -0,0 +1,427 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.fusesource.hawtjni.runtime.JniArg; +import org.fusesource.hawtjni.runtime.JniClass; +import org.fusesource.hawtjni.runtime.JniMethod; +import org.fusesource.hawtjni.runtime.Library; + +import java.io.File; +import java.io.IOException; + +import static org.fusesource.hawtjni.runtime.ArgFlag.*; +import static org.fusesource.hawtjni.runtime.ClassFlag.CPP; +import static org.fusesource.hawtjni.runtime.MethodFlag.*; + +/** + * The DB object provides the main interface to acessing LevelDB + * + * @author Hiram Chirino + */ +public class NativeDB extends NativeObject { + + public static final Library LIBRARY = new Library("leveldbjni", NativeDB.class); + + @JniClass(name="leveldb::DB", flags={CPP}) + static class DBJNI { + static { + NativeDB.LIBRARY.load(); + } + + @JniMethod(flags={JNI, POINTER_RETURN}, cast="jobject") + public static final native long NewGlobalRef( + Object target); + + @JniMethod(flags={JNI}, cast="jobject") + public static final native void DeleteGlobalRef( + @JniArg(cast="jobject", flags={POINTER_ARG}) + long target); + + @JniMethod(flags={JNI, POINTER_RETURN}, cast="jmethodID") + public static final native long GetMethodID( + @JniArg(cast="jclass", flags={POINTER_ARG}) + Class clazz, + String name, + String signature); + + @JniMethod(flags={CPP_DELETE}) + static final native void delete( + long self + ); + + @JniMethod(copy="leveldb::Status", accessor = "leveldb::DB::Open") + static final native long Open( + @JniArg(flags={BY_VALUE, NO_OUT}) NativeOptions options, + @JniArg(cast="const char*") String path, + @JniArg(cast="leveldb::DB**") long[] self); + + @JniMethod(copy="leveldb::Status", flags={CPP_METHOD}) + static final native long Put( + long self, + @JniArg(flags={BY_VALUE, NO_OUT}) NativeWriteOptions options, + @JniArg(flags={BY_VALUE, NO_OUT}) NativeSlice key, + @JniArg(flags={BY_VALUE, NO_OUT}) NativeSlice value + ); + + @JniMethod(copy="leveldb::Status", flags={CPP_METHOD}) + static final native long Delete( + long self, + @JniArg(flags={BY_VALUE, NO_OUT}) NativeWriteOptions options, + @JniArg(flags={BY_VALUE, NO_OUT}) NativeSlice key + ); + + @JniMethod(copy="leveldb::Status", flags={CPP_METHOD}) + static final native long Write( + long self, + @JniArg(flags={BY_VALUE}) NativeWriteOptions options, + @JniArg(cast="leveldb::WriteBatch *") long updates + ); + + @JniMethod(copy="leveldb::Status", flags={CPP_METHOD}) + static final native long Get( + long self, + @JniArg(flags={NO_OUT, BY_VALUE}) NativeReadOptions options, + @JniArg(flags={BY_VALUE, NO_OUT}) NativeSlice key, + @JniArg(cast="std::string *") long value + ); + + @JniMethod(cast="leveldb::Iterator *", flags={CPP_METHOD}) + static final native long NewIterator( + long self, + @JniArg(flags={NO_OUT, BY_VALUE}) NativeReadOptions options + ); + + @JniMethod(cast="leveldb::Snapshot *", flags={CPP_METHOD}) + static final native long GetSnapshot( + long self); + + @JniMethod(flags={CPP_METHOD}) + static final native void ReleaseSnapshot( + long self, + @JniArg(cast="const leveldb::Snapshot *") long snapshot + ); + + @JniMethod(flags={CPP_METHOD}) + static final native void GetApproximateSizes( + long self, + @JniArg(cast="const leveldb::Range *") long range, + int n, + @JniArg(cast="uint64_t*") long[] sizes + ); + + @JniMethod(flags={CPP_METHOD}) + static final native boolean GetProperty( + long self, + @JniArg(flags={BY_VALUE, NO_OUT}) NativeSlice property, + @JniArg(cast="std::string *") long value + ); + + @JniMethod(copy="leveldb::Status", accessor = "leveldb::DestroyDB") + static final native long DestroyDB( + @JniArg(cast="const char*") String path, + @JniArg(flags={BY_VALUE, NO_OUT}) NativeOptions options); + + @JniMethod(copy="leveldb::Status", accessor = "leveldb::RepairDB") + static final native long RepairDB( + @JniArg(cast="const char*") String path, + @JniArg(flags={BY_VALUE, NO_OUT}) NativeOptions options); + + @JniMethod(flags={CPP_METHOD}) + static final native void CompactRange( + long self, + @JniArg(flags={NO_OUT}) NativeSlice begin, + @JniArg(flags={NO_OUT}) NativeSlice end + ); + + @JniMethod(flags={CPP_METHOD}) + static final native void SuspendCompactions(long self); + + @JniMethod(flags={CPP_METHOD}) + static final native void ResumeCompactions(long self); + } + + public void delete() { + assertAllocated(); + DBJNI.delete(self); + self = 0; + } + + private NativeDB(long self) { + super(self); + } + + public static class DBException extends IOException { + private final boolean notFound; + + DBException(String s, boolean notFound) { + super(s); + this.notFound = notFound; + } + + public boolean isNotFound() { + return notFound; + } + } + + static void checkStatus(long s) throws DBException { + NativeStatus status = new NativeStatus(s); + try { + if( !status.isOk() ) { + throw new DBException(status.toString(), status.isNotFound()); + } + } finally { + status.delete(); + } + } + + static void checkArgNotNull(Object value, String name) { + if(value==null) { + throw new IllegalArgumentException("The "+name+" argument cannot be null"); + } + } + + public static NativeDB open(NativeOptions options, File path) throws IOException, DBException { + checkArgNotNull(options, "options"); + checkArgNotNull(path, "path"); + long rc[] = new long[1]; + try { + checkStatus(DBJNI.Open(options, path.getCanonicalPath(), rc)); + } catch (IOException e) { + if( rc[0]!=0 ) { + DBJNI.delete(rc[0]); + } + throw e; + } + return new NativeDB(rc[0]); + } + + public void suspendCompactions() { + DBJNI.SuspendCompactions(self); + } + + public void resumeCompactions() { + DBJNI.ResumeCompactions(self); + } + + public void put(NativeWriteOptions options, byte[] key, byte[] value) throws DBException { + checkArgNotNull(options, "options"); + checkArgNotNull(key, "key"); + checkArgNotNull(value, "value"); + NativeBuffer keyBuffer = NativeBuffer.create(key); + try { + NativeBuffer valueBuffer = NativeBuffer.create(value); + try { + put(options, keyBuffer, valueBuffer); + } finally { + valueBuffer.delete(); + } + } finally { + keyBuffer.delete(); + } + } + + private void put(NativeWriteOptions options, NativeBuffer keyBuffer, NativeBuffer valueBuffer) throws DBException { + put(options, new NativeSlice(keyBuffer), new NativeSlice(valueBuffer)); + } + + private void put(NativeWriteOptions options, NativeSlice keySlice, NativeSlice valueSlice) throws DBException { + assertAllocated(); + checkStatus(DBJNI.Put(self, options, keySlice, valueSlice)); + } + + public void delete(NativeWriteOptions options, byte[] key) throws DBException { + checkArgNotNull(options, "options"); + checkArgNotNull(key, "key"); + NativeBuffer keyBuffer = NativeBuffer.create(key); + try { + delete(options, keyBuffer); + } finally { + keyBuffer.delete(); + } + } + + private void delete(NativeWriteOptions options, NativeBuffer keyBuffer) throws DBException { + delete(options, new NativeSlice(keyBuffer)); + } + + private void delete(NativeWriteOptions options, NativeSlice keySlice) throws DBException { + assertAllocated(); + checkStatus(DBJNI.Delete(self, options, keySlice)); + } + + public void write(NativeWriteOptions options, NativeWriteBatch updates) throws DBException { + checkArgNotNull(options, "options"); + checkArgNotNull(updates, "updates"); + checkStatus(DBJNI.Write(self, options, updates.pointer())); + } + + public byte[] get(NativeReadOptions options, byte[] key) throws DBException { + checkArgNotNull(options, "options"); + checkArgNotNull(key, "key"); + NativeBuffer keyBuffer = NativeBuffer.create(key); + try { + return get(options, keyBuffer); + } finally { + keyBuffer.delete(); + } + } + + private byte[] get(NativeReadOptions options, NativeBuffer keyBuffer) throws DBException { + return get(options, new NativeSlice(keyBuffer)); + } + + private byte[] get(NativeReadOptions options, NativeSlice keySlice) throws DBException { + assertAllocated(); + NativeStdString result = new NativeStdString(); + try { + checkStatus(DBJNI.Get(self, options, keySlice, result.pointer())); + return result.toByteArray(); + } finally { + result.delete(); + } + } + + public NativeSnapshot getSnapshot() { + return new NativeSnapshot(DBJNI.GetSnapshot(self)); + } + + public void releaseSnapshot(NativeSnapshot snapshot) { + checkArgNotNull(snapshot, "snapshot"); + DBJNI.ReleaseSnapshot(self, snapshot.pointer()); + } + + public NativeIterator iterator(NativeReadOptions options) { + checkArgNotNull(options, "options"); + return new NativeIterator(DBJNI.NewIterator(self, options)); + } + + public long[] getApproximateSizes(NativeRange... ranges) { + if( ranges==null ) { + return null; + } + + long rc[] = new long[ranges.length]; + NativeRange.RangeJNI structs[] = new NativeRange.RangeJNI[ranges.length]; + if( rc.length> 0 ) { + NativeBuffer range_array = NativeRange.RangeJNI.arrayCreate(ranges.length); + try { + for(int i=0; i < ranges.length; i++) { + structs[i] = new NativeRange.RangeJNI(ranges[i]); + structs[i].arrayWrite(range_array.pointer(), i); + } + DBJNI.GetApproximateSizes(self,range_array.pointer(), ranges.length, rc); + } finally { + for(int i=0; i < ranges.length; i++) { + if( structs[i] != null ) { + structs[i].delete(); + } + } + range_array.delete(); + } + } + return rc; + } + + public String getProperty(String name) { + checkArgNotNull(name, "name"); + NativeBuffer keyBuffer = NativeBuffer.create(name.getBytes()); + try { + byte[] property = getProperty(keyBuffer); + if( property==null ) { + return null; + } else { + return new String(property); + } + } finally { + keyBuffer.delete(); + } + } + + private byte[] getProperty(NativeBuffer nameBuffer) { + return getProperty(new NativeSlice(nameBuffer)); + } + + private byte[] getProperty(NativeSlice nameSlice) { + assertAllocated(); + NativeStdString result = new NativeStdString(); + try { + if( DBJNI.GetProperty(self, nameSlice, result.pointer()) ) { + return result.toByteArray(); + } else { + return null; + } + } finally { + result.delete(); + } + } + + public void compactRange(byte[] begin, byte[] end) { + NativeBuffer keyBuffer = NativeBuffer.create(begin); + try { + NativeBuffer valueBuffer = NativeBuffer.create(end); + try { + compactRange(keyBuffer, valueBuffer); + } finally { + if( valueBuffer!=null ) { + valueBuffer.delete(); + } + } + } finally { + if( keyBuffer!=null ) { + keyBuffer.delete(); + } + } + } + + private void compactRange( NativeBuffer beginBuffer, NativeBuffer endBuffer) { + compactRange(NativeSlice.create(beginBuffer), NativeSlice.create(endBuffer)); + } + + private void compactRange( NativeSlice beginSlice, NativeSlice endSlice) { + assertAllocated(); + DBJNI.CompactRange(self, beginSlice, endSlice); + } + + + static public void destroy(File path, NativeOptions options) throws IOException, DBException { + checkArgNotNull(options, "options"); + checkArgNotNull(path, "path"); + checkStatus(DBJNI.DestroyDB(path.getCanonicalPath(), options)); + } + + static public void repair(File path, NativeOptions options) throws IOException, DBException { + checkArgNotNull(options, "options"); + checkArgNotNull(path, "path"); + checkStatus(DBJNI.RepairDB(path.getCanonicalPath(), options)); + } +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeIterator.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeIterator.java new file mode 100644 index 00000000..bf40b190 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeIterator.java @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.fusesource.hawtjni.runtime.*; + +import static org.fusesource.hawtjni.runtime.MethodFlag.*; +import static org.fusesource.hawtjni.runtime.ArgFlag.*; +import static org.fusesource.hawtjni.runtime.ClassFlag.*; + +/** + * Provides a java interface to the C++ leveldb::Iterator class. + * + * @author Hiram Chirino + */ +public class NativeIterator extends NativeObject { + + @JniClass(name="leveldb::Iterator", flags={CPP}) + private static class IteratorJNI { + static { + NativeDB.LIBRARY.load(); + } + + @JniMethod(flags={CPP_DELETE}) + public static final native void delete( + long self + ); + + @JniMethod(flags={CPP_METHOD}) + static final native boolean Valid( + long self + ); + + @JniMethod(flags={CPP_METHOD}) + static final native void SeekToFirst( + long self + ); + + @JniMethod(flags={CPP_METHOD}) + static final native void SeekToLast( + long self + ); + + @JniMethod(flags={CPP_METHOD}) + static final native void Seek( + long self, + @JniArg(flags={BY_VALUE, NO_OUT}) NativeSlice target + ); + + @JniMethod(flags={CPP_METHOD}) + static final native void Next( + long self + ); + + @JniMethod(flags={CPP_METHOD}) + static final native void Prev( + long self + ); + + @JniMethod(copy="leveldb::Slice", flags={CPP_METHOD}) + static final native long key( + long self + ); + + @JniMethod(copy="leveldb::Slice", flags={CPP_METHOD}) + static final native long value( + long self + ); + + @JniMethod(copy="leveldb::Status", flags={CPP_METHOD}) + static final native long status( + long self + ); + } + + NativeIterator(long self) { + super(self); + } + + public void delete() { + assertAllocated(); + IteratorJNI.delete(self); + self = 0; + } + + public boolean isValid() { + assertAllocated(); + return IteratorJNI.Valid(self); + } + + private void checkStatus() throws NativeDB.DBException { + NativeDB.checkStatus(IteratorJNI.status(self)); + } + + public void seekToFirst() { + assertAllocated(); + IteratorJNI.SeekToFirst(self); + } + + public void seekToLast() { + assertAllocated(); + IteratorJNI.SeekToLast(self); + } + + public void seek(byte[] key) throws NativeDB.DBException { + NativeDB.checkArgNotNull(key, "key"); + NativeBuffer keyBuffer = NativeBuffer.create(key); + try { + seek(keyBuffer); + } finally { + keyBuffer.delete(); + } + } + + private void seek(NativeBuffer keyBuffer) throws NativeDB.DBException { + seek(new NativeSlice(keyBuffer)); + } + + private void seek(NativeSlice keySlice) throws NativeDB.DBException { + assertAllocated(); + IteratorJNI.Seek(self, keySlice); + checkStatus(); + } + + public void next() throws NativeDB.DBException { + assertAllocated(); + IteratorJNI.Next(self); + checkStatus(); + } + + public void prev() throws NativeDB.DBException { + assertAllocated(); + IteratorJNI.Prev(self); + checkStatus(); + } + + public byte[] key() throws NativeDB.DBException { + assertAllocated(); + long slice_ptr = IteratorJNI.key(self); + checkStatus(); + try { + NativeSlice slice = new NativeSlice(); + slice.read(slice_ptr, 0); + return slice.toByteArray(); + } finally { + NativeSlice.SliceJNI.delete(slice_ptr); + } + } + + public byte[] value() throws NativeDB.DBException { + assertAllocated(); + long slice_ptr = IteratorJNI.value(self); + checkStatus(); + try { + NativeSlice slice = new NativeSlice(); + slice.read(slice_ptr, 0); + return slice.toByteArray(); + } finally { + NativeSlice.SliceJNI.delete(slice_ptr); + } + } +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeLogger.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeLogger.java new file mode 100644 index 00000000..10f83e44 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeLogger.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.fusesource.hawtjni.runtime.JniArg; +import org.fusesource.hawtjni.runtime.JniClass; +import org.fusesource.hawtjni.runtime.JniField; +import org.fusesource.hawtjni.runtime.JniMethod; + +import static org.fusesource.hawtjni.runtime.ArgFlag.CRITICAL; +import static org.fusesource.hawtjni.runtime.ArgFlag.NO_OUT; +import static org.fusesource.hawtjni.runtime.ClassFlag.CPP; +import static org.fusesource.hawtjni.runtime.ClassFlag.STRUCT; +import static org.fusesource.hawtjni.runtime.FieldFlag.CONSTANT; +import static org.fusesource.hawtjni.runtime.FieldFlag.POINTER_FIELD; +import static org.fusesource.hawtjni.runtime.MethodFlag.*; + +/** + *

+ * Provides a java interface to the C++ leveldb::Logger class. + *

+ * + * @author Hiram Chirino + */ +public abstract class NativeLogger extends NativeObject { + + @JniClass(name="JNILogger", flags={STRUCT, CPP}) + static public class LoggerJNI { + + static { + NativeDB.LIBRARY.load(); + init(); + } + + @JniMethod(flags={CPP_NEW}) + public static final native long create(); + + @JniMethod(flags={CPP_DELETE}) + public static final native void delete( + long self + ); + + public static final native void memmove ( + @JniArg(cast="void *") long dest, + @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}) LoggerJNI src, + @JniArg(cast="size_t") long size); + + @JniField(cast="jobject", flags={POINTER_FIELD}) + long target; + + @JniField(cast="jmethodID", flags={POINTER_FIELD}) + long log_method; + + @JniMethod(flags={CONSTANT_INITIALIZER}) + private static final native void init(); + + @JniField(flags={CONSTANT}, accessor="sizeof(struct JNILogger)") + static int SIZEOF; + } + + private long globalRef; + + public NativeLogger() { + super(LoggerJNI.create()); + try { + globalRef = NativeDB.DBJNI.NewGlobalRef(this); + if( globalRef==0 ) { + throw new RuntimeException("jni call failed: NewGlobalRef"); + } + LoggerJNI struct = new LoggerJNI(); + struct.log_method = NativeDB.DBJNI.GetMethodID(this.getClass(), "log", "(Ljava/lang/String;)V"); + if( struct.log_method ==0 ) { + throw new RuntimeException("jni call failed: GetMethodID"); + } + struct.target = globalRef; + LoggerJNI.memmove(self, struct, LoggerJNI.SIZEOF); + + } catch (RuntimeException e) { + delete(); + throw e; + } + } + + NativeLogger(long ptr) { + super(ptr); + } + + public void delete() { + if( globalRef!=0 ) { + NativeDB.DBJNI.DeleteGlobalRef(globalRef); + globalRef = 0; + } + } + + public abstract void log(String message); + +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeObject.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeObject.java new file mode 100644 index 00000000..af2fb84a --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeObject.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +/** + * A helper base class which is used to track a pointer to a native + * structure or class. + * + * @author Hiram Chirino + */ +class NativeObject { + + protected long self; + + protected NativeObject(long self) { + this.self = self; + if( self ==0 ) { + throw new OutOfMemoryError("Failure allocating native heap memory"); + } + } + + long pointer() { + return self; + } + + public boolean isAllocated() { + return self !=0; + } + + protected void assertAllocated() { + assert isAllocated() : "This object has been deleted"; + } + +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeOptions.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeOptions.java new file mode 100644 index 00000000..dafbb588 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeOptions.java @@ -0,0 +1,465 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.fusesource.hawtjni.runtime.JniClass; +import org.fusesource.hawtjni.runtime.JniField; +import org.fusesource.hawtjni.runtime.JniMethod; + +import static org.fusesource.hawtjni.runtime.ClassFlag.CPP; +import static org.fusesource.hawtjni.runtime.ClassFlag.STRUCT; +import static org.fusesource.hawtjni.runtime.FieldFlag.CONSTANT; +import static org.fusesource.hawtjni.runtime.FieldFlag.FIELD_SKIP; +import static org.fusesource.hawtjni.runtime.MethodFlag.CONSTANT_INITIALIZER; + +/** + * Provides a java interface to the C++ leveldb::Options class. + * + * @author Hiram Chirino + */ +@JniClass(name="leveldb::Options", flags={STRUCT, CPP}) +public class NativeOptions { + + static { + NativeDB.LIBRARY.load(); + init(); + } + + @JniMethod(flags={CONSTANT_INITIALIZER}) + private static final native void init(); + + @JniField(flags={CONSTANT}, cast="Env*", accessor="leveldb::Env::Default()") + private static long DEFAULT_ENV; + + private boolean create_if_missing = false; + private boolean error_if_exists = false; + private boolean paranoid_checks = false; + @JniField(cast="size_t") + private long write_buffer_size = 4 << 20; + @JniField(cast="size_t") + private long max_write_buffer_number = 2; + @JniField(cast="size_t") + private long block_size = 4086; + private int max_open_files = 1000; + private int block_restart_interval = 16; + private boolean no_block_cache = false; + private boolean use_fsync = false; + private int num_levels = 7; + private int level0_file_num_compaction_trigger = 4; + private int level0_slowdown_writes_trigger = 8; + private int level0_stop_writes_trigger = 12; + private int max_mem_compaction_level = 2; + private int target_file_size_base = 2 * 1048576; + private int target_file_size_multiplier = 1; + + @JniField(flags={FIELD_SKIP}) + private NativeComparator comparatorObject = NativeComparator.BYTEWISE_COMPARATOR; + @JniField(cast="const leveldb::Comparator*") + private long comparator = comparatorObject.pointer(); + + @JniField(cast="uint64_t") + private long max_bytes_for_level_base = 10 * 1048576; + private int max_bytes_for_level_multiplier = 10; + private int expanded_compaction_factor = 25; + private int source_compaction_factor = 1; + private int max_grandparent_overlap_factor = 10; + private boolean disableDataSync = false; + private int db_stats_log_interval = 1800; + private boolean disable_seek_compaction = false; + @JniField(cast="uint64_t") + private long delete_obsolete_files_period_micros = 0; + private int max_background_compactions = 1; + + @JniField(cast="size_t") + private long max_log_file_size = 0; + private double rate_limit = 0.0; + private int table_cache_numshardbits = 4; + private boolean disable_auto_compactions = false; + + @JniField(cast="uint64_t") + private long WAL_ttl_seconds = 0; + + @JniField(flags={FIELD_SKIP}) + private NativeLogger infoLogObject = null; + @JniField(cast="leveldb::Logger*") + private long info_log = 0; + + @JniField(cast="leveldb::Env*") + private long env = DEFAULT_ENV; + @JniField(cast="leveldb::Cache*") + private long block_cache = 0; + @JniField(flags={FIELD_SKIP}) + private NativeCache cache; + + @JniField(cast="leveldb::CompressionType") + private int compression = NativeCompressionType.kSnappyCompression.value; + + public NativeOptions createIfMissing(boolean value) { + this.create_if_missing = value; + return this; + } + public boolean createIfMissing() { + return create_if_missing; + } + + public NativeOptions errorIfExists(boolean value) { + this.error_if_exists = value; + return this; + } + public boolean errorIfExists() { + return error_if_exists; + } + + public NativeOptions paranoidChecks(boolean value) { + this.paranoid_checks = value; + return this; + } + public boolean paranoidChecks() { + return paranoid_checks; + } + + public NativeOptions writeBufferSize(long value) { + this.write_buffer_size = value; + return this; + } + public long writeBufferSize() { + return write_buffer_size; + } + + public NativeOptions maxOpenFiles(int value) { + this.max_open_files = value; + return this; + } + public int maxOpenFiles() { + return max_open_files; + } + + public NativeOptions blockRestartInterval(int value) { + this.block_restart_interval = value; + return this; + } + public int blockRestartInterval() { + return block_restart_interval; + } + + public NativeOptions blockSize(long value) { + this.block_size = value; + return this; + } + public long blockSize() { + return block_size; + } + +// @JniField(cast="Env*") +// private long env = DEFAULT_ENV; + + public NativeComparator comparator() { + return comparatorObject; + } + + public NativeOptions comparator(NativeComparator comparator) { + if( comparator==null ) { + throw new IllegalArgumentException("comparator cannot be null"); + } + this.comparatorObject = comparator; + this.comparator = comparator.pointer(); + return this; + } + + public NativeLogger infoLog() { + return infoLogObject; + } + + public NativeOptions infoLog(NativeLogger logger) { + this.infoLogObject = logger; + if( logger ==null ) { + this.info_log = 0; + } else { + this.info_log = logger.pointer(); + } + return this; + } + + public NativeCompressionType compression() { + if(compression == NativeCompressionType.kNoCompression.value) { + return NativeCompressionType.kNoCompression; + } else if(compression == NativeCompressionType.kSnappyCompression.value) { + return NativeCompressionType.kSnappyCompression; + } else { + return NativeCompressionType.kSnappyCompression; + } + } + + public NativeOptions compression(NativeCompressionType compression) { + this.compression = compression.value; + return this; + } + + public NativeCache cache() { + return cache; + } + + public NativeOptions cache(NativeCache cache) { + this.cache = cache; + if( cache!=null ) { + this.block_cache = cache.pointer(); + } else { + this.block_cache = 0; + } + return this; + } + + public int numLevels() { + return this.num_levels; + } + + public NativeOptions numLevels(int numLevels) { + this.num_levels = numLevels; + return this; + } + + public int level0FileNumCompactionTrigger() { + return this.level0_file_num_compaction_trigger; + } + + public NativeOptions level0FileNumCompactionTrigger(int n) { + this.level0_file_num_compaction_trigger = n; + return this; + } + + public int level0SlowdownWritesTrigger() { + return this.level0_slowdown_writes_trigger; + } + + public NativeOptions level0SlowdownWritesTrigger(int n) { + this.level0_slowdown_writes_trigger = n; + return this; + } + + public int level0StopWritesTrigger() { + return this.level0_stop_writes_trigger; + } + + public NativeOptions level0StopWritesTrigger(int n) { + this.level0_stop_writes_trigger = n; + return this; + } + + public int maxMemCompactionLevel() { + return this.max_mem_compaction_level; + } + + public NativeOptions maxMemCompactionLevel(int n) { + this.max_mem_compaction_level = n; + return this; + } + + public int targetFileSizeBase() { + return this.target_file_size_base; + } + + public NativeOptions targetFileSizeBase(int n) { + this.target_file_size_base = n; + return this; + } + + public int targetFileSizeMultiplier() { + return this.target_file_size_multiplier; + } + + public NativeOptions targetFileSizeMultiplier(int n) { + this.target_file_size_multiplier = n; + return this; + } + + public long maxBytesLevelBase() { + return this.max_bytes_for_level_base; + } + + public NativeOptions maxBytesLevelBase(long n) { + this.max_bytes_for_level_base = n; + return this; + } + + public int maxBytesLevelMultiplier() { + return this.max_bytes_for_level_multiplier; + } + + public NativeOptions maxBytesLevelMultiplier(int n) { + this.max_bytes_for_level_multiplier = n; + return this; + } + + public int expandedCompactionFactor() { + return this.expanded_compaction_factor; + } + + public NativeOptions expandedCompactionFactor(int n) { + this.expanded_compaction_factor = n; + return this; + } + + public int sourceCompactionFactor() { + return this.source_compaction_factor; + } + + public NativeOptions sourceCompactionFactor(int n) { + this.source_compaction_factor = n; + return this; + } + + public int maxGrandparentOverlapFactor() { + return this.max_grandparent_overlap_factor; + } + + public NativeOptions maxGrandparentOverlapFactor(int n) { + this.max_grandparent_overlap_factor = n; + return this; + } + + public boolean disableDataSync() { + return this.disableDataSync; + } + + public NativeOptions disableDataSync(boolean flag) { + this.disableDataSync = flag; + return this; + } + + public int dbStatsLogInterval() { + return this.db_stats_log_interval; + } + + public NativeOptions dbStatsLogInterval(int n) { + this.db_stats_log_interval = n; + return this; + } + + public boolean disableSeekCompaction() { + return this.disable_seek_compaction; + } + + public NativeOptions disableSeekCompaction(boolean flag) { + this.disable_seek_compaction = flag; + return this; + } + + public long deleteObsoleteFilesMicros() { + return this.delete_obsolete_files_period_micros; + } + + public NativeOptions deleteObsoleteFilesMicros(long micros) { + this.delete_obsolete_files_period_micros = micros; + return this; + } + + public int maxBackgroundCompactions() { + return this.max_background_compactions; + } + + public NativeOptions maxBackgroundCompactions(int n) { + this.max_background_compactions = n; + return this; + } + + public long maxLogFileSize() { + return this.max_log_file_size; + } + + public NativeOptions maxLogFileSize(long s) { + this.max_log_file_size = s; + return this; + } + + public double rateLimit() { + return this.rate_limit; + } + + public NativeOptions rateLimit(double rate) { + this.rate_limit = rate; + return this; + } + + public int tableCacheNumShardBits() { + return this.table_cache_numshardbits; + } + + public NativeOptions tableCacheNumShardBits(int n) { + this.table_cache_numshardbits = n; + return this; + } + + public boolean disableAutoCompactions() { + return this.disable_auto_compactions; + } + + public NativeOptions disableAutoCompactions(boolean b) { + this.disable_auto_compactions = b; + return this; + } + + public long WALttlSeconds() { + return this.WAL_ttl_seconds; + } + + public NativeOptions WALttlSeconds(long n) { + this.WAL_ttl_seconds = n; + return this; + } + + public boolean noBlockCache() { + return this.no_block_cache; + } + + public NativeOptions noBlockCache(boolean b) { + this.no_block_cache = b; + return this; + } + + public boolean useFsync() { + return this.use_fsync; + } + + public NativeOptions useFsync(boolean b) { + this.use_fsync = b; + return this; + } + + public long maxWriteBufferNumber() { + return this.max_write_buffer_number; + } + + public NativeOptions maxWriteBufferNumber(long n) { + this.max_write_buffer_number = n; + return this; + } +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeRange.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeRange.java new file mode 100644 index 00000000..953d37e7 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeRange.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.fusesource.hawtjni.runtime.*; + +import static org.fusesource.hawtjni.runtime.ArgFlag.*; +import static org.fusesource.hawtjni.runtime.ClassFlag.CPP; +import static org.fusesource.hawtjni.runtime.ClassFlag.STRUCT; +import static org.fusesource.hawtjni.runtime.FieldFlag.CONSTANT; +import static org.fusesource.hawtjni.runtime.FieldFlag.FIELD_SKIP; +import static org.fusesource.hawtjni.runtime.MethodFlag.CONSTANT_INITIALIZER; + +/** + * Provides a java interface to the C++ leveldb::ReadOptions class. + * + * @author Hiram Chirino + */ +public class NativeRange { + + @JniClass(name="leveldb::Range", flags={STRUCT, CPP}) + static public class RangeJNI { + + static { + NativeDB.LIBRARY.load(); + init(); + } + + public static final native void memmove ( + @JniArg(cast="void *") long dest, + @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}) RangeJNI src, + @JniArg(cast="size_t") long size); + + public static final native void memmove ( + @JniArg(cast="void *", flags={NO_IN, CRITICAL}) RangeJNI dest, + @JniArg(cast="const void *") long src, + @JniArg(cast="size_t") long size); + + + @JniMethod(flags={CONSTANT_INITIALIZER}) + private static final native void init(); + + @JniField(flags={CONSTANT}, accessor="sizeof(struct leveldb::Range)") + static int SIZEOF; + + @JniField + NativeSlice start = new NativeSlice(); + @JniField(flags={FIELD_SKIP}) + NativeBuffer start_buffer; + + @JniField + NativeSlice limit = new NativeSlice(); + @JniField(flags={FIELD_SKIP}) + NativeBuffer limit_buffer; + + public RangeJNI(NativeRange range) { + start_buffer = NativeBuffer.create(range.start()); + start.set(start_buffer); + try { + limit_buffer = NativeBuffer.create(range.limit()); + } catch (OutOfMemoryError e) { + start_buffer.delete(); + throw e; + } + limit.set(limit_buffer); + } + + public void delete() { + start_buffer.delete(); + limit_buffer.delete(); + } + + static NativeBuffer arrayCreate(int dimension) { + return NativeBuffer.create(dimension*SIZEOF); + } + + void arrayWrite(long buffer, int index) { + RangeJNI.memmove(PointerMath.add(buffer, SIZEOF * index), this, SIZEOF); + } + + void arrayRead(long buffer, int index) { + RangeJNI.memmove(this, PointerMath.add(buffer, SIZEOF * index), SIZEOF); + } + + } + + final private byte[] start; + final private byte[] limit; + + public byte[] limit() { + return limit; + } + + public byte[] start() { + return start; + } + + public NativeRange(byte[] start, byte[] limit) { + NativeDB.checkArgNotNull(start, "start"); + NativeDB.checkArgNotNull(limit, "limit"); + this.limit = limit; + this.start = start; + } +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeReadOptions.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeReadOptions.java new file mode 100644 index 00000000..85e76a3d --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeReadOptions.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.fusesource.hawtjni.runtime.JniClass; +import org.fusesource.hawtjni.runtime.JniField; + +import static org.fusesource.hawtjni.runtime.ClassFlag.CPP; +import static org.fusesource.hawtjni.runtime.ClassFlag.STRUCT; + +/** + * Provides a java interface to the C++ leveldb::ReadOptions class. + * + * @author Hiram Chirino + */ +@JniClass(name="leveldb::ReadOptions", flags={STRUCT, CPP}) +public class NativeReadOptions { + + @JniField + private boolean verify_checksums = false; + + @JniField + private boolean fill_cache = true; + + @JniField(cast="const leveldb::Snapshot*") + private long snapshot=0; + + public boolean fillCache() { + return fill_cache; + } + + public NativeReadOptions fillCache(boolean fill_cache) { + this.fill_cache = fill_cache; + return this; + } + + public NativeSnapshot snapshot() { + if( snapshot == 0 ) { + return null; + } else { + return new NativeSnapshot(snapshot); + } + } + + public NativeReadOptions snapshot(NativeSnapshot snapshot) { + if( snapshot==null ) { + this.snapshot = 0; + } else { + this.snapshot = snapshot.pointer(); + } + return this; + } + + public boolean verifyChecksums() { + return verify_checksums; + } + + public NativeReadOptions verifyChecksums(boolean verify_checksums) { + this.verify_checksums = verify_checksums; + return this; + } +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeSlice.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeSlice.java new file mode 100644 index 00000000..a2e2d60b --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeSlice.java @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.fusesource.hawtjni.runtime.*; + +import static org.fusesource.hawtjni.runtime.ArgFlag.*; +import static org.fusesource.hawtjni.runtime.ClassFlag.CPP; +import static org.fusesource.hawtjni.runtime.ClassFlag.STRUCT; +import static org.fusesource.hawtjni.runtime.FieldFlag.CONSTANT; +import static org.fusesource.hawtjni.runtime.MethodFlag.CONSTANT_INITIALIZER; +import static org.fusesource.hawtjni.runtime.MethodFlag.CPP_DELETE; + +/** + * Provides a java interface to the C++ leveldb::Slice class. + * + * @author Hiram Chirino + */ +@JniClass(name="leveldb::Slice", flags={STRUCT, CPP}) +class NativeSlice { + + @JniClass(name="leveldb::Slice", flags={CPP}) + static class SliceJNI { + static { + NativeDB.LIBRARY.load(); + init(); + } + + @JniMethod(flags={CPP_DELETE}) + public static final native void delete( + long self + ); + + public static final native void memmove ( + @JniArg(cast="void *") long dest, + @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}) NativeSlice src, + @JniArg(cast="size_t") long size); + + public static final native void memmove ( + @JniArg(cast="void *", flags={NO_IN, CRITICAL}) NativeSlice dest, + @JniArg(cast="const void *") long src, + @JniArg(cast="size_t") long size); + + + @JniMethod(flags={CONSTANT_INITIALIZER}) + private static final native void init(); + + @JniField(flags={CONSTANT}, accessor="sizeof(struct leveldb::Slice)") + static int SIZEOF; + + } + + + @JniField(cast="const char*") + private long data_; + @JniField(cast="size_t") + private long size_; + + public NativeSlice() { + } + + public NativeSlice(long data, long length) { + this.data_ = data; + this.size_ = length; + } + + public NativeSlice(NativeBuffer buffer) { + this(buffer.pointer(), buffer.capacity()); + } + + public static NativeSlice create(NativeBuffer buffer) { + if(buffer == null ) { + return null; + } else { + return new NativeSlice(buffer); + } + } + + public long data() { + return data_; + } + + public NativeSlice data(long data) { + this.data_ = data; + return this; + } + + public long size() { + return size_; + } + + public NativeSlice size(long size) { + this.size_ = size; + return this; + } + + public NativeSlice set(NativeSlice buffer) { + this.size_ = buffer.size_; + this.data_ = buffer.data_; + return this; + } + + public NativeSlice set(NativeBuffer buffer) { + this.size_ = buffer.capacity(); + this.data_ = buffer.pointer(); + return this; + } + + public byte[] toByteArray() { + if( size_ > Integer.MAX_VALUE ) { + throw new ArrayIndexOutOfBoundsException("Native slice is larger than the maximum Java array"); + } + byte []rc = new byte[(int) size_]; + NativeBuffer.NativeBufferJNI.buffer_copy(data_, 0, rc, 0, rc.length); + return rc; + } + + static NativeBuffer arrayCreate(int dimension) { + return NativeBuffer.create(dimension*SliceJNI.SIZEOF); + } + + void write(long buffer, int index) { + SliceJNI.memmove(PointerMath.add(buffer, SliceJNI.SIZEOF*index), this, SliceJNI.SIZEOF); + } + + void read(long buffer, int index) { + SliceJNI.memmove(this, PointerMath.add(buffer, SliceJNI.SIZEOF*index), SliceJNI.SIZEOF); + } + + +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeSnapshot.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeSnapshot.java new file mode 100644 index 00000000..69403e19 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeSnapshot.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +/** + * Provides a java interface to the C++ leveldb::Snapshot class. + * + * @author Hiram Chirino + */ +public class NativeSnapshot extends NativeObject { + + NativeSnapshot(long self) { + super(self); + } + +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeStatus.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeStatus.java new file mode 100644 index 00000000..2950066b --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeStatus.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.fusesource.hawtjni.runtime.JniClass; +import org.fusesource.hawtjni.runtime.JniMethod; + +import static org.fusesource.hawtjni.runtime.ClassFlag.CPP; +import static org.fusesource.hawtjni.runtime.MethodFlag.CPP_DELETE; +import static org.fusesource.hawtjni.runtime.MethodFlag.CPP_METHOD; + +/** + * Provides a java interface to the C++ leveldb::Status class. + * + * @author Hiram Chirino + */ +class NativeStatus extends NativeObject{ + + @JniClass(name="leveldb::Status", flags={CPP}) + static class StatusJNI { + static { + NativeDB.LIBRARY.load(); + } + + @JniMethod(flags={CPP_DELETE}) + public static final native void delete( + long self); + + @JniMethod(flags={CPP_METHOD}) + public static final native boolean ok( + long self); + + @JniMethod(flags={CPP_METHOD}) + public static final native boolean IsNotFound( + long self); + + @JniMethod(copy="std::string", flags={CPP_METHOD}) + public static final native long ToString( + long self); + } + + public NativeStatus(long self) { + super(self); + } + + public void delete() { + assertAllocated(); + StatusJNI.delete(self); + self = 0; + } + + public boolean isOk() { + assertAllocated(); + return StatusJNI.ok(self); + } + + public boolean isNotFound() { + assertAllocated(); + return StatusJNI.IsNotFound(self); + } + + public String toString() { + assertAllocated(); + long strptr = StatusJNI.ToString(self); + if( strptr==0 ) { + return null; + } else { + NativeStdString rc = new NativeStdString(strptr); + try { + return rc.toString(); + } finally { + rc.delete(); + } + } + } + +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeStdString.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeStdString.java new file mode 100644 index 00000000..85a51c2b --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeStdString.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.fusesource.hawtjni.runtime.JniClass; +import org.fusesource.hawtjni.runtime.JniMethod; + +import static org.fusesource.hawtjni.runtime.ClassFlag.CPP; +import static org.fusesource.hawtjni.runtime.MethodFlag.*; + +/** + * Provides a java interface to the C++ std::string class. + * + * @author Hiram Chirino + */ +class NativeStdString extends NativeObject { + + @JniClass(name="std::string", flags={CPP}) + private static class StdStringJNI { + static { + NativeDB.LIBRARY.load(); + } + + @JniMethod(flags={CPP_NEW}) + public static final native long create(); + + @JniMethod(flags={CPP_NEW}) + public static final native long create(String value); + + @JniMethod(flags={CPP_DELETE}) + static final native void delete( + long self); + + @JniMethod(flags={CPP_METHOD}, accessor = "c_str", cast="const char*") + public static final native long c_str_ptr ( + long self); + + @JniMethod(flags={CPP_METHOD},cast = "size_t") + public static final native long length ( + long self); + + } + + public NativeStdString(long self) { + super(self); + } + + public NativeStdString() { + super(StdStringJNI.create()); + } + + public void delete() { + assertAllocated(); + StdStringJNI.delete(self); + self = 0; + } + + public String toString() { + return new String(toByteArray()); + } + + public long length() { + assertAllocated(); + return StdStringJNI.length(self); + } + + public byte[] toByteArray() { + long l = length(); + if( l > Integer.MAX_VALUE ) { + throw new ArrayIndexOutOfBoundsException("Native string is larger than the maximum Java array"); + } + byte []rc = new byte[(int) l]; + NativeBuffer.NativeBufferJNI.buffer_copy(StdStringJNI.c_str_ptr(self), 0, rc, 0, rc.length); + return rc; + } +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeWriteBatch.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeWriteBatch.java new file mode 100644 index 00000000..bac8f21f --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeWriteBatch.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.fusesource.hawtjni.runtime.JniArg; +import org.fusesource.hawtjni.runtime.JniClass; +import org.fusesource.hawtjni.runtime.JniMethod; + +import static org.fusesource.hawtjni.runtime.ArgFlag.BY_VALUE; +import static org.fusesource.hawtjni.runtime.ArgFlag.NO_OUT; +import static org.fusesource.hawtjni.runtime.ClassFlag.CPP; +import static org.fusesource.hawtjni.runtime.MethodFlag.*; + +/** + * Provides a java interface to the C++ leveldb::WriteBatch class. + * + * @author Hiram Chirino + */ +public class NativeWriteBatch extends NativeObject { + + @JniClass(name="leveldb::WriteBatch", flags={CPP}) + private static class WriteBatchJNI { + static { + NativeDB.LIBRARY.load(); + } + + @JniMethod(flags={CPP_NEW}) + public static final native long create(); + @JniMethod(flags={CPP_DELETE}) + public static final native void delete( + long self); + + @JniMethod(flags={CPP_METHOD}) + static final native void Put( + long self, + @JniArg(flags={BY_VALUE, NO_OUT}) NativeSlice key, + @JniArg(flags={BY_VALUE, NO_OUT}) NativeSlice value + ); + + @JniMethod(flags={CPP_METHOD}) + static final native void Delete( + long self, + @JniArg(flags={BY_VALUE, NO_OUT}) NativeSlice key + ); + + @JniMethod(flags={CPP_METHOD}) + static final native void Clear( + long self + ); + + } + + public NativeWriteBatch() { + super(WriteBatchJNI.create()); + } + + public void delete() { + assertAllocated(); + WriteBatchJNI.delete(self); + self = 0; + } + + public void put(byte[] key, byte[] value) { + NativeDB.checkArgNotNull(key, "key"); + NativeDB.checkArgNotNull(value, "value"); + NativeBuffer keyBuffer = NativeBuffer.create(key); + try { + NativeBuffer valueBuffer = NativeBuffer.create(value); + try { + put(keyBuffer, valueBuffer); + } finally { + valueBuffer.delete(); + } + } finally { + keyBuffer.delete(); + } + } + + private void put(NativeBuffer keyBuffer, NativeBuffer valueBuffer) { + put(new NativeSlice(keyBuffer), new NativeSlice(valueBuffer)); + } + + private void put(NativeSlice keySlice, NativeSlice valueSlice) { + assertAllocated(); + WriteBatchJNI.Put(self, keySlice, valueSlice); + } + + + public void delete(byte[] key) { + NativeDB.checkArgNotNull(key, "key"); + NativeBuffer keyBuffer = NativeBuffer.create(key); + try { + delete(keyBuffer); + } finally { + keyBuffer.delete(); + } + } + + private void delete(NativeBuffer keyBuffer) { + delete(new NativeSlice(keyBuffer)); + } + + private void delete(NativeSlice keySlice) { + assertAllocated(); + WriteBatchJNI.Delete(self, keySlice); + } + + public void clear() { + assertAllocated(); + WriteBatchJNI.Clear(self); + } + +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeWriteOptions.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeWriteOptions.java new file mode 100644 index 00000000..81c76fea --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeWriteOptions.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.fusesource.hawtjni.runtime.JniClass; +import org.fusesource.hawtjni.runtime.JniField; + +import static org.fusesource.hawtjni.runtime.ClassFlag.CPP; +import static org.fusesource.hawtjni.runtime.ClassFlag.STRUCT; + +/** + * Provides a java interface to the C++ leveldb::WriteOptions class. + * + * @author Hiram Chirino + */ +@JniClass(name="leveldb::WriteOptions", flags={STRUCT, CPP}) +public class NativeWriteOptions { + + @JniField + boolean sync; + + public boolean sync() { + return sync; + } + + public NativeWriteOptions sync(boolean sync) { + this.sync = sync; + return this; + } + +} diff --git a/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/Util.java b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/Util.java new file mode 100644 index 00000000..55258ad4 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/Util.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.internal; + +import org.fusesource.hawtjni.runtime.JniArg; +import org.fusesource.hawtjni.runtime.JniClass; +import org.fusesource.hawtjni.runtime.JniField; +import org.fusesource.hawtjni.runtime.JniMethod; + +import java.io.File; +import java.io.IOException; + +import static org.fusesource.hawtjni.runtime.ClassFlag.CPP; +import static org.fusesource.hawtjni.runtime.FieldFlag.CONSTANT; +import static org.fusesource.hawtjni.runtime.MethodFlag.*; +import static org.fusesource.hawtjni.runtime.ArgFlag.*; + +/** + * Some miscellaneous utility functions. + * + * @author Hiram Chirino + */ +public class Util { + + @JniClass(name="leveldb::Env", flags={CPP}) + static class EnvJNI { + + static { + NativeDB.LIBRARY.load(); + } + + @JniMethod(cast = "leveldb::Env *", accessor = "leveldb::Env::Default") + public static final native long Default(); + + @JniMethod(flags = {CPP_METHOD}) + public static final native void Schedule( + long self, + @JniArg(cast = "void (*)(void*)") long fp, + @JniArg(cast = "void *") long arg); + + } + + @JniClass(flags={CPP}) + static class UtilJNI { + + static { + NativeDB.LIBRARY.load(); + init(); + } + + @JniMethod(flags={CONSTANT_INITIALIZER}) + private static final native void init(); + + @JniField(flags={CONSTANT}, accessor="1", conditional="defined(_WIN32) || defined(_WIN64)") + static int ON_WINDOWS; + + + @JniMethod(conditional="!defined(_WIN32) && !defined(_WIN64)") + static final native int link( + @JniArg(cast="const char*") String source, + @JniArg(cast="const char*") String target); + + @JniMethod(conditional="defined(_WIN32) || defined(_WIN64)") + static final native int CreateHardLinkW( + @JniArg(cast="LPCTSTR", flags={POINTER_ARG, UNICODE}) String target, + @JniArg(cast="LPCTSTR", flags={POINTER_ARG, UNICODE}) String source, + @JniArg(cast="LPSECURITY_ATTRIBUTES", flags={POINTER_ARG}) long lpSecurityAttributes); + + @JniMethod(flags={CONSTANT_GETTER}) + public static final native int errno(); + + @JniMethod(cast="char *") + public static final native long strerror(int errnum); + + public static final native int strlen( + @JniArg(cast="const char *")long s); + + } + + /** + * Creates a hard link from source to target. + * @param source + * @param target + * @return + */ + public static void link(File source, File target) throws IOException { + if( UtilJNI.ON_WINDOWS == 1 ) { + if( UtilJNI.CreateHardLinkW(target.getCanonicalPath(), source.getCanonicalPath(), 0) == 0) { + throw new IOException("link failed"); + } + } else { + if( UtilJNI.link(source.getCanonicalPath(), target.getCanonicalPath()) != 0 ) { + throw new IOException("link failed: "+strerror()); + } + } + } + + static int errno() { + return UtilJNI.errno(); + } + + static String strerror() { + return string(UtilJNI.strerror(errno())); + } + + static String string(long ptr) { + if( ptr == 0 ) + return null; + return new String(new NativeSlice(ptr, UtilJNI.strlen(ptr)).toByteArray()); + } + +} diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/Makefile.am b/java/leveldbjni/leveldbjni/src/main/native-package/Makefile.am new file mode 100644 index 00000000..c73517d1 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/Makefile.am @@ -0,0 +1,28 @@ +# --------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# --------------------------------------------------------------------------- + +ACLOCAL_AMFLAGS = -I m4 + +lib_LTLIBRARIES = libleveldbjni.la +# libleveldbjni_la_CFLAGS = +#libleveldbjni_la_LDFLAGS = + +libleveldbjni_la_SOURCES = src/leveldbjni.cpp\ + src/leveldbjni_stats.cpp\ + src/leveldbjni_structs.cpp\ + src/buffer.c\ + src/hawtjni.c diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/Makefile.in b/java/leveldbjni/leveldbjni/src/main/native-package/Makefile.in new file mode 100644 index 00000000..e5c0f39c --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/Makefile.in @@ -0,0 +1,810 @@ +# Makefile.in generated by automake 1.12.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# --------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# --------------------------------------------------------------------------- + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = . +DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/autotools/ar-lib \ + $(top_srcdir)/autotools/config.guess \ + $(top_srcdir)/autotools/config.sub \ + $(top_srcdir)/autotools/install-sh \ + $(top_srcdir)/autotools/ltmain.sh \ + $(top_srcdir)/autotools/missing $(top_srcdir)/configure \ + $(top_srcdir)/src/config.h.in autotools/ar-lib \ + autotools/config.guess autotools/config.sub \ + autotools/install-sh autotools/ltmain.sh autotools/missing +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/custom.m4 \ + $(top_srcdir)/m4/jni.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/osx-universal.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/src/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +libleveldbjni_la_LIBADD = +am_libleveldbjni_la_OBJECTS = leveldbjni.lo leveldbjni_stats.lo \ + leveldbjni_structs.lo buffer.lo hawtjni.lo +libleveldbjni_la_OBJECTS = $(am_libleveldbjni_la_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src +depcomp = +am__depfiles_maybe = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libleveldbjni_la_SOURCES) +DIST_SOURCES = $(libleveldbjni_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +AM_RECURSIVE_TARGETS = cscope +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +DIST_TARGETS = dist-gzip +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JNI_EXTRA_CFLAGS = @JNI_EXTRA_CFLAGS@ +JNI_EXTRA_LDFLAGS = @JNI_EXTRA_LDFLAGS@ +JNI_JDK = @JNI_JDK@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OSX_SDKS_DIR = @OSX_SDKS_DIR@ +OSX_VERSION = @OSX_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I m4 +lib_LTLIBRARIES = libleveldbjni.la +# libleveldbjni_la_CFLAGS = +#libleveldbjni_la_LDFLAGS = +libleveldbjni_la_SOURCES = src/leveldbjni.cpp\ + src/leveldbjni_stats.cpp\ + src/leveldbjni_structs.cpp\ + src/buffer.c\ + src/hawtjni.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .cpp .lo .o .obj +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign --ignore-deps'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign --ignore-deps \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign --ignore-deps Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign --ignore-deps Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +src/config.h: src/stamp-h1 + @if test ! -f $@; then rm -f src/stamp-h1; else :; fi + @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) src/stamp-h1; else :; fi + +src/stamp-h1: $(top_srcdir)/src/config.h.in $(top_builddir)/config.status + @rm -f src/stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status src/config.h +$(top_srcdir)/src/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f src/stamp-h1 + touch $@ + +distclean-hdr: + -rm -f src/config.h src/stamp-h1 +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libleveldbjni.la: $(libleveldbjni_la_OBJECTS) $(libleveldbjni_la_DEPENDENCIES) $(EXTRA_libleveldbjni_la_DEPENDENCIES) + $(CXXLINK) -rpath $(libdir) $(libleveldbjni_la_OBJECTS) $(libleveldbjni_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(COMPILE) -c $< + +.c.obj: + $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: + $(LTCOMPILE) -c -o $@ $< + +buffer.lo: src/buffer.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o buffer.lo `test -f 'src/buffer.c' || echo '$(srcdir)/'`src/buffer.c + +hawtjni.lo: src/hawtjni.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hawtjni.lo `test -f 'src/hawtjni.c' || echo '$(srcdir)/'`src/hawtjni.c + +.cpp.o: + $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: + $(LTCXXCOMPILE) -c -o $@ $< + +leveldbjni.lo: src/leveldbjni.cpp + $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o leveldbjni.lo `test -f 'src/leveldbjni.cpp' || echo '$(srcdir)/'`src/leveldbjni.cpp + +leveldbjni_stats.lo: src/leveldbjni_stats.cpp + $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o leveldbjni_stats.lo `test -f 'src/leveldbjni_stats.cpp' || echo '$(srcdir)/'`src/leveldbjni_stats.cpp + +leveldbjni_structs.lo: src/leveldbjni_structs.cpp + $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o leveldbjni_structs.lo `test -f 'src/leveldbjni_structs.cpp' || echo '$(srcdir)/'`src/leveldbjni_structs.cpp + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) + +clean-cscope: + -rm -f cscope.files + +cscope.files: clean-cscope cscopelist + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \ + clean-cscope clean-generic clean-libLTLIBRARIES clean-libtool \ + cscope cscopelist ctags dist dist-all dist-bzip2 dist-gzip \ + dist-lzip dist-shar dist-tarZ dist-xz dist-zip distcheck \ + distclean distclean-compile distclean-generic distclean-hdr \ + distclean-libtool distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-libLTLIBRARIES + + +# 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/java/leveldbjni/leveldbjni/src/main/native-package/aclocal.m4 b/java/leveldbjni/leveldbjni/src/main/native-package/aclocal.m4 new file mode 100644 index 00000000..289e0773 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/aclocal.m4 @@ -0,0 +1,718 @@ +# generated automatically by aclocal 1.12.1 -*- Autoconf -*- + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +# Copyright (C) 2002-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 8 + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.12' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.12.1], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.12.1])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# Copyright (C) 2011-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_PROG_AR([ACT-IF-FAIL]) +# ------------------------- +# Try to determine the archiver interface, and trigger the ar-lib wrapper +# if it is needed. If the detection of archiver interface fails, run +# ACT-IF-FAIL (default is to abort configure with a proper error message). +AC_DEFUN([AM_PROG_AR], +[AC_BEFORE([$0], [LT_INIT])dnl +AC_BEFORE([$0], [AC_PROG_LIBTOOL])dnl +AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([ar-lib])dnl +AC_CHECK_TOOLS([AR], [ar lib "link -lib"], [false]) +: ${AR=ar} + +AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface], + [am_cv_ar_interface=ar + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int some_variable = 0;]])], + [am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([am_ar_try]) + if test "$ac_status" -eq 0; then + am_cv_ar_interface=ar + else + am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([am_ar_try]) + if test "$ac_status" -eq 0; then + am_cv_ar_interface=lib + else + am_cv_ar_interface=unknown + fi + fi + rm -f conftest.lib libconftest.a + ]) + ]) + +case $am_cv_ar_interface in +ar) + ;; +lib) + # Microsoft lib, so override with the ar-lib wrapper script. + # FIXME: It is wrong to rewrite AR. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__AR in this case, + # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something + # similar. + AR="$am_aux_dir/ar-lib $AR" + ;; +unknown) + m4_default([$1], + [AC_MSG_ERROR([could not determine $AR interface])]) + ;; +esac +AC_SUBST([AR])dnl +]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 10 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 19 + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.62])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], +[$0: two- and three-arguments forms are deprecated. For more info, see: +http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +dnl Support for Objective C++ was only introduced in Autoconf 2.65, +dnl but we still cater to Autoconf 2.62. +m4_ifdef([AC_PROG_OBJCXX], +[AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])])dnl +]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The 'parallel-tests' driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 8 + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 7 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 6 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 9 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 3 + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 3 + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of '-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([m4/custom.m4]) +m4_include([m4/jni.m4]) +m4_include([m4/libtool.m4]) +m4_include([m4/ltoptions.m4]) +m4_include([m4/ltsugar.m4]) +m4_include([m4/ltversion.m4]) +m4_include([m4/lt~obsolete.m4]) +m4_include([m4/osx-universal.m4]) diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/autotools/ar-lib b/java/leveldbjni/leveldbjni/src/main/native-package/autotools/ar-lib new file mode 100755 index 00000000..67f5f36f --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/autotools/ar-lib @@ -0,0 +1,270 @@ +#! /bin/sh +# Wrapper for Microsoft lib.exe + +me=ar-lib +scriptversion=2012-03-01.08; # UTC + +# Copyright (C) 2010-2012 Free Software Foundation, Inc. +# Written by Peter Rosin . +# +# 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, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + + +# func_error message +func_error () +{ + echo "$me: $1" 1>&2 + exit 1 +} + +file_conv= + +# func_file_conv build_file +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv in + mingw) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_at_file at_file operation archive +# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE +# for each of them. +# When interpreting the content of the @FILE, do NOT use func_file_conv, +# since the user would need to supply preconverted file names to +# binutils ar, at least for MinGW. +func_at_file () +{ + operation=$2 + archive=$3 + at_file_contents=`cat "$1"` + eval set x "$at_file_contents" + shift + + for member + do + $AR -NOLOGO $operation:"$member" "$archive" || exit $? + done +} + +case $1 in + '') + func_error "no command. Try '$0 --help' for more information." + ;; + -h | --h*) + cat <. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/autotools/config.sub b/java/leveldbjni/leveldbjni/src/main/native-package/autotools/config.sub new file mode 100755 index 00000000..59bb593f --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/autotools/config.sub @@ -0,0 +1,1779 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-04-18' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | open8 \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i386-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/autotools/install-sh b/java/leveldbjni/leveldbjni/src/main/native-package/autotools/install-sh new file mode 100755 index 00000000..377bb868 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/autotools/install-sh @@ -0,0 +1,527 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2011-11-20.07; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/autotools/ltmain.sh b/java/leveldbjni/leveldbjni/src/main/native-package/autotools/ltmain.sh new file mode 100644 index 00000000..63ae69dc --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/autotools/ltmain.sh @@ -0,0 +1,9655 @@ + +# libtool (GNU libtool) 2.4.2 +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, +# 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool 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. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, +# or obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Usage: $progname [OPTION]... [MODE-ARG]... +# +# Provide generalized library-building support services. +# +# --config show all configuration variables +# --debug enable verbose shell tracing +# -n, --dry-run display commands without modifying any files +# --features display basic configuration information and exit +# --mode=MODE use operation mode MODE +# --preserve-dup-deps don't remove duplicate dependency libraries +# --quiet, --silent don't print informational messages +# --no-quiet, --no-silent +# print informational messages (default) +# --no-warn don't display warning messages +# --tag=TAG use configuration variables from tag TAG +# -v, --verbose print more informational messages than default +# --no-verbose don't print the extra informational messages +# --version print version information +# -h, --help, --help-all print short, long, or detailed help message +# +# MODE must be one of the following: +# +# clean remove files from the build directory +# compile compile a source file into a libtool object +# execute automatically set library path, then run a program +# finish complete the installation of libtool libraries +# install install libraries or executables +# link create a library or an executable +# uninstall remove libraries from an installed directory +# +# MODE-ARGS vary depending on the MODE. When passed as first option, +# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. +# Try `$progname --help --mode=MODE' for a more detailed description of MODE. +# +# When reporting a bug, please describe a test case to reproduce it and +# include the following information: +# +# host-triplet: $host +# shell: $SHELL +# compiler: $LTCC +# compiler flags: $LTCFLAGS +# linker: $LD (gnu? $with_gnu_ld) +# $progname: (GNU libtool) 2.4.2 +# automake: $automake_version +# autoconf: $autoconf_version +# +# Report bugs to . +# GNU libtool home page: . +# General help using GNU software: . + +PROGRAM=libtool +PACKAGE=libtool +VERSION=2.4.2 +TIMESTAMP="" +package_revision=1.3337 + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + 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 + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# NLS nuisances: We save the old values to restore during execute mode. +lt_user_locale= +lt_safe_locale= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test \"\${$lt_var+set}\" = set; then + save_$lt_var=\$$lt_var + $lt_var=C + export $lt_var + lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" + lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + fi" +done +LC_ALL=C +LANGUAGE=C +export LANGUAGE LC_ALL + +$lt_unset CDPATH + + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + + + +: ${CP="cp -f"} +test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} +: ${Xsed="$SED -e 1s/^X//"} + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +exit_status=$EXIT_SUCCESS + +# Make sure IFS has a sensible default +lt_nl=' +' +IFS=" $lt_nl" + +dirname="s,/[^/]*$,," +basename="s,^.*/,," + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} # func_dirname may be replaced by extended shell implementation + + +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "${1}" | $SED "$basename"` +} # func_basename may be replaced by extended shell implementation + + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi + func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` +} # func_dirname_and_basename may be replaced by extended shell implementation + + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname may be replaced by extended shell implementation + + +# These SED scripts presuppose an absolute path with a trailing slash. +pathcar='s,^/\([^/]*\).*$,\1,' +pathcdr='s,^/[^/]*,,' +removedotparts=':dotsl + s@/\./@/@g + t dotsl + s,/\.$,/,' +collapseslashes='s@/\{1,\}@/@g' +finalslash='s,/*$,/,' + +# func_normal_abspath PATH +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +# value returned in "$func_normal_abspath_result" +func_normal_abspath () +{ + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` + while :; do + # Processed it all yet? + if test "$func_normal_abspath_tpath" = / ; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result" ; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + +# func_relative_path SRCDIR DSTDIR +# generates a relative path from SRCDIR to DSTDIR, with a trailing +# slash if non-empty, suitable for immediately appending a filename +# without needing to append a separator. +# value returned in "$func_relative_path_result" +func_relative_path () +{ + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=${func_dirname_result} + if test "x$func_relative_path_tlibdir" = x ; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test "x$func_stripname_result" != x ; then + func_relative_path_result=${func_relative_path_result}/${func_stripname_result} + fi + + # Normalisation. If bindir is libdir, return empty string, + # else relative path ending with a slash; either way, target + # file name can be directly appended. + if test ! -z "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result/" + func_relative_path_result=$func_stripname_result + fi +} + +# The name of this program: +func_dirname_and_basename "$progpath" +progname=$func_basename_result + +# Make sure we have an absolute path for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=$func_dirname_result + progdir=`cd "$progdir" && pwd` + progpath="$progdir/$progname" + ;; + *) + save_IFS="$IFS" + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS="$save_IFS" + test -x "$progdir/$progname" && break + done + IFS="$save_IFS" + test -n "$progdir" || progdir=`pwd` + progpath="$progdir/$progname" + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed="${SED}"' -e 1s/^X//' +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' + +# Sed substitution that converts a w32 file name or path +# which contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-`\' parameter expansions in output of double_quote_subst that were +# `\'-ed in input to the same. If an odd number of `\' preceded a '$' +# in input to double_quote_subst, that '$' was protected from expansion. +# Since each input `\' is now two `\'s, look for any number of runs of +# four `\'s followed by two `\'s and then a '$'. `\' that '$'. +bs='\\' +bs2='\\\\' +bs4='\\\\\\\\' +dollar='\$' +sed_double_backslash="\ + s/$bs4/&\\ +/g + s/^$bs2$dollar/$bs&/ + s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g + s/\n//g" + +# Standard options: +opt_dry_run=false +opt_help=false +opt_quiet=false +opt_verbose=false +opt_warning=: + +# func_echo arg... +# Echo program name prefixed message, along with the current mode +# name if it has been set yet. +func_echo () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }$*" +} + +# func_verbose arg... +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $opt_verbose && func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +# func_error arg... +# Echo program name prefixed message to standard error. +func_error () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 +} + +# func_warning arg... +# Echo program name prefixed warning message to standard error. +func_warning () +{ + $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 + + # bash bug again: + : +} + +# func_fatal_error arg... +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + +# func_fatal_help arg... +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + func_error ${1+"$@"} + func_fatal_error "$help" +} +help="Try \`$progname --help' for more information." ## default + + +# func_grep expression filename +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_mkdir_p directory-path +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + my_directory_path="$1" + my_dir_list= + + if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then + + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$my_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + my_dir_list="$my_directory_path:$my_dir_list" + + # If the last portion added has no slash in it, the list is done + case $my_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` + done + my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` + + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$my_dir" 2>/dev/null || : + done + IFS="$save_mkdir_p_IFS" + + # Bail out if we (or some other process) failed to create a directory. + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" + fi +} + + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$opt_dry_run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || \ + func_fatal_error "cannot create temporary directory \`$my_tmpdir'" + fi + + $ECHO "$my_tmpdir" +} + + +# func_quote_for_eval arg +# Aesthetically quote ARG to be evaled later. +# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT +# is double-quoted, suitable for a subsequent eval, whereas +# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters +# which are still active within double quotes backslashified. +func_quote_for_eval () +{ + case $1 in + *[\\\`\"\$]*) + func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; + *) + func_quote_for_eval_unquoted_result="$1" ;; + esac + + case $func_quote_for_eval_unquoted_result in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and and variable + # expansion for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" + ;; + *) + func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" + esac +} + + +# func_quote_for_expand arg +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + case $1 in + *[\\\`\"]*) + my_arg=`$ECHO "$1" | $SED \ + -e "$double_quote_subst" -e "$sed_double_backslash"` ;; + *) + my_arg="$1" ;; + esac + + case $my_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + my_arg="\"$my_arg\"" + ;; + esac + + func_quote_for_expand_result="$my_arg" +} + + +# func_show_eval cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$my_cmd" + my_status=$? + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + +# func_show_eval_locale cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$lt_user_locale + $my_cmd" + my_status=$? + eval "$lt_safe_locale" + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + +# func_tr_sh +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_version +# Echo version message to standard output and exit. +func_version () +{ + $opt_debug + + $SED -n '/(C)/!b go + :more + /\./!{ + N + s/\n# / / + b more + } + :go + /^# '$PROGRAM' (GNU /,/# warranty; / { + s/^# // + s/^# *$// + s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ + p + }' < "$progpath" + exit $? +} + +# func_usage +# Echo short help message to standard output and exit. +func_usage () +{ + $opt_debug + + $SED -n '/^# Usage:/,/^# *.*--help/ { + s/^# // + s/^# *$// + s/\$progname/'$progname'/ + p + }' < "$progpath" + echo + $ECHO "run \`$progname --help | more' for full usage" + exit $? +} + +# func_help [NOEXIT] +# Echo long help message to standard output and exit, +# unless 'noexit' is passed as argument. +func_help () +{ + $opt_debug + + $SED -n '/^# Usage:/,/# Report bugs to/ { + :print + s/^# // + s/^# *$// + s*\$progname*'$progname'* + s*\$host*'"$host"'* + s*\$SHELL*'"$SHELL"'* + s*\$LTCC*'"$LTCC"'* + s*\$LTCFLAGS*'"$LTCFLAGS"'* + s*\$LD*'"$LD"'* + s/\$with_gnu_ld/'"$with_gnu_ld"'/ + s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ + s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ + p + d + } + /^# .* home page:/b print + /^# General help using/b print + ' < "$progpath" + ret=$? + if test -z "$1"; then + exit $ret + fi +} + +# func_missing_arg argname +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $opt_debug + + func_error "missing argument for $1." + exit_cmd=exit +} + + +# func_split_short_opt shortopt +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +func_split_short_opt () +{ + my_sed_short_opt='1s/^\(..\).*$/\1/;q' + my_sed_short_rest='1s/^..\(.*\)$/\1/;q' + + func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` + func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` +} # func_split_short_opt may be replaced by extended shell implementation + + +# func_split_long_opt longopt +# Set func_split_long_opt_name and func_split_long_opt_arg shell +# variables after splitting LONGOPT at the `=' sign. +func_split_long_opt () +{ + my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' + my_sed_long_arg='1s/^--[^=]*=//' + + func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` + func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` +} # func_split_long_opt may be replaced by extended shell implementation + +exit_cmd=: + + + + + +magic="%%%MAGIC variable%%%" +magic_exe="%%%MAGIC EXE variable%%%" + +# Global variables. +nonopt= +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "${1}=\$${1}\${2}" +} # func_append may be replaced by extended shell implementation + +# func_append_quoted var value +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +func_append_quoted () +{ + func_quote_for_eval "${2}" + eval "${1}=\$${1}\\ \$func_quote_for_eval_result" +} # func_append_quoted may be replaced by extended shell implementation + + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=`expr "${@}"` +} # func_arith may be replaced by extended shell implementation + + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` +} # func_len may be replaced by extended shell implementation + + +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` +} # func_lo2o may be replaced by extended shell implementation + + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` +} # func_xform may be replaced by extended shell implementation + + +# func_fatal_configuration arg... +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func_error ${1+"$@"} + func_error "See the $PACKAGE documentation for more information." + func_fatal_error "Fatal configuration error." +} + + +# func_config +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + +# func_features +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test "$build_libtool_libs" = yes; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + +# func_enable_tag tagname +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname="$1" + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf="/$re_begincf/,/$re_endcf/p" + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + +# func_check_version_match +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# Shorthand for --mode=foo, only valid as the first argument +case $1 in +clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; +compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; +execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; +finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; +install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; +link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; +uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; +esac + + + +# Option defaults: +opt_debug=: +opt_dry_run=false +opt_config=false +opt_preserve_dup_deps=false +opt_features=false +opt_finish=false +opt_help=false +opt_help_all=false +opt_silent=: +opt_warning=: +opt_verbose=: +opt_silent=false +opt_verbose=false + + +# Parse options once, thoroughly. This comes as soon as possible in the +# script to make things like `--version' happen as quickly as we can. +{ + # this just eases exit handling + while test $# -gt 0; do + opt="$1" + shift + case $opt in + --debug|-x) opt_debug='set -x' + func_echo "enabling shell trace mode" + $opt_debug + ;; + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + --config) + opt_config=: +func_config + ;; + --dlopen|-dlopen) + optarg="$1" + opt_dlopen="${opt_dlopen+$opt_dlopen +}$optarg" + shift + ;; + --preserve-dup-deps) + opt_preserve_dup_deps=: + ;; + --features) + opt_features=: +func_features + ;; + --finish) + opt_finish=: +set dummy --mode finish ${1+"$@"}; shift + ;; + --help) + opt_help=: + ;; + --help-all) + opt_help_all=: +opt_help=': help-all' + ;; + --mode) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_mode="$optarg" +case $optarg in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $opt" + exit_cmd=exit + break + ;; +esac + shift + ;; + --no-silent|--no-quiet) + opt_silent=false +func_append preserve_args " $opt" + ;; + --no-warning|--no-warn) + opt_warning=false +func_append preserve_args " $opt" + ;; + --no-verbose) + opt_verbose=false +func_append preserve_args " $opt" + ;; + --silent|--quiet) + opt_silent=: +func_append preserve_args " $opt" + opt_verbose=false + ;; + --verbose|-v) + opt_verbose=: +func_append preserve_args " $opt" +opt_silent=false + ;; + --tag) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_tag="$optarg" +func_append preserve_args " $opt $optarg" +func_enable_tag "$optarg" + shift + ;; + + -\?|-h) func_usage ;; + --help) func_help ;; + --version) func_version ;; + + # Separate optargs to long options: + --*=*) + func_split_long_opt "$opt" + set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-n*|-v*) + func_split_short_opt "$opt" + set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognized option \`$opt'" ;; + *) set dummy "$opt" ${1+"$@"}; shift; break ;; + esac + done + + # Validate options: + + # save first non-option argument + if test "$#" -gt 0; then + nonopt="$opt" + shift + fi + + # preserve --debug + test "$opt_debug" = : || func_append preserve_args " --debug" + + case $host in + *cygwin* | *mingw* | *pw32* | *cegcc*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + func_fatal_configuration "not configured to build any kind of library" + fi + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test "$opt_mode" != execute; then + func_error "unrecognized option \`-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$progname --help --mode=$opt_mode' for more information." + } + + + # Bail if the options were screwed + $exit_cmd $EXIT_FAILURE +} + + + + +## ----------- ## +## Main. ## +## ----------- ## + +# func_lalib_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null \ + | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if `file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case "$lalib_p_line" in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test "$lalib_p" = yes +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + func_lalib_p "$1" +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $opt_debug + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$save_ifs + eval cmd=\"$cmd\" + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# `FILE.' does not work on cygwin managed mounts. +func_source () +{ + $opt_debug + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case "$lt_sysroot:$1" in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result="=$func_stripname_result" + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $opt_debug + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with \`--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=${1} + if test "$build_libtool_libs" = yes; then + write_lobj=\'${2}\' + else + write_lobj=none + fi + + if test "$build_old_libs" = yes; then + write_oldobj=\'${3}\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$lt_sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $opt_debug + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result="" + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result" ; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $opt_debug + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $opt_debug + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $opt_debug + if test -z "$2" && test -n "$1" ; then + func_error "Could not determine host file name corresponding to" + func_error " \`$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result="$1" + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $opt_debug + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " \`$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result="$3" + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $opt_debug + case $4 in + $1 ) func_to_host_path_result="$3$func_to_host_path_result" + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via `$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $opt_debug + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $opt_debug + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result="$1" +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result="$func_convert_core_msys_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via `$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $opt_debug + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd="func_convert_path_${func_stripname_result}" + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $opt_debug + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result="$1" +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_msys_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result="$func_cygpath_result" + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result="$func_cygpath_result" + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_mode_compile arg... +func_mode_compile () +{ + $opt_debug + # Get the compilation command and the source file. + base_compile= + srcfile="$nonopt" # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg="$arg" + arg_mode=normal + ;; + + target ) + libobj="$arg" + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify \`-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + func_append_quoted lastarg "$arg" + done + IFS="$save_ifs" + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg="$srcfile" + srcfile="$arg" + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with \`-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj="$func_basename_result" + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from \`$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name \`$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname="$func_basename_result" + xdir="$func_dirname_result" + lobj=${xdir}$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test "$suppress_opt" = yes; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test "$compiler_c_o" = yes; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test "$opt_mode" = compile && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a \`.o' file suitable for static linking + -static only build a \`.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode \`$opt_mode'" + ;; + esac + + echo + $ECHO "Try \`$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test "$opt_help" = :; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | sed -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + sed '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $opt_debug + # The first argument is the command name. + cmd="$nonopt" + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "\`$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "\`$file' was not linked with \`-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir="$func_dirname_result" + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir="$func_dirname_result" + ;; + + *) + func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file="$progdir/$program" + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if test "X$opt_dry_run" = Xfalse; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + fi +} + +test "$opt_mode" = execute && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $opt_debug + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "\`$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument \`$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and \`=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_silent && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test "$opt_mode" = finish && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $opt_debug + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac; then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test "x$prev" = x-m && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the \`$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir="$func_dirname_result" + destname="$func_basename_result" + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "\`$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "\`$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir="$func_dirname_result" + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking \`$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname="$1" + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme="$stripme" + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme="" + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name="$func_basename_result" + instname="$dir/$name"i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to \`$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script \`$wrapper'" + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "\`$lib' has not been installed in \`$libdir'" + finalize=no + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + $opt_dry_run || { + if test "$finalize" = yes; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file="$func_basename_result" + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_silent || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink \`$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file="$outputname" + else + func_warning "cannot relink \`$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name="$func_basename_result" + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run \`$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test "$opt_mode" = install && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $opt_debug + my_outputname="$1" + my_originator="$2" + my_pic_p="${3-no}" + my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms="${my_outputname}S.c" + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${my_outputname}.nm" + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + func_verbose "generating symbol list for \`$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $opt_dry_run || { + $RM $export_symbols + eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from \`$dlprefile'" + func_basename "$dlprefile" + name="$func_basename_result" + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename="" + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname" ; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename="$func_basename_result" + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename" ; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[]; +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{\ + { \"$my_originator\", (void *) 0 }," + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + if test "X$my_pic_p" != Xno; then + pic_flag_for_symtable=" $pic_flag" + fi + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' + + # Transform the symbol file into the correct name. + symfileobj="$output_objdir/${my_outputname}S.$objext" + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for \`$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $opt_debug + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s,.*,import, + p + q + } + }'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $opt_debug + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $opt_debug + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive which possess that section. Heuristic: eliminate + # all those which have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $opt_debug + if func_cygming_gnu_implib_p "$1" ; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1" ; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result="" + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $opt_debug + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + if test "$lock_old_archive_extraction" = yes; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test "$lock_old_archive_extraction" = yes; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $opt_debug + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib="$func_basename_result" + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir="$my_gentop/$my_xlib_u" + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`basename "$darwin_archive"` + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result="$my_oldobjs" +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory in which it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + 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 + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ which is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options which match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +/* declarations of non-ANSI functions */ +#if defined(__MINGW32__) +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined(__CYGWIN__) +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined (other platforms) ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined(_MSC_VER) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +# ifndef _INTPTR_T_DEFINED +# define _INTPTR_T_DEFINED +# define intptr_t int +# endif +#elif defined(__MINGW32__) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined(__CYGWIN__) +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined (other platforms) ... */ +#endif + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +#if defined(LT_DEBUGWRAPPER) +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp (str, pat) == 0) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + int len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + int orig_value_len = strlen (orig_value); + int add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + int len = strlen (new_value); + while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[len-1] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $opt_debug + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $opt_debug + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module="${wl}-single_module" + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir="$arg" + prev= + continue + ;; + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + test -f "$arg" \ + || func_fatal_error "symbol file \`$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file \`$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "\`-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between \`-L' and \`$1'" + else + func_fatal_error "need path for \`-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of \`$dir'" + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module="${wl}-multi_module" + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "\`-no-install' is ignored for $host" + func_warning "assuming \`-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-flto*|-fwhopr*|-fuse-linker-plugin) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the \`$prevarg' option requires an argument" + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname="$func_basename_result" + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + func_dirname "$output" "/" "" + output_objdir="$func_dirname_result$objdir" + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps ; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test "$linkmode,$pass" = "lib,link"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs="$tmp_deplibs" + fi + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test "$linkmode,$pass" = "lib,dlpreopen"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs="$dlprefiles" + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + func_warning "\`-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test "$linkmode" = lib; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + *.ltframework) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "\`-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + else + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + ;; + esac + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + + if test "$found" = yes || test -f "$lib"; then : + else + func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" + fi + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "\`$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + elif test "$linkmode" != prog && test "$linkmode" != lib; then + func_fatal_error "\`$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test "$prefer_static_libs" = yes || + test "$prefer_static_libs,$installed" = "built,no"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib="$l" + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + func_fatal_error "cannot -dlopen a convenience library: \`$lib'" + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of \`$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir="$ladir" + fi + ;; + esac + func_basename "$lib" + laname="$func_basename_result" + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library \`$lib' was moved." + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$lt_sysroot$libdir" + absdir="$lt_sysroot$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir" && test "$linkmode" = prog; then + func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" + fi + case "$host" in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { { test "$prefer_static_libs" = no || + test "$prefer_static_libs,$installed" = "built,yes"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath:" in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test "$installed" = no; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule="" + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule="$dlpremoduletest" + break + fi + done + if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then + echo + if test "$linkmode" = prog; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname="$1" + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc*) + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + func_basename "$soroot" + soname="$func_basename_result" + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from \`$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for \`$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$opt_mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we can not + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null ; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + elif test -n "$old_library"; then + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$absdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && + test "$hardcode_minus_L" != yes && + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$opt_mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system can not link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path="$deplib" ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of \`$dir'" + absdir="$dir" + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl" ; then + depdepl="$absdir/$objdir/$depdepl" + darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" + func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" + path= + fi + fi + ;; + *) + path="-L$absdir/$objdir" + ;; + esac + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "\`$deplib' seems to be moved" + + path="-L$absdir" + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test "$pass" = link; then + if test "$linkmode" = "prog"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + fi + if test "$linkmode" = prog || test "$linkmode" = lib; then + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "\`-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "\`-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test "$module" = no && \ + func_fatal_help "libtool library \`$output' must begin with \`lib'" + + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test "$dlself" != no && \ + func_warning "\`-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test "$#" -gt 1 && \ + func_warning "ignoring multiple \`-rpath's for a libtool library" + + install_libdir="$1" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "\`-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + shift + IFS="$save_ifs" + + test -n "$7" && \ + func_fatal_help "too many parameters to \`-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$1" + number_minor="$2" + number_revision="$3" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|qnx|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_minor" + lt_irix_increment=no + ;; + esac + ;; + no) + current="$1" + revision="$2" + age="$3" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT \`$current' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION \`$revision' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE \`$age' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE \`$age' is greater than the current interface number \`$current'" + func_fatal_error "\`$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current" + ;; + + irix | nonstopux) + if test "X$lt_irix_increment" = "Xno"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + func_append verstring ":${current}.0" + ;; + + qnx) + major=".$current" + versuffix=".$current" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + + *) + func_fatal_configuration "unknown library version type \`$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + func_warning "undefined symbols not allowed in $host shared libraries" + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + fi + + func_generate_dlsyms "$libname" "$libname" "yes" + func_append libobjs " $symfileobj" + test "X$libobjs" = "X " && libobjs= + + if test "$opt_mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test "X$deplibs_check_method" = "Xnone"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs="$new_libs" + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + # Remove ${wl} instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$opt_mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname="$1" + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols="$output_objdir/$libname.uexp" + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + if test "x`$SED 1q $export_symbols`" != xEXPORTS; then + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols="$export_symbols" + export_symbols= + always_export_symbols=yes + fi + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd1 in $cmds; do + IFS="$save_ifs" + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test "$try_normal_branch" = yes \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=${output_objdir}/${output_la}.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test "$compiler_needs_object" = yes && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$opt_mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then + output=${output_objdir}/${output_la}.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then + output=${output_objdir}/${output_la}.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test "$compiler_needs_object" = yes; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-${k}.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test "X$objlist" = X || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-${k}.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\${concat_cmds}$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + if ${skipped_export-false}; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + fi + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + if ${skipped_export-false}; then + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + fi + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "\`-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object \`$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec and hope we can get by with + # turning comma into space.. + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + else + gentop="$output_objdir/${obj}x" + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "\`-release' is ignored for programs" + + test "$preload" = yes \ + && test "$dlopen_support" = unknown \ + && test "$dlopen_self" = unknown \ + && test "$dlopen_self_static" = unknown && \ + func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test "$tagname" = CXX ; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " ${wl}-bind_at_load" + func_append finalize_command " ${wl}-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" "no" + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=yes + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=no + ;; + *cygwin* | *mingw* ) + if test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + *) + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + esac + if test "$wrappers_required" = no; then + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.${objext}"; then + func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' + fi + + exit $exit_status + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "\`$output' will be relinked during installation" + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host" ; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save $symfileobj" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + if test "$preload" = yes && test -f "$symfileobj"; then + func_append oldobjs " $symfileobj" + fi + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase="$func_basename_result" + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name="$func_basename_result" + func_resolve_sysroot "$deplib" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles="$newdlprefiles" + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test "x$bindir" != x ; + then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +{ test "$opt_mode" = link || test "$opt_mode" = relink; } && + func_mode_link ${1+"$@"} + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $opt_debug + RM="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=yes ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir="$func_dirname_result" + if test "X$dir" = X.; then + odir="$objdir" + else + odir="$dir/$objdir" + fi + func_basename "$file" + name="$func_basename_result" + test "$opt_mode" = uninstall && odir="$dir" + + # Remember odir for removal later, being careful to avoid duplicates + if test "$opt_mode" = clean; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case "$opt_mode" in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && + test "$pic_object" != none; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && + test "$non_pic_object" != none; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$opt_mode" = clean ; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + func_append rmfiles " $odir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && + func_mode_uninstall ${1+"$@"} + +test -z "$opt_mode" && { + help="$generic_help" + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode \`$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: +# vi:sw=2 + diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/autotools/missing b/java/leveldbjni/leveldbjni/src/main/native-package/autotools/missing new file mode 100755 index 00000000..9a556482 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/autotools/missing @@ -0,0 +1,330 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2012-01-06.18; # UTC + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +run=: +sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' +sed_minuso='s/.* -o \([^ ]*\).*/\1/p' + +# In the cases where this matters, 'missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case $1 in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle 'PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file 'aclocal.m4' + autoconf touch file 'configure' + autoheader touch file 'config.h.in' + autom4te touch the output file, or create a stub one + automake touch all 'Makefile.in' files + bison create 'y.tab.[ch]', if possible, from existing .[ch] + flex create 'lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create 'lex.yy.c', if possible, from existing .c + makeinfo touch the output file + yacc create 'y.tab.[ch]', if possible, from existing .[ch] + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# normalize program name to check for. +program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). This is about non-GNU programs, so use $1 not +# $program. +case $1 in + lex*|yacc*) + # Not GNU programs, they don't have --version. + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running '$TOOL --version' or '$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case $program in + aclocal*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified 'acinclude.m4' or '${configure_ac}'. You might want + to install the Automake and Perl packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified '${configure_ac}'. You might want to install the + Autoconf and GNU m4 packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified 'acconfig.h' or '${configure_ac}'. You might want + to install the Autoconf and GNU m4 packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case $f in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified 'Makefile.am', 'acinclude.m4' or '${configure_ac}'. + You might want to install the Automake and Perl packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te*) + echo 1>&2 "\ +WARNING: '$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get '$1' as part of Autoconf from any GNU + archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison*|yacc*) + echo 1>&2 "\ +WARNING: '$1' $msg. You should only need it if + you modified a '.y' file. You may need the Bison package + in order for those modifications to take effect. You can get + Bison from any GNU archive site." + rm -f y.tab.c y.tab.h + if test $# -ne 1; then + eval LASTARG=\${$#} + case $LASTARG in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if test ! -f y.tab.h; then + echo >y.tab.h + fi + if test ! -f y.tab.c; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex*|flex*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified a '.l' file. You may need the Flex package + in order for those modifications to take effect. You can get + Flex from any GNU archive site." + rm -f lex.yy.c + if test $# -ne 1; then + eval LASTARG=\${$#} + case $LASTARG in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if test ! -f lex.yy.c; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + Help2man package in order for those modifications to take + effect. You can get Help2man from any GNU archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit $? + fi + ;; + + makeinfo*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified a '.texi' or '.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy 'make' (AIX, + DU, IRIX). You might want to install the Texinfo package or + the GNU make package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n ' + /^@setfilename/{ + s/.* \([^ ]*\) *$/\1/ + p + q + }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + *) + echo 1>&2 "\ +WARNING: '$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the 'README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing '$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/configure b/java/leveldbjni/leveldbjni/src/main/native-package/configure new file mode 100755 index 00000000..733b6cdb --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/configure @@ -0,0 +1,18037 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for leveldbjni 99-master-SNAPSHOT. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# 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=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# 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'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='leveldbjni' +PACKAGE_TARNAME='leveldbjni' +PACKAGE_VERSION='99-master-SNAPSHOT' +PACKAGE_STRING='leveldbjni 99-master-SNAPSHOT' +PACKAGE_BUGREPORT='' +PACKAGE_URL='' + +ac_unique_file="src/leveldbjni.cpp" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +MKDIR_P +INSTALL_STRIP_PROGRAM +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +OSX_VERSION +OSX_SDKS_DIR +JNI_EXTRA_LDFLAGS +JNI_EXTRA_CFLAGS +JNI_JDK +CXXCPP +CPP +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +AWK +RANLIB +STRIP +ac_ct_AR +AR +DLLTOOL +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +EGREP +GREP +SED +ac_ct_CC +CFLAGS +CC +LIBTOOL +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +OBJEXT +EXEEXT +ac_ct_CXX +CPPFLAGS +LDFLAGS +CXXFLAGS +CXX +target_os +target_vendor +target_cpu +target +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_static +enable_shared +with_pic +enable_fast_install +with_gnu_ld +with_sysroot +enable_libtool_lock +with_jni_jdk +with_leveldb +with_snappy +with_osxsdk +with_universal +' + ac_precious_vars='build_alias +host_alias +target_alias +CXX +CXXFLAGS +LDFLAGS +LIBS +CPPFLAGS +CCC +CC +CFLAGS +CPP +CXXCPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures leveldbjni 99-master-SNAPSHOT to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/leveldbjni] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of leveldbjni 99-master-SNAPSHOT:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-static[=PKGS] build static libraries [default=no] + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + both] + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot=DIR Search for dependent libraries within DIR + (or the compiler's sysroot if not specified). + --with-jni-jdk=PATH Location of the Java Development Kit. Defaults to + your JAVA_HOME setting and falls back to where it is + typically installed on your OS + --with-leveldb[=PATH] Directory where leveldb was built. Example: + --with-leveldb=/opt/leveldb + --with-snappy[=PATH] Directory where snappy was built. Example: + --with-snappy=/opt/snappy + --with-osxsdk[=VERSION] OS X SDK version to build against. Example: + --with-osxsdk=10.6 + --with-universal[=ARCH] Build a universal binary. Set to a space separated + architecture list. Pick from: i386, x86_64, ppc, + and/or ppc64. [default="i386 x86_64"] + +Some influential environment variables: + CXX C++ compiler command + 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 (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CC C compiler command + CFLAGS C compiler flags + CPP C preprocessor + CXXCPP C++ preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +leveldbjni configure 99-master-SNAPSHOT +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* 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 $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_cxx_try_cpp LINENO +# ------------------------ +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_cpp + +# ac_fn_cxx_try_link LINENO +# ------------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_link + +# ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES +# --------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_cxx_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_header_mongrel +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by leveldbjni $as_me 99-master-SNAPSHOT, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_aux_dir= +for ac_dir in autotools "$srcdir"/autotools; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in autotools \"$srcdir\"/autotools" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + + +ac_config_headers="$ac_config_headers src/config.h" + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 +$as_echo_n "checking target system type... " >&6; } +if ${ac_cv_target+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$target_alias" = x; then + ac_cv_target=$ac_cv_host +else + ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 +$as_echo "$ac_cv_target" >&6; } +case $ac_cv_target in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; +esac +target=$ac_cv_target +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_target +shift +target_cpu=$1 +target_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +target_os=$* +IFS=$ac_save_IFS +case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + + +## ----------------------------------------------- +## Application Checks +## ----------------------------------------------- +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5 +$as_echo_n "checking whether the C++ compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# 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 '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C++ compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5 +$as_echo_n "checking for C++ compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C++ compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if ${ac_cv_cxx_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if ${ac_cv_prog_cxx_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$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. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.2' +macro_revision='1.3337' + + + + + + + + + + + + + +ltmain="$ac_aux_dir/ltmain.sh" + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case "$ECHO" in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$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 + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + 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" + as_fn_executable_p "$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 +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + 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" + as_fn_executable_p "$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 +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 +$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 +$as_echo "$xsi_shell" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 +$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } +lt_shell_append=no +( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 +$as_echo "$lt_shell_append" >&6; } + + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test "$GCC" != yes; then + reload_cmds=false + fi + ;; + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. + if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 +$as_echo "${with_sysroot}" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD="${LD-ld}_sol2" + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test $_lt_result -eq 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[012]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + +func_stripname_cnf () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname_cnf + + + + + +# Set options +# Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=no +fi + + + + + + + + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for lt_pkg in $withval; do + IFS="$lt_save_ifs" + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + pic_mode=default +fi + + +test -z "$pic_mode" && pic_mode=default + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC="$CC" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -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:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $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. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test "$GCC" = yes; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -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:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $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. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test x"$lt_cv_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test x"$lt_cv_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -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:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $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 + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -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:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $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 + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='${wl}--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + export_dynamic_flag_spec='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test x"$lt_cv_prog_compiler__b" = xyes; then + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test "$lt_cv_irix_exported_symbol" = yes; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='${wl}-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test "$ld_shlibs" = no && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([A-Za-z]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test "$hardcode_action" = relink || + test "$inherit_rpath" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* 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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* 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 shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* 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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* 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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* 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 dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report which library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } +if test -z "$CXXCPP"; then + if ${ac_cv_prog_CXXCPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +else + _lt_caught_CXX_error=yes +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +archive_cmds_need_lc_CXX=no +allow_undefined_flag_CXX= +always_export_symbols_CXX=no +archive_expsym_cmds_CXX= +compiler_needs_object_CXX=no +export_dynamic_flag_spec_CXX= +hardcode_direct_CXX=no +hardcode_direct_absolute_CXX=no +hardcode_libdir_flag_spec_CXX= +hardcode_libdir_separator_CXX= +hardcode_minus_L_CXX=no +hardcode_shlibpath_var_CXX=unsupported +hardcode_automatic_CXX=no +inherit_rpath_CXX=no +module_cmds_CXX= +module_expsym_cmds_CXX= +link_all_deplibs_CXX=unknown +old_archive_cmds_CXX=$old_archive_cmds +reload_flag_CXX=$reload_flag +reload_cmds_CXX=$reload_cmds +no_undefined_flag_CXX= +whole_archive_flag_spec_CXX= +enable_shared_with_static_runtimes_CXX=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +objext_CXX=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_caught_CXX_error" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + + # save warnings/boilerplate of simple test code + ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + + ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + compiler_CXX=$CC + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` + + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test "$GXX" = yes; then + lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' + else + lt_prog_compiler_no_builtin_flag_CXX= + fi + + if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_CXX= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + ld_shlibs_CXX=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_CXX='' + hardcode_direct_CXX=yes + hardcode_direct_absolute_CXX=yes + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + file_list_spec_CXX='${wl}-f,' + + if test "$GXX" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct_CXX=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_CXX=yes + hardcode_libdir_flag_spec_CXX='-L$libdir' + hardcode_libdir_separator_CXX= + fi + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + export_dynamic_flag_spec_CXX='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + always_export_symbols_CXX=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_CXX='-berok' + # Determine the default libpath from the value encoded in an empty + # executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath__CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath__CXX +fi + + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + + archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_CXX="-z nodefs" + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath__CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath__CXX +fi + + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_CXX=' ${wl}-bernotok' + allow_undefined_flag_CXX=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_CXX='$convenience' + fi + archive_cmds_need_lc_CXX=yes + # This is similar to how AIX traditionally builds its shared + # libraries. + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_CXX=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_CXX=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec_CXX=' ' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=yes + file_list_spec_CXX='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' + enable_shared_with_static_runtimes_CXX=yes + # Don't use ranlib + old_postinstall_cmds_CXX='chmod 644 $oldlib' + postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_CXX='-L$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-all-symbols' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=no + enable_shared_with_static_runtimes_CXX=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_CXX=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + + + archive_cmds_need_lc_CXX=no + hardcode_direct_CXX=no + hardcode_automatic_CXX=yes + hardcode_shlibpath_var_CXX=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec_CXX='' + fi + link_all_deplibs_CXX=yes + allow_undefined_flag_CXX="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds_CXX="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + if test "$lt_cv_apple_cc_single_mod" != "yes"; then + archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" + archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" + fi + + else + ld_shlibs_CXX=no + fi + + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + ld_shlibs_CXX=no + ;; + + freebsd-elf*) + archive_cmds_need_lc_CXX=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + ld_shlibs_CXX=yes + ;; + + gnu*) + ;; + + haiku*) + archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + link_all_deplibs_CXX=yes + ;; + + hpux9*) + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + export_dynamic_flag_spec_CXX='${wl}-E' + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + export_dynamic_flag_spec_CXX='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + ;; + *) + hardcode_direct_CXX=yes + hardcode_direct_absolute_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + interix[3-9]*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' + fi + fi + link_all_deplibs_CXX=yes + ;; + esac + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + inherit_rpath_CXX=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [1-5].* | *pgcpp\ [1-5].*) + prelink_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + old_archive_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + archive_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + archive_expsym_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + esac + + hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + hardcode_libdir_flag_spec_CXX='-R$libdir' + whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object_CXX=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + ld_shlibs_CXX=yes + ;; + + openbsd2*) + # C++ shared libraries are fairly broken + ld_shlibs_CXX=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + hardcode_direct_absolute_CXX=yes + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + export_dynamic_flag_spec_CXX='${wl}-E' + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + ld_shlibs_CXX=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx*) + case $host in + osf3*) + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + ;; + *) + allow_undefined_flag_CXX=' -expect_unresolved \*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ + $RM $lib.exp' + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + ;; + esac + + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + case $host in + osf3*) + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + *) + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + esac + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + archive_cmds_need_lc_CXX=yes + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_shlibpath_var_CXX=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' + ;; + esac + link_all_deplibs_CXX=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + no_undefined_flag_CXX=' ${wl}-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_CXX='${wl}-z,text' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag_CXX='${wl}-z,text' + allow_undefined_flag_CXX='${wl}-z,nodefs' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-R,$libdir' + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + export_dynamic_flag_spec_CXX='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ + '"$old_archive_cmds_CXX" + reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ + '"$reload_cmds_CXX" + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 +$as_echo "$ld_shlibs_CXX" >&6; } + test "$ld_shlibs_CXX" = no && can_build_shared=no + + GCC_CXX="$GXX" + LD_CXX="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + # Dependencies to place before and after the object being linked: +predep_objects_CXX= +postdep_objects_CXX= +predeps_CXX= +postdeps_CXX= +compiler_lib_search_path_CXX= + +cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF + + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case ${prev}${p} in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" || + test $p = "-R"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test "$pre_test_object_deps_done" = no; then + case ${prev} in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$compiler_lib_search_path_CXX"; then + compiler_lib_search_path_CXX="${prev}${p}" + else + compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$postdeps_CXX"; then + postdeps_CXX="${prev}${p}" + else + postdeps_CXX="${postdeps_CXX} ${prev}${p}" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$predep_objects_CXX"; then + predep_objects_CXX="$p" + else + predep_objects_CXX="$predep_objects_CXX $p" + fi + else + if test -z "$postdep_objects_CXX"; then + postdep_objects_CXX="$p" + else + postdep_objects_CXX="$postdep_objects_CXX $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling CXX test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +case $host_os in +interix[3-9]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + predep_objects_CXX= + postdep_objects_CXX= + postdeps_CXX= + ;; + +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + if test "$solaris_use_stlport4" != yes; then + postdeps_CXX='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC* | sunCC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + postdeps_CXX='-library=Cstd -library=Crun' + fi + ;; + esac + ;; +esac + + +case " $postdeps_CXX " in +*" -lc "*) archive_cmds_need_lc_CXX=no ;; +esac + compiler_lib_search_dirs_CXX= +if test -n "${compiler_lib_search_path_CXX}"; then + compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lt_prog_compiler_wl_CXX= +lt_prog_compiler_pic_CXX= +lt_prog_compiler_static_CXX= + + + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic_CXX='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_CXX='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + lt_prog_compiler_pic_CXX= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static_CXX= + ;; + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_CXX=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic_CXX='-fPIC -shared' + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + else + case $host_os in + aix[4-9]*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + else + lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + ;; + dgux*) + case $cc_basename in + ec++*) + lt_prog_compiler_pic_CXX='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + lt_prog_compiler_pic_CXX='+Z' + fi + ;; + aCC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_CXX='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + lt_prog_compiler_wl_CXX='--backend -Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64 which still supported -KPIC. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + lt_prog_compiler_static_CXX='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fpic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-qpic' + lt_prog_compiler_static_CXX='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + lt_prog_compiler_pic_CXX='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic_CXX='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + lt_prog_compiler_wl_CXX='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + lt_prog_compiler_pic_CXX='-pic' + ;; + cxx*) + # Digital/Compaq C++ + lt_prog_compiler_wl_CXX='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + lt_prog_compiler_pic_CXX='-pic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + lcc*) + # Lucid + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + lt_prog_compiler_pic_CXX='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + lt_prog_compiler_can_build_shared_CXX=no + ;; + esac + fi + +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_CXX= + ;; + *) + lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; } +lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } +if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works_CXX=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -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:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $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. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works_CXX=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } + +if test x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; then + case $lt_prog_compiler_pic_CXX in + "" | " "*) ;; + *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; + esac +else + lt_prog_compiler_pic_CXX= + lt_prog_compiler_can_build_shared_CXX=no +fi + +fi + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works_CXX=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works_CXX=yes + fi + else + lt_cv_prog_compiler_static_works_CXX=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } + +if test x"$lt_cv_prog_compiler_static_works_CXX" = xyes; then + : +else + lt_prog_compiler_static_CXX= +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -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:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $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 + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -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:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $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 + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } + + + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + case $host_os in + aix[4-9]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global defined + # symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + export_symbols_cmds_CXX="$ltdll_cmds" + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + ;; + esac + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 +$as_echo "$ld_shlibs_CXX" >&6; } +test "$ld_shlibs_CXX" = no && can_build_shared=no + +with_gnu_ld_CXX=$with_gnu_ld + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_CXX" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_CXX=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_CXX in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_CXX + pic_flag=$lt_prog_compiler_pic_CXX + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_CXX + allow_undefined_flag_CXX= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc_CXX=no + else + lt_cv_archive_cmds_need_lc_CXX=yes + fi + allow_undefined_flag_CXX=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } + archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action_CXX= +if test -n "$hardcode_libdir_flag_spec_CXX" || + test -n "$runpath_var_CXX" || + test "X$hardcode_automatic_CXX" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$hardcode_direct_CXX" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" != no && + test "$hardcode_minus_L_CXX" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_CXX=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_CXX=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_CXX=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 +$as_echo "$hardcode_action_CXX" >&6; } + +if test "$hardcode_action_CXX" = relink || + test "$inherit_rpath_CXX" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test "$_lt_caught_CXX_error" != yes + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar lib "link -lib" + 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar lib "link -lib" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5 +$as_echo_n "checking the archiver ($AR) interface... " >&6; } +if ${am_cv_ar_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + am_cv_ar_interface=ar + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int some_variable = 0; +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 + (eval $am_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + am_cv_ar_interface=ar + else + am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 + (eval $am_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + am_cv_ar_interface=lib + else + am_cv_ar_interface=unknown + fi + fi + rm -f conftest.lib libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5 +$as_echo "$am_cv_ar_interface" >&6; } + +case $am_cv_ar_interface in +ar) + ;; +lib) + # Microsoft lib, so override with the ar-lib wrapper script. + # FIXME: It is wrong to rewrite AR. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__AR in this case, + # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something + # similar. + AR="$am_aux_dir/ar-lib $AR" + ;; +unknown) + as_fn_error $? "could not determine $AR interface" "$LINENO" 5 + ;; +esac + + +## ----------------------------------------------- +## API Checks +## ----------------------------------------------- + + + +# Check whether --with-jni-jdk was given. +if test "${with_jni_jdk+set}" = set; then : + withval=$with_jni_jdk; + if test "$withval" = "no" || test "$withval" = "yes"; then + as_fn_error $? "--with-jni-jdk: PATH to JDK not supplied" "$LINENO" 5 + fi + + + __JNI_JDK_HOME="$withval" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if '$__JNI_JDK_HOME' is a JDK" >&5 +$as_echo_n "checking if '$__JNI_JDK_HOME' is a JDK... " >&6; } + # OSX had to be a little different. + case "$host_os" in + darwin*) __JNI_INCLUDE="$__JNI_JDK_HOME/Headers";; + *) __JNI_INCLUDE="$__JNI_JDK_HOME/include";; + esac + + if test -r "$__JNI_INCLUDE/jni.h"; then : + + + # Also include the os specific include dirs in the JNI_CFLAGS + __JNI_CFLAGS="-I$__JNI_INCLUDE" + case "$host_os" in + bsdi*) __JNI_INCLUDE_EXTRAS="bsdos";; + linux*) __JNI_INCLUDE_EXTRAS="linux genunix";; + osf*) __JNI_INCLUDE_EXTRAS="alpha";; + solaris*) __JNI_INCLUDE_EXTRAS="solaris";; + mingw*) __JNI_INCLUDE_EXTRAS="win32";; + cygwin*) __JNI_INCLUDE_EXTRAS="win32";; + *) __JNI_INCLUDE_EXTRAS="genunix";; + esac + + for f in $__JNI_INCLUDE_EXTRAS ; do + if test -d "$__JNI_INCLUDE/$f"; then + __JNI_CFLAGS="$__JNI_CFLAGS -I$__JNI_INCLUDE/$f" + fi + done + + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $__JNI_CFLAGS" + JNI_VERSION="1_2" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + + #ifndef JNI_VERSION_$JNI_VERSION + # error JNI version $JNI_VERSION is not supported. + #endif + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + + JNI_JDK=$"$__JNI_JDK_HOME" + JNI_EXTRA_CFLAGS="$__JNI_CFLAGS" + + + case $host_os in + darwin*) + JNI_EXTRA_LDFLAGS="-shrext .jnilib -dynamiclib" ;; + esac + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "JDK not found. Invalid --with-jni-jdk PATH" "$LINENO" 5 + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + CPPFLAGS="$saved_CPPFLAGS" + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "JDK not found. Invalid --with-jni-jdk PATH" "$LINENO" 5 + +fi + + +else + + + if test -n "$JAVA_HOME" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: JAVA_HOME was set, checking to see if it's a JDK we can use..." >&5 +$as_echo "$as_me: JAVA_HOME was set, checking to see if it's a JDK we can use..." >&6;} + + + __JNI_JDK_HOME="$JAVA_HOME" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if '$__JNI_JDK_HOME' is a JDK" >&5 +$as_echo_n "checking if '$__JNI_JDK_HOME' is a JDK... " >&6; } + # OSX had to be a little different. + case "$host_os" in + darwin*) __JNI_INCLUDE="$__JNI_JDK_HOME/Headers";; + *) __JNI_INCLUDE="$__JNI_JDK_HOME/include";; + esac + + if test -r "$__JNI_INCLUDE/jni.h"; then : + + + # Also include the os specific include dirs in the JNI_CFLAGS + __JNI_CFLAGS="-I$__JNI_INCLUDE" + case "$host_os" in + bsdi*) __JNI_INCLUDE_EXTRAS="bsdos";; + linux*) __JNI_INCLUDE_EXTRAS="linux genunix";; + osf*) __JNI_INCLUDE_EXTRAS="alpha";; + solaris*) __JNI_INCLUDE_EXTRAS="solaris";; + mingw*) __JNI_INCLUDE_EXTRAS="win32";; + cygwin*) __JNI_INCLUDE_EXTRAS="win32";; + *) __JNI_INCLUDE_EXTRAS="genunix";; + esac + + for f in $__JNI_INCLUDE_EXTRAS ; do + if test -d "$__JNI_INCLUDE/$f"; then + __JNI_CFLAGS="$__JNI_CFLAGS -I$__JNI_INCLUDE/$f" + fi + done + + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $__JNI_CFLAGS" + JNI_VERSION="1_2" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + + #ifndef JNI_VERSION_$JNI_VERSION + # error JNI version $JNI_VERSION is not supported. + #endif + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + + JNI_JDK=$"$__JNI_JDK_HOME" + JNI_EXTRA_CFLAGS="$__JNI_CFLAGS" + + + case $host_os in + darwin*) + JNI_EXTRA_LDFLAGS="-shrext .jnilib -dynamiclib" ;; + esac + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + CPPFLAGS="$saved_CPPFLAGS" + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + +fi + + fi + + __JNI_GUESS=`which javac` + if test -z "$JNI_JDK" && test -n "$__JNI_GUESS"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: javac was on your path, checking to see if it's part of a JDK we can use..." >&5 +$as_echo "$as_me: javac was on your path, checking to see if it's part of a JDK we can use..." >&6;} + # transitively resolve the symbolic links to javac + while file -h "$__JNI_GUESS" 2>/dev/null | grep " symbolic link to " >/dev/null; do + __JNI_LINK=$( file -h $__JNI_GUESS | sed 's/.*symbolic link to //' | sed "s/'$//" | sed 's/^`//' ) + __JNI_GUESS=$(cd $(dirname $__JNI_GUESS); cd $(dirname $__JNI_LINK); echo "$(pwd)/$(basename $__JNI_LINK)") + done + # move 2 dirs up to the home dir... + __JNI_GUESS=$(dirname $(dirname $__JNI_GUESS)) + + + __JNI_JDK_HOME="$__JNI_GUESS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if '$__JNI_JDK_HOME' is a JDK" >&5 +$as_echo_n "checking if '$__JNI_JDK_HOME' is a JDK... " >&6; } + # OSX had to be a little different. + case "$host_os" in + darwin*) __JNI_INCLUDE="$__JNI_JDK_HOME/Headers";; + *) __JNI_INCLUDE="$__JNI_JDK_HOME/include";; + esac + + if test -r "$__JNI_INCLUDE/jni.h"; then : + + + # Also include the os specific include dirs in the JNI_CFLAGS + __JNI_CFLAGS="-I$__JNI_INCLUDE" + case "$host_os" in + bsdi*) __JNI_INCLUDE_EXTRAS="bsdos";; + linux*) __JNI_INCLUDE_EXTRAS="linux genunix";; + osf*) __JNI_INCLUDE_EXTRAS="alpha";; + solaris*) __JNI_INCLUDE_EXTRAS="solaris";; + mingw*) __JNI_INCLUDE_EXTRAS="win32";; + cygwin*) __JNI_INCLUDE_EXTRAS="win32";; + *) __JNI_INCLUDE_EXTRAS="genunix";; + esac + + for f in $__JNI_INCLUDE_EXTRAS ; do + if test -d "$__JNI_INCLUDE/$f"; then + __JNI_CFLAGS="$__JNI_CFLAGS -I$__JNI_INCLUDE/$f" + fi + done + + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $__JNI_CFLAGS" + JNI_VERSION="1_2" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + + #ifndef JNI_VERSION_$JNI_VERSION + # error JNI version $JNI_VERSION is not supported. + #endif + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + + JNI_JDK=$"$__JNI_JDK_HOME" + JNI_EXTRA_CFLAGS="$__JNI_CFLAGS" + + + case $host_os in + darwin*) + JNI_EXTRA_LDFLAGS="-shrext .jnilib -dynamiclib" ;; + esac + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + CPPFLAGS="$saved_CPPFLAGS" + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + +fi + + +fi + + if test -z "$JNI_JDK"; then : + + case "$host_os" in + darwin*) __JNI_GUESS="/System/Library/Frameworks/JavaVM.framework";; + *) __JNI_GUESS="/usr";; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: Taking a guess as to where your OS installs the JDK by default..." >&5 +$as_echo "$as_me: Taking a guess as to where your OS installs the JDK by default..." >&6;} + + + __JNI_JDK_HOME="$__JNI_GUESS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if '$__JNI_JDK_HOME' is a JDK" >&5 +$as_echo_n "checking if '$__JNI_JDK_HOME' is a JDK... " >&6; } + # OSX had to be a little different. + case "$host_os" in + darwin*) __JNI_INCLUDE="$__JNI_JDK_HOME/Headers";; + *) __JNI_INCLUDE="$__JNI_JDK_HOME/include";; + esac + + if test -r "$__JNI_INCLUDE/jni.h"; then : + + + # Also include the os specific include dirs in the JNI_CFLAGS + __JNI_CFLAGS="-I$__JNI_INCLUDE" + case "$host_os" in + bsdi*) __JNI_INCLUDE_EXTRAS="bsdos";; + linux*) __JNI_INCLUDE_EXTRAS="linux genunix";; + osf*) __JNI_INCLUDE_EXTRAS="alpha";; + solaris*) __JNI_INCLUDE_EXTRAS="solaris";; + mingw*) __JNI_INCLUDE_EXTRAS="win32";; + cygwin*) __JNI_INCLUDE_EXTRAS="win32";; + *) __JNI_INCLUDE_EXTRAS="genunix";; + esac + + for f in $__JNI_INCLUDE_EXTRAS ; do + if test -d "$__JNI_INCLUDE/$f"; then + __JNI_CFLAGS="$__JNI_CFLAGS -I$__JNI_INCLUDE/$f" + fi + done + + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $__JNI_CFLAGS" + JNI_VERSION="1_2" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + + #ifndef JNI_VERSION_$JNI_VERSION + # error JNI version $JNI_VERSION is not supported. + #endif + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + + JNI_JDK=$"$__JNI_JDK_HOME" + JNI_EXTRA_CFLAGS="$__JNI_CFLAGS" + + + case $host_os in + darwin*) + JNI_EXTRA_LDFLAGS="-shrext .jnilib -dynamiclib" ;; + esac + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "JDK not found. Please use the --with-jni-jdk option" "$LINENO" 5 + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + CPPFLAGS="$saved_CPPFLAGS" + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "JDK not found. Please use the --with-jni-jdk option" "$LINENO" 5 + +fi + + +fi + +fi + + + + + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + ac_fn_cxx_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" +if test "x$ac_cv_header_pthread_h" = xyes; then : + +$as_echo "#define HAVE_PTHREAD_H 1" >>confdefs.h + +fi + + + + +# Check whether --with-leveldb was given. +if test "${with_leveldb+set}" = set; then : + withval=$with_leveldb; + CFLAGS="$CFLAGS -I${withval}/include" + CXXFLAGS="$CXXFLAGS -I${withval}/include" + + LDFLAGS="$LDFLAGS -lleveldb -L${withval}" + + +fi + + + ac_fn_cxx_check_header_mongrel "$LINENO" "leveldb/db.h" "ac_cv_header_leveldb_db_h" "$ac_includes_default" +if test "x$ac_cv_header_leveldb_db_h" = xyes; then : + +else + as_fn_error $? "cannot find headers for leveldb" "$LINENO" 5 +fi + + + + +# Check whether --with-snappy was given. +if test "${with_snappy+set}" = set; then : + withval=$with_snappy; + LDFLAGS="$LDFLAGS -lsnappy -L${withval}" + + +fi + + + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/errno.h" "ac_cv_header_sys_errno_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_errno_h" = xyes; then : + +$as_echo "#define HAVE_SYS_ERRNO_H 1" >>confdefs.h + +fi + + + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + case "$host_os" in + darwin*) + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking OS X SDK version" >&5 +$as_echo_n "checking OS X SDK version... " >&6; } + +# Check whether --with-osxsdk was given. +if test "${with_osxsdk+set}" = set; then : + withval=$with_osxsdk; + OSX_UNIVERSAL="$withval" + +else + + OSX_SDKS_DIR="" + OSX_VERSION="" + for v in 10.0 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 10.10 10.11 10.12; do + for location in "/Developer/SDKs" "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs" ; do + if test -z "${OSX_VERSION}" && test -d "${location}/MacOSX${v}.sdk" ; then + OSX_SDKS_DIR="${location}" + OSX_VERSION="${v}" + fi + done + done + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OSX_VERSION" >&5 +$as_echo "$OSX_VERSION" >&6; } + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build universal binaries" >&5 +$as_echo_n "checking whether to build universal binaries... " >&6; } + +# Check whether --with-universal was given. +if test "${with_universal+set}" = set; then : + withval=$with_universal; + if test "$withval" = "no"; then : + + OSX_UNIVERSAL="" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +elif test "$withval" = "yes"; then : + + OSX_UNIVERSAL="i386 x86_64" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, archs: $OSX_UNIVERSAL" >&5 +$as_echo "yes, archs: $OSX_UNIVERSAL" >&6; } + +else + + OSX_UNIVERSAL="$withval" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, archs: $OSX_UNIVERSAL" >&5 +$as_echo "yes, archs: $OSX_UNIVERSAL" >&6; } + +fi + +else + + OSX_UNIVERSAL="" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi + + + if test -n "$OSX_UNIVERSAL"; then : + + for i in $OSX_UNIVERSAL ; do + CFLAGS="-arch $i $CFLAGS" + CXXFLAGS="-arch $i $CXXFLAGS" + LDFLAGS="-arch $i $LDFLAGS" + done + + + for f in $__JNI_INCLUDE_EXTRAS ; do + if test -d "$__JNI_INCLUDE/$f"; then + __JNI_CFLAGS="$__JNI_CFLAGS -I$__JNI_INCLUDE/$f" + fi + done + + + CFLAGS="-isysroot ${OSX_SDKS_DIR}/MacOSX${OSX_VERSION}.sdk $CFLAGS" + CXXFLAGS="-isysroot ${OSX_SDKS_DIR}/MacOSX${OSX_VERSION}.sdk $CXXFLAGS" + LDFLAGS="-syslibroot,${OSX_SDKS_DIR}/MacOSX${OSX_VERSION}.sdk $LDFLAGS" + + + + +fi + ;; + esac + + +CFLAGS="$CFLAGS $JNI_EXTRA_CFLAGS" + +CXXFLAGS="$CXXFLAGS $JNI_EXTRA_CFLAGS" + +LDFLAGS="$LDFLAGS $JNI_EXTRA_LDFLAGS -release 99-master-SNAPSHOT" + + +## ----------------------------------------------------- +## Generate the files +## ----------------------------------------------------- +am__api_version='1.12' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='leveldbjni' + VERSION='99-master-SNAPSHOT' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + +ac_config_files="$ac_config_files Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# 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=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# 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'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by leveldbjni $as_me 99-master-SNAPSHOT, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +leveldbjni config.status 99-master-SNAPSHOT +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' +predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' +postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' +predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' +postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' +LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' +reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' +reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' +compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' +GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' +archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' +module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' +with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' +no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' +inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' +link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' +always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' +exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' +include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' +prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' +postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' +file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' +predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' +postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' +predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' +postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +nm_file_list_spec \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib \ +compiler_lib_search_dirs \ +predep_objects \ +postdep_objects \ +predeps \ +postdeps \ +compiler_lib_search_path \ +LD_CXX \ +reload_flag_CXX \ +compiler_CXX \ +lt_prog_compiler_no_builtin_flag_CXX \ +lt_prog_compiler_pic_CXX \ +lt_prog_compiler_wl_CXX \ +lt_prog_compiler_static_CXX \ +lt_cv_prog_compiler_c_o_CXX \ +export_dynamic_flag_spec_CXX \ +whole_archive_flag_spec_CXX \ +compiler_needs_object_CXX \ +with_gnu_ld_CXX \ +allow_undefined_flag_CXX \ +no_undefined_flag_CXX \ +hardcode_libdir_flag_spec_CXX \ +hardcode_libdir_separator_CXX \ +exclude_expsyms_CXX \ +include_expsyms_CXX \ +file_list_spec_CXX \ +compiler_lib_search_dirs_CXX \ +predep_objects_CXX \ +postdep_objects_CXX \ +predeps_CXX \ +postdeps_CXX \ +compiler_lib_search_path_CXX; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +sys_lib_dlsearch_path_spec \ +reload_cmds_CXX \ +old_archive_cmds_CXX \ +old_archive_from_new_cmds_CXX \ +old_archive_from_expsyms_cmds_CXX \ +archive_cmds_CXX \ +archive_expsym_cmds_CXX \ +module_cmds_CXX \ +module_expsym_cmds_CXX \ +export_symbols_cmds_CXX \ +prelink_cmds_CXX \ +postlink_cmds_CXX; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' +xsi_shell='$xsi_shell' +lt_shell_append='$lt_shell_append' + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile' + + + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "src/config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/config.h" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "libtool":C) + + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool 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. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +# The names of the tagged configurations supported by this script. +available_tags="CXX " + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and in which our libraries should be installed. +lt_sysroot=$lt_sysroot + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects=$lt_predep_objects +postdep_objects=$lt_postdep_objects +predeps=$lt_predeps +postdeps=$lt_postdeps + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path + +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain="$ac_aux_dir/ltmain.sh" + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + if test x"$xsi_shell" = xyes; then + sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ +func_dirname ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_basename ()$/,/^} # func_basename /c\ +func_basename ()\ +{\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ +func_dirname_and_basename ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ +func_stripname ()\ +{\ +\ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ +\ # positional parameters, so assign one to ordinary parameter first.\ +\ func_stripname_result=${3}\ +\ func_stripname_result=${func_stripname_result#"${1}"}\ +\ func_stripname_result=${func_stripname_result%"${2}"}\ +} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ +func_split_long_opt ()\ +{\ +\ func_split_long_opt_name=${1%%=*}\ +\ func_split_long_opt_arg=${1#*=}\ +} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ +func_split_short_opt ()\ +{\ +\ func_split_short_opt_arg=${1#??}\ +\ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ +} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ +func_lo2o ()\ +{\ +\ case ${1} in\ +\ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ +\ *) func_lo2o_result=${1} ;;\ +\ esac\ +} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_xform ()$/,/^} # func_xform /c\ +func_xform ()\ +{\ + func_xform_result=${1%.*}.lo\ +} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_arith ()$/,/^} # func_arith /c\ +func_arith ()\ +{\ + func_arith_result=$(( $* ))\ +} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_len ()$/,/^} # func_len /c\ +func_len ()\ +{\ + func_len_result=${#1}\ +} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + +fi + +if test x"$lt_shell_append" = xyes; then + sed -e '/^func_append ()$/,/^} # func_append /c\ +func_append ()\ +{\ + eval "${1}+=\\${2}"\ +} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ +func_append_quoted ()\ +{\ +\ func_quote_for_eval "${2}"\ +\ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ +} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 +$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} +fi + + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + + cat <<_LT_EOF >> "$ofile" + +# ### BEGIN LIBTOOL TAG CONFIG: CXX + +# The linker used to build libraries. +LD=$lt_LD_CXX + +# How to create reloadable object files. +reload_flag=$lt_reload_flag_CXX +reload_cmds=$lt_reload_cmds_CXX + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds_CXX + +# A language specific compiler. +CC=$lt_compiler_CXX + +# Is the compiler the GNU compiler? +with_gcc=$GCC_CXX + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_CXX + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_CXX + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_CXX + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_CXX + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object_CXX + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds_CXX +archive_expsym_cmds=$lt_archive_expsym_cmds_CXX + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds_CXX +module_expsym_cmds=$lt_module_expsym_cmds_CXX + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld_CXX + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_CXX + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_CXX + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct_CXX + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute_CXX + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L_CXX + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic_CXX + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath_CXX + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_CXX + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols_CXX + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_CXX + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_CXX + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_CXX + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds_CXX + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds_CXX + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec_CXX + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_CXX + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects=$lt_predep_objects_CXX +postdep_objects=$lt_postdep_objects_CXX +predeps=$lt_predeps_CXX +postdeps=$lt_postdeps_CXX + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_CXX + +# ### END LIBTOOL TAG CONFIG: CXX +_LT_EOF + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + +echo " + ($PACKAGE_NAME) version $PACKAGE_VERSION + Prefix.........: $prefix + C Compiler.....: $CC $CFLAGS + Linker.........: $LD $LDFLAGS $LIBS +" diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/license.txt b/java/leveldbjni/leveldbjni/src/main/native-package/license.txt new file mode 100644 index 00000000..8edd3759 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/license.txt @@ -0,0 +1,27 @@ +Copyright (c) 2011 FuseSource Corp. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of FuseSource Corp. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/m4/custom.m4 b/java/leveldbjni/leveldbjni/src/main/native-package/m4/custom.m4 new file mode 100644 index 00000000..f29e5805 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/m4/custom.m4 @@ -0,0 +1,63 @@ +dnl --------------------------------------------------------------------------- +dnl Copyright (C) 2011, FuseSource Corp. All rights reserved. +dnl +dnl http://fusesource.com +dnl +dnl Redistribution and use in source and binary forms, with or without +dnl modification, are permitted provided that the following conditions are +dnl met: +dnl +dnl * Redistributions of source code must retain the above copyright +dnl notice, this list of conditions and the following disclaimer. +dnl * Redistributions in binary form must reproduce the above +dnl copyright notice, this list of conditions and the following disclaimer +dnl in the documentation and/or other materials provided with the +dnl distribution. +dnl * Neither the name of FuseSource Corp. nor the names of its +dnl contributors may be used to endorse or promote products derived from +dnl this software without specific prior written permission. +dnl +dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +dnl --------------------------------------------------------------------------- + +AC_DEFUN([CUSTOM_M4_SETUP], +[ + AC_LANG_PUSH(C++) + + AC_CHECK_HEADER([pthread.h],[AC_DEFINE([HAVE_PTHREAD_H], [1], [Define to 1 if you have the header file.])]) + + AC_ARG_WITH([leveldb], + [AS_HELP_STRING([--with-leveldb@<:@=PATH@:>@], + [Directory where leveldb was built. Example: --with-leveldb=/opt/leveldb])], + [ + CFLAGS="$CFLAGS -I${withval}/include" + CXXFLAGS="$CXXFLAGS -I${withval}/include" + AC_SUBST(CXXFLAGS) + LDFLAGS="$LDFLAGS -lleveldb -L${withval}" + AC_SUBST(LDFLAGS) + ]) + + AC_CHECK_HEADER([leveldb/db.h],,AC_MSG_ERROR([cannot find headers for leveldb])) + + AC_ARG_WITH([snappy], + [AS_HELP_STRING([--with-snappy@<:@=PATH@:>@], + [Directory where snappy was built. Example: --with-snappy=/opt/snappy])], + [ + LDFLAGS="$LDFLAGS -lsnappy -L${withval}" + AC_SUBST(LDFLAGS) + ]) + + AC_CHECK_HEADER([sys/errno.h],[AC_DEFINE([HAVE_SYS_ERRNO_H], [1], [Define to 1 if you have the header file.])]) + + AC_LANG_POP() +]) \ No newline at end of file diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/m4/jni.m4 b/java/leveldbjni/leveldbjni/src/main/native-package/m4/jni.m4 new file mode 100644 index 00000000..511f297c --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/m4/jni.m4 @@ -0,0 +1,156 @@ +dnl --------------------------------------------------------------------------- +dnl Copyright (C) 2009-2011 FuseSource Corp. +dnl http://fusesource.com +dnl +dnl Licensed under the Apache License, Version 2.0 (the "License"); +dnl you may not use this file except in compliance with the License. +dnl You may obtain a copy of the License at +dnl +dnl http://www.apache.org/licenses/LICENSE-2.0 +dnl +dnl Unless required by applicable law or agreed to in writing, software +dnl distributed under the License is distributed on an "AS IS" BASIS, +dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +dnl See the License for the specific language governing permissions and +dnl limitations under the License. +dnl --------------------------------------------------------------------------- +dnl --------------------------------------------------------------------------- +dnl SYNOPSIS: +dnl +dnl WITH_JNI_JDK() +dnl +dnl Adds the --with-jni-jdk=PATH option. If not provided, it searches +dnl for the JDK in the default OS locations. +dnl +dnl This macro calls: +dnl AC_SUBST(JNI_JDK) +dnl AC_SUBST(JNI_EXTRA_CFLAGS) +dnl AC_SUBST(JNI_EXTRA_LDFLAGS) +dnl +dnl AUTHOR: Hiram Chrino +dnl --------------------------------------------------------------------------- + +AC_DEFUN([WITH_JNI_JDK], +[ + AC_PREREQ([2.61]) + AC_ARG_WITH(jni-jdk, + [AS_HELP_STRING([--with-jni-jdk=PATH], + [Location of the Java Development Kit. Defaults to your JAVA_HOME setting and falls back to where it is typically installed on your OS])], + [ + if test "$withval" = "no" || test "$withval" = "yes"; then + AC_MSG_ERROR([--with-jni-jdk: PATH to JDK not supplied]) + fi + CHECK_JNI_JDK([$withval], [], [AC_MSG_ERROR([JDK not found. Invalid --with-jni-jdk PATH])]) + ],[ + + if test -n "$JAVA_HOME" ; then + AC_MSG_NOTICE([JAVA_HOME was set, checking to see if it's a JDK we can use...]) + CHECK_JNI_JDK([$JAVA_HOME], [], []) + fi + + __JNI_GUESS=`which javac` + AS_IF(test -z "$JNI_JDK" && test -n "$__JNI_GUESS", [ + AC_MSG_NOTICE([javac was on your path, checking to see if it's part of a JDK we can use...]) + # transitively resolve the symbolic links to javac + while file -h "$__JNI_GUESS" 2>/dev/null | grep " symbolic link to " >/dev/null; do + __JNI_LINK=$( file -h $__JNI_GUESS | sed 's/.*symbolic link to //' | sed "s/'$//" | sed 's/^`//' ) + __JNI_GUESS=$(cd $(dirname $__JNI_GUESS); cd $(dirname $__JNI_LINK); echo "$(pwd)/$(basename $__JNI_LINK)") + done + # move 2 dirs up to the home dir... + __JNI_GUESS=$(dirname $(dirname $__JNI_GUESS)) + CHECK_JNI_JDK([$__JNI_GUESS], [], [],[]) + ],[]) + + AS_IF(test -z "$JNI_JDK", [ + case "$host_os" in + darwin*) __JNI_GUESS="/System/Library/Frameworks/JavaVM.framework";; + *) __JNI_GUESS="/usr";; + esac + AC_MSG_NOTICE([Taking a guess as to where your OS installs the JDK by default...]) + CHECK_JNI_JDK([$__JNI_GUESS], [], [AC_MSG_ERROR([JDK not found. Please use the --with-jni-jdk option])]) + ],[]) + ]) +]) + +dnl --------------------------------------------------------------------------- +dnl +dnl JNI_CHECK_JDK_HOME(PATH, [ACTION-SUCCESS], [ACTION-FAILURE]) +dnl +dnl Tests to see if the given path is a valid JDK home location with +dnl with a JNI headers and library that can be compiled against. +dnl +dnl This macro calls: +dnl +dnl AC_SUBST(JNI_JDK) +dnl AC_SUBST(JNI_EXTRA_CFLAGS) +dnl AC_SUBST(JNI_EXTRA_LDFLAGS) +dnl +dnl AUTHOR: Hiram Chrino +dnl --------------------------------------------------------------------------- +AC_DEFUN([CHECK_JNI_JDK],[ + AC_PREREQ([2.61]) + __JNI_JDK_HOME="$1" + AC_MSG_CHECKING(if '$__JNI_JDK_HOME' is a JDK) + # OSX had to be a little different. + case "$host_os" in + darwin*) __JNI_INCLUDE="$__JNI_JDK_HOME/Headers";; + *) __JNI_INCLUDE="$__JNI_JDK_HOME/include";; + esac + + AS_IF(test -r "$__JNI_INCLUDE/jni.h",[ + + # Also include the os specific include dirs in the JNI_CFLAGS + __JNI_CFLAGS="-I$__JNI_INCLUDE" + case "$host_os" in + bsdi*) __JNI_INCLUDE_EXTRAS="bsdos";; + linux*) __JNI_INCLUDE_EXTRAS="linux genunix";; + osf*) __JNI_INCLUDE_EXTRAS="alpha";; + solaris*) __JNI_INCLUDE_EXTRAS="solaris";; + mingw*) __JNI_INCLUDE_EXTRAS="win32";; + cygwin*) __JNI_INCLUDE_EXTRAS="win32";; + *) __JNI_INCLUDE_EXTRAS="genunix";; + esac + + for f in $__JNI_INCLUDE_EXTRAS ; do + if test -d "$__JNI_INCLUDE/$f"; then + __JNI_CFLAGS="$__JNI_CFLAGS -I$__JNI_INCLUDE/$f" + fi + done + + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $__JNI_CFLAGS" + JNI_VERSION="1_2" + AC_LANG_PUSH(C) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[@%:@include ]],[[ + #ifndef JNI_VERSION_$JNI_VERSION + # error JNI version $JNI_VERSION is not supported. + #endif + ]]) + ],[ + + JNI_JDK=$"$__JNI_JDK_HOME" + JNI_EXTRA_CFLAGS="$__JNI_CFLAGS" + AC_SUBST(JNI_JDK) + AC_SUBST(JNI_EXTRA_CFLAGS) + case $host_os in + darwin*) + JNI_EXTRA_LDFLAGS="-shrext .jnilib -dynamiclib" ;; + esac + AC_SUBST(JNI_EXTRA_LDFLAGS) + + + AC_MSG_RESULT([yes]) + $2 + ],[ + AC_MSG_RESULT([no]) + $3 + ]) + AC_LANG_POP() + CPPFLAGS="$saved_CPPFLAGS" + ],[ + AC_MSG_RESULT([no]) + $3 + ]) +]) + diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/m4/libtool.m4 b/java/leveldbjni/leveldbjni/src/main/native-package/m4/libtool.m4 new file mode 100644 index 00000000..44e0ecff --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/m4/libtool.m4 @@ -0,0 +1,7982 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool 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. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +]) + +# serial 57 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +m4_defun([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from `configure', and `config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# `config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain="$ac_aux_dir/ltmain.sh" +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the `libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to `config.status' so that its +# declaration there will have the same value as in `configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags="_LT_TAGS"dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the `libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into `config.status', and then the shell code to quote escape them in +# for loops in `config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# `#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test $lt_write_fail = 0 && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +\`$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test $[#] != 0 +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try \`$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try \`$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test "$silent" = yes && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +_LT_COPYING +_LT_LIBTOOL_TAGS + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + _LT_PROG_REPLACE_SHELLFNS + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test $_lt_result -eq 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS="$save_LDFLAGS" + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[[012]]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + m4_if([$1], [CXX], +[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script which will find a shell with a builtin +# printf (which we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case "$ECHO" in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[ --with-sysroot[=DIR] Search for dependent libraries within DIR + (or the compiler's sysroot if not specified).], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([${with_sysroot}]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and in which our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD="${LD-ld}_sol2" + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -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:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + 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. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test x"[$]$2" = xyes; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -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:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links="nottested" +if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", + [Define to the sub-directory in which libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || + test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([], [sys_lib_dlsearch_path_spec], [2], + [Run-time system search path for libraries]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program which can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program which can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi]) +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64 which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global defined + # symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS="$save_LDFLAGS"]) + if test "$lt_cv_irix_exported_symbol" = yes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting ${shlibpath_var} if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report which library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC="$lt_save_CC" +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_caught_CXX_error" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared + # libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + gnu*) + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd2*) + # C++ shared libraries are fairly broken + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + + _LT_TAGVAR(GCC, $1)="$GXX" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test "$_lt_caught_CXX_error" != yes + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case ${prev}${p} in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" || + test $p = "-R"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test "$pre_test_object_deps_done" = no; then + case ${prev} in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)="${prev}${p}" + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)="$p" + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)="$p" + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; + +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC* | sunCC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test "X$F77" = "Xno"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_F77" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$G77" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC="$lt_save_CC" + CFLAGS="$lt_save_CFLAGS" +fi # test "$_lt_disable_F77" != yes + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test "X$FC" = "Xno"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_FC" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test "$_lt_disable_FC" != yes + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)="$LD" +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)="$LD" +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[AC_MSG_CHECKING([whether the shell understands some XSI constructs]) +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +AC_MSG_RESULT([$xsi_shell]) +_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) + +AC_MSG_CHECKING([whether the shell understands "+="]) +lt_shell_append=no +( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +AC_MSG_RESULT([$lt_shell_append]) +_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) +# ------------------------------------------------------ +# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and +# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. +m4_defun([_LT_PROG_FUNCTION_REPLACE], +[dnl { +sed -e '/^$1 ()$/,/^} # $1 /c\ +$1 ()\ +{\ +m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) +} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: +]) + + +# _LT_PROG_REPLACE_SHELLFNS +# ------------------------- +# Replace existing portable implementations of several shell functions with +# equivalent extended shell implementations where those features are available.. +m4_defun([_LT_PROG_REPLACE_SHELLFNS], +[if test x"$xsi_shell" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl + func_split_long_opt_name=${1%%=*} + func_split_long_opt_arg=${1#*=}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) + + _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) + + _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) + + _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) +fi + +if test x"$lt_shell_append" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) + + _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl + func_quote_for_eval "${2}" +dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ + eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) +fi +]) + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine which file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/m4/ltoptions.m4 b/java/leveldbjni/leveldbjni/src/main/native-package/m4/ltoptions.m4 new file mode 100644 index 00000000..5d9acd8e --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/m4/ltoptions.m4 @@ -0,0 +1,384 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 7 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option `$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl `shared' nor `disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the `shared' and +# `disable-shared' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the `static' and +# `disable-static' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the `fast-install' +# and `disable-fast-install' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the `pic-only' and `no-pic' +# LT_INIT options. +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for lt_pkg in $withval; do + IFS="$lt_save_ifs" + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [pic_mode=default]) + +test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/m4/ltsugar.m4 b/java/leveldbjni/leveldbjni/src/main/native-package/m4/ltsugar.m4 new file mode 100644 index 00000000..9000a057 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/m4/ltsugar.m4 @@ -0,0 +1,123 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59 which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/m4/ltversion.m4 b/java/leveldbjni/leveldbjni/src/main/native-package/m4/ltversion.m4 new file mode 100644 index 00000000..07a8602d --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/m4/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 3337 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.2]) +m4_define([LT_PACKAGE_REVISION], [1.3337]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.2' +macro_revision='1.3337' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/m4/lt~obsolete.m4 b/java/leveldbjni/leveldbjni/src/main/native-package/m4/lt~obsolete.m4 new file mode 100644 index 00000000..c573da90 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/m4/lt~obsolete.m4 @@ -0,0 +1,98 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/m4/osx-universal.m4 b/java/leveldbjni/leveldbjni/src/main/native-package/m4/osx-universal.m4 new file mode 100644 index 00000000..1b726bda --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/m4/osx-universal.m4 @@ -0,0 +1,115 @@ +dnl --------------------------------------------------------------------------- +dnl Copyright (C) 2009-2011 FuseSource Corp. +dnl http://fusesource.com +dnl +dnl Licensed under the Apache License, Version 2.0 (the "License"); +dnl you may not use this file except in compliance with the License. +dnl You may obtain a copy of the License at +dnl +dnl http://www.apache.org/licenses/LICENSE-2.0 +dnl +dnl Unless required by applicable law or agreed to in writing, software +dnl distributed under the License is distributed on an "AS IS" BASIS, +dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +dnl See the License for the specific language governing permissions and +dnl limitations under the License. +dnl --------------------------------------------------------------------------- +dnl --------------------------------------------------------------------------- +dnl SYNOPSIS: +dnl +dnl WITH_OSX_UNIVERSAL() +dnl +dnl Allows creating universal binaries on the +dnl +dnl Adds the --with-universal=ARCH option. This will will +dnl set -isysroot option to the location of the MacOSX${OSX_VERSION}.sdk. +dnl if OSX_VERSION is not defined, it will set it to the latest version +dnl of the SDK installed on your system. +dnl +dnl You must use the no-dependencies option when automake is initialized. +dnl for example: AM_INIT_AUTOMAKE([no-dependencies]) +dnl +dnl This macro calls: +dnl AC_SUBST(CFLAGS) +dnl AC_SUBST(CXXFLAGS) +dnl AC_SUBST(LDFLAGS) +dnl AC_SUBST(OSX_VERSION) +dnl +dnl AUTHOR: Hiram Chrino +dnl --------------------------------------------------------------------------- + +AC_DEFUN([WITH_OSX_UNIVERSAL], +[ + AC_PREREQ([2.61]) + case "$host_os" in + darwin*) + + AC_MSG_CHECKING(OS X SDK version) + AC_ARG_WITH([osxsdk], + [AS_HELP_STRING([--with-osxsdk@<:@=VERSION@:>@], + [OS X SDK version to build against. Example: --with-osxsdk=10.6])], + [ + OSX_UNIVERSAL="$withval" + ],[ + OSX_SDKS_DIR="" + OSX_VERSION="" + for v in 10.0 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 10.10 10.11 10.12; do + for location in "/Developer/SDKs" "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs" ; do + if test -z "${OSX_VERSION}" && test -d "${location}/MacOSX${v}.sdk" ; then + OSX_SDKS_DIR="${location}" + OSX_VERSION="${v}" + fi + done + done + ]) + AC_MSG_RESULT([$OSX_VERSION]) + AC_SUBST(OSX_SDKS_DIR) + AC_SUBST(OSX_VERSION) + + AC_MSG_CHECKING(whether to build universal binaries) + AC_ARG_WITH([universal], + [AS_HELP_STRING([--with-universal@<:@=ARCH@:>@], + [Build a universal binary. Set to a space separated architecture list. Pick from: i386, x86_64, ppc, and/or ppc64. @<:@default="i386 x86_64"@:>@])], + [ + AS_IF(test "$withval" = "no", [ + OSX_UNIVERSAL="" + AC_MSG_RESULT([no]) + ], test "$withval" = "yes", [ + OSX_UNIVERSAL="i386 x86_64" + AC_MSG_RESULT([yes, archs: $OSX_UNIVERSAL]) + ],[ + OSX_UNIVERSAL="$withval" + AC_MSG_RESULT([yes, archs: $OSX_UNIVERSAL]) + ]) + ],[ + OSX_UNIVERSAL="" + AC_MSG_RESULT([no]) + ]) + + AS_IF(test -n "$OSX_UNIVERSAL", [ + for i in $OSX_UNIVERSAL ; do + CFLAGS="-arch $i $CFLAGS" + CXXFLAGS="-arch $i $CXXFLAGS" + LDFLAGS="-arch $i $LDFLAGS" + done + + + for f in $__JNI_INCLUDE_EXTRAS ; do + if test -d "$__JNI_INCLUDE/$f"; then + __JNI_CFLAGS="$__JNI_CFLAGS -I$__JNI_INCLUDE/$f" + fi + done + + + CFLAGS="-isysroot ${OSX_SDKS_DIR}/MacOSX${OSX_VERSION}.sdk $CFLAGS" + CXXFLAGS="-isysroot ${OSX_SDKS_DIR}/MacOSX${OSX_VERSION}.sdk $CXXFLAGS" + LDFLAGS="-syslibroot,${OSX_SDKS_DIR}/MacOSX${OSX_VERSION}.sdk $LDFLAGS" + AC_SUBST(CFLAGS) + AC_SUBST(CXXFLAGS) + AC_SUBST(LDFLAGS) + ]) + ;; + esac +]) + + diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/src/buffer.c b/java/leveldbjni/leveldbjni/src/main/native-package/src/buffer.c new file mode 100644 index 00000000..c2beaf28 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/src/buffer.c @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ +#include "leveldbjni.h" + +void buffer_copy(const void *source, size_t source_pos, void *dest, size_t dest_pos, size_t length) { + memmove(((char *)dest)+dest_pos, ((const char *)source)+source_pos, length); +} diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/src/config.h.in b/java/leveldbjni/leveldbjni/src/main/native-package/src/config.h.in new file mode 100644 index 00000000..ba1af84c --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/src/config.h.in @@ -0,0 +1,68 @@ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PTHREAD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_ERRNO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/src/leveldbjni.h b/java/leveldbjni/leveldbjni/src/main/native-package/src/leveldbjni.h new file mode 100755 index 00000000..97740512 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/src/leveldbjni.h @@ -0,0 +1,142 @@ +/******************************************************************************* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ +#ifndef LEVELDBJNI_H +#define LEVELDBJNI_H + +#ifdef HAVE_CONFIG_H + /* configure based build.. we will use what it discovered about the platform */ + #include "config.h" +#else + #if defined(_WIN32) || defined(_WIN64) + /* Windows based build */ + #define HAVE_STDLIB_H 1 + #define HAVE_STRINGS_H 1 + #include + #endif +#endif + +#ifdef HAVE_UNISTD_H + #include +#endif + +#ifdef HAVE_STDLIB_H + #include +#endif + +#ifdef HAVE_STRINGS_H + #include +#endif + +#ifdef HAVE_SYS_ERRNO_H + #include +#endif + +#include "hawtjni.h" +#include +#include + +#ifdef __cplusplus + +#include "leveldb/db.h" +#include "leveldb/options.h" +#include "leveldb/write_batch.h" +#include "leveldb/cache.h" +#include "leveldb/comparator.h" +#include "leveldb/env.h" +#include "leveldb/slice.h" + +struct JNIComparator : public leveldb::Comparator { + jobject target; + jmethodID compare_method; + const char *name; + + int Compare(const leveldb::Slice& a, const leveldb::Slice& b) const { + JNIEnv *env; + if ( hawtjni_attach_thread(&env, "leveldb") ) { + return 0; + } + int rc = env->CallIntMethod(target, compare_method, (jlong)(intptr_t)&a, (jlong)(intptr_t)&b); + hawtjni_detach_thread(); + return rc; + } + + const char* Name() const { + return name; + } + + void FindShortestSeparator(std::string*, const leveldb::Slice&) const { } + void FindShortSuccessor(std::string*) const { } +}; + +struct JNILogger : public leveldb::Logger { + jobject target; + jmethodID log_method; + + void Logv(const char* format, va_list ap) { + JNIEnv *env; + if ( hawtjni_attach_thread(&env, "leveldb") ) { + return; + } + + char buffer[1024]; + vsnprintf(buffer, sizeof(buffer), format, ap); + + jstring message = env->NewStringUTF(buffer); + if( message ) { + env->CallVoidMethod(target, log_method, message); + env->DeleteLocalRef(message); + } + + if (env->ExceptionOccurred() ) { + env->ExceptionDescribe(); + env->ExceptionClear(); + } + hawtjni_detach_thread(); + } + +}; + +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +void buffer_copy(const void *source, size_t source_pos, void *dest, size_t dest_pos, size_t length); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* LEVELDBJNI_H */ diff --git a/java/leveldbjni/leveldbjni/src/main/native-package/vs2010.vcxproj b/java/leveldbjni/leveldbjni/src/main/native-package/vs2010.vcxproj new file mode 100755 index 00000000..3c59b4a8 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/native-package/vs2010.vcxproj @@ -0,0 +1,194 @@ + + + + + + debug + Win32 + + + debug + x64 + + + release + Win32 + + + release + x64 + + + + leveldbjni + leveldbjni + + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(ProjectDir)/target/$(Platform)-$(Configuration)/lib\ + $(ProjectDir)/target/$(Platform)-$(Configuration)/obj\ + false + $(ProjectDir)/target/$(Platform)-$(Configuration)/lib\ + $(ProjectDir)/target/$(Platform)-$(Configuration)/obj\ + false + $(ProjectDir)/target/$(Platform)-$(Configuration)/lib\ + $(ProjectDir)/target/$(Platform)-$(Configuration)/obj\ + true + $(ProjectDir)/target/$(Platform)-$(Configuration)/lib\ + $(ProjectDir)/target/$(Platform)-$(Configuration)/obj\ + true + + + + $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(ProjectDir)\src\windows;%(AdditionalIncludeDirectories) + MaxSpeed + true + Speed + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + Sync + MultiThreadedDLL + true + false + + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX86 + + + + + $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(ProjectDir)\src\windows;%(AdditionalIncludeDirectories) + MaxSpeed + true + Speed + WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + Sync + MultiThreadedDLL + true + false + + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX64 + + + + + $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(ProjectDir)\src\windows;%(AdditionalIncludeDirectories) + Disabled + Speed + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + Sync + EnableFastChecks + MultiThreadedDebugDLL + false + + + Level3 + EditAndContinue + + + true + Windows + MachineX86 + + + + + $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(ProjectDir)\src\windows;%(AdditionalIncludeDirectories) + Disabled + Speed + WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + Sync + EnableFastChecks + MultiThreadedDebugDLL + false + + + Level3 + EditAndContinue + + + true + Windows + MachineX64 + + + + + + + + + + + + SNAPPY;LEVELDB_PLATFORM_WINDOWS;OS_WIN;%(PreprocessorDefinitions) + $(LEVELDB_HOME);$(LEVELDB_HOME)\include;$(LEVELDB_HOME)\port\win;$(SNAPPY_HOME);%(AdditionalIncludeDirectories) + + + + + shlwapi.lib;$(LEVELDB_HOME)\Release\leveldb.lib;%(AdditionalDependencies) + + + + + shlwapi.lib;$(LEVELDB_HOME)\x64\Release\leveldb.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/java/leveldbjni/leveldbjni/src/main/resources/org/fusesource/leveldbjni/version.txt b/java/leveldbjni/leveldbjni/src/main/resources/org/fusesource/leveldbjni/version.txt new file mode 100644 index 00000000..f2ab45c3 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/main/resources/org/fusesource/leveldbjni/version.txt @@ -0,0 +1 @@ +${project.version} \ No newline at end of file diff --git a/java/leveldbjni/leveldbjni/src/test/java/org/fusesource/leveldbjni/test/DBTest.java b/java/leveldbjni/leveldbjni/src/test/java/org/fusesource/leveldbjni/test/DBTest.java new file mode 100644 index 00000000..4d4a45f4 --- /dev/null +++ b/java/leveldbjni/leveldbjni/src/test/java/org/fusesource/leveldbjni/test/DBTest.java @@ -0,0 +1,432 @@ +/* + * Copyright (C) 2011, FuseSource Corp. All rights reserved. + * + * http://fusesource.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of FuseSource Corp. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.fusesource.leveldbjni.test; + +import junit.framework.TestCase; +import org.fusesource.leveldbjni.JniDBFactory; +import org.fusesource.leveldbjni.internal.JniDB; +import org.iq80.leveldb.*; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.util.*; + +import static org.fusesource.leveldbjni.JniDBFactory.asString; +import static org.fusesource.leveldbjni.JniDBFactory.bytes; + +/** + * A Unit test for the DB class implementation. + * + * @author Hiram Chirino + */ +public class DBTest extends TestCase { + DBFactory factory = JniDBFactory.factory; + + File getTestDirectory(String name) throws IOException { + File rc = new File(new File("test-data"), name); + factory.destroy(rc, new Options().createIfMissing(true)); + rc.mkdirs(); + return rc; + } + + @Test + public void testOpen() throws IOException { + + Options options = new Options().createIfMissing(true); + + File path = getTestDirectory(getName()); + DB db = factory.open(path, options); + + db.close(); + + // Try again.. this time we expect a failure since it exists. + options = new Options().errorIfExists(true); + try { + factory.open(path, options); + fail("Expected exception."); + } catch (IOException e) { + } + + } + + @Test + public void testRepair() throws IOException, DBException { + testCRUD(); + factory.repair(new File(new File("test-data"), getName()), new Options()); + } + + @Test + public void testCRUD() throws IOException, DBException { + + Options options = new Options().createIfMissing(true); + + File path = getTestDirectory(getName()); + DB db = factory.open(path, options); + + WriteOptions wo = new WriteOptions().sync(false); + ReadOptions ro = new ReadOptions().fillCache(true).verifyChecksums(true); + + db.put(bytes("Tampa"), bytes("green")); + db.put(bytes("London"), bytes("red")); + db.put(bytes("New York"), bytes("blue")); + + assertEquals(db.get(bytes("Tampa"), ro), bytes("green")); + assertEquals(db.get(bytes("London"), ro), bytes("red")); + assertEquals(db.get(bytes("New York"), ro), bytes("blue")); + + db.delete(bytes("New York"), wo); + assertNull(db.get(bytes("New York"), ro)); + + // leveldb does not consider deleting something that does not exist an error. + db.delete(bytes("New York"), wo); + + db.close(); + } + + @Test + public void testIterator() throws IOException, DBException { + + Options options = new Options().createIfMissing(true); + + File path = getTestDirectory(getName()); + DB db = factory.open(path, options); + + db.put(bytes("Tampa"), bytes("green")); + db.put(bytes("London"), bytes("red")); + db.put(bytes("New York"), bytes("blue")); + + ArrayList expecting = new ArrayList(); + expecting.add("London"); + expecting.add("New York"); + expecting.add("Tampa"); + + ArrayList actual = new ArrayList(); + + DBIterator iterator = db.iterator(); + for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) { + actual.add(asString(iterator.peekNext().getKey())); + } + iterator.close(); + assertEquals(expecting, actual); + + db.close(); + } + + @Test + public void testSnapshot() throws IOException, DBException { + + Options options = new Options().createIfMissing(true); + + File path = getTestDirectory(getName()); + DB db = factory.open(path, options); + + db.put(bytes("Tampa"), bytes("green")); + db.put(bytes("London"), bytes("red")); + db.delete(bytes("New York")); + + ReadOptions ro = new ReadOptions().snapshot(db.getSnapshot()); + + db.put(bytes("New York"), bytes("blue")); + + assertEquals(db.get(bytes("Tampa"), ro), bytes("green")); + assertEquals(db.get(bytes("London"), ro), bytes("red")); + + // Should not be able to get "New York" since it was added + // after the snapshot + assertNull(db.get(bytes("New York"), ro)); + + ro.snapshot().close(); + + // Now try again without the snapshot.. + ro.snapshot(null); + assertEquals(db.get(bytes("New York"), ro), bytes("blue")); + + db.close(); + } + + @Test + public void testWriteBatch() throws IOException, DBException { + + Options options = new Options().createIfMissing(true); + + File path = getTestDirectory(getName()); + DB db = factory.open(path, options); + + db.put(bytes("NA"), bytes("Na")); + + WriteBatch batch = db.createWriteBatch(); + batch.delete(bytes("NA")); + batch.put(bytes("Tampa"), bytes("green")); + batch.put(bytes("London"), bytes("red")); + batch.put(bytes("New York"), bytes("blue")); + db.write(batch); + batch.close(); + + ArrayList expecting = new ArrayList(); + expecting.add("London"); + expecting.add("New York"); + expecting.add("Tampa"); + + ArrayList actual = new ArrayList(); + + DBIterator iterator = db.iterator(); + for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) { + actual.add(asString(iterator.peekNext().getKey())); + } + iterator.close(); + assertEquals(expecting, actual); + + db.close(); + } + + @Test + public void testApproximateSizes() throws IOException, DBException { + Options options = new Options().createIfMissing(true); + + File path = getTestDirectory(getName()); + DB db = factory.open(path, options); + + Random r = new Random(0); + String data=""; + for(int i=0; i < 1024; i++) { + data+= 'a'+r.nextInt(26); + } + for(int i=0; i < 5*1024; i++) { + db.put(bytes("row"+i), bytes(data)); + } + + long[] approximateSizes = db.getApproximateSizes(new Range(bytes("row"), bytes("s"))); + assertNotNull(approximateSizes); + assertEquals(1, approximateSizes.length); + assertTrue("Wrong size", approximateSizes[0] > 0); + + db.close(); + } + + @Test + public void testGetProperty() throws IOException, DBException { + Options options = new Options().createIfMissing(true); + + File path = getTestDirectory(getName()); + DB db = factory.open(path, options); + + Random r = new Random(0); + String data=""; + for(int i=0; i < 1024; i++) { + data+= 'a'+r.nextInt(26); + } + for(int i=0; i < 5*1024; i++) { + db.put(bytes("row"+i), bytes(data)); + } + + String stats = db.getProperty("leveldb.stats"); + assertNotNull(stats); + assertTrue(stats.contains("Compactions")); + + db.close(); + } + + @Test + public void testCustomComparator1() throws IOException, DBException { + Options options = new Options().createIfMissing(true); + options.comparator(new DBComparator() { + + public int compare(byte[] key1, byte[] key2) { + return new String(key1).compareTo(new String(key2)); + } + + public String name() { + return getName(); + } + + public byte[] findShortestSeparator(byte[] start, byte[] limit) { + return start; + } + + public byte[] findShortSuccessor(byte[] key) { + return key; + } + }); + + File path = getTestDirectory(getName()); + DB db = factory.open(path, options); + + ArrayList expecting = new ArrayList(); + for(int i=0; i < 26; i++) { + String t = ""+ ((char) ('a' + i)); + expecting.add(t); + db.put(bytes(t), bytes(t)); + } + + ArrayList actual = new ArrayList(); + + DBIterator iterator = db.iterator(); + for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) { + actual.add(asString(iterator.peekNext().getKey())); + } + iterator.close(); + assertEquals(expecting, actual); + + + db.close(); + } + + @Test + public void testCustomComparator2() throws IOException, DBException { + Options options = new Options().createIfMissing(true); + options.comparator(new DBComparator() { + + public int compare(byte[] key1, byte[] key2) { + return new String(key1).compareTo(new String(key2)) * -1; + } + + public String name() { + return getName(); + } + + public byte[] findShortestSeparator(byte[] start, byte[] limit) { + return start; + } + + public byte[] findShortSuccessor(byte[] key) { + return key; + } + }); + + File path = getTestDirectory(getName()); + DB db = factory.open(path, options); + + ArrayList expecting = new ArrayList(); + for(int i=0; i < 26; i++) { + String t = ""+ ((char) ('a' + i)); + expecting.add(t); + db.put(bytes(t), bytes(t)); + } + Collections.reverse(expecting); + + ArrayList actual = new ArrayList(); + DBIterator iterator = db.iterator(); + for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) { + actual.add(asString(iterator.peekNext().getKey())); + } + iterator.close(); + assertEquals(expecting, actual); + + db.close(); + } + + @Test + public void testLogger() throws IOException, InterruptedException, DBException { + final List messages = Collections.synchronizedList(new ArrayList()); + + Options options = new Options().createIfMissing(true); + options.logger(new Logger() { + public void log(String message) { + messages.add(message); + } + }); + + File path = getTestDirectory(getName()); + DB db = factory.open(path, options); + + for( int j=0; j < 5; j++) { + Random r = new Random(0); + String data=""; + for(int i=0; i < 1024; i++) { + data+= 'a'+r.nextInt(26); + } + for(int i=0; i < 5*1024; i++) { + db.put(bytes("row"+i), bytes(data)); + } + Thread.sleep(100); + } + + db.close(); + + assertFalse(messages.isEmpty()); + + } + + @Test + public void testCompactRanges() throws IOException, InterruptedException, DBException { + Options options = new Options().createIfMissing(true); + File path = getTestDirectory(getName()); + DB db = factory.open(path, options); + if( db instanceof JniDB) { + Random r = new Random(0); + String data=""; + for(int i=0; i < 1024; i++) { + data+= 'a'+r.nextInt(26); + } + for(int i=0; i < 5*1024; i++) { + db.put(bytes("row"+i), bytes(data)); + } + for(int i=0; i < 5*1024; i++) { + db.delete(bytes("row" + i)); + } + + String stats = db.getProperty("leveldb.stats"); + System.out.println(stats); + + // Compactions + // Level Files Size(MB) Time(sec) Read(MB) Write(MB) + // -------------------------------------------------- + assertFalse(stats.contains("1 0 0 0")); + assertFalse(stats.contains("2 0 0 0")); + + // After the compaction, level 1 and 2 should not have any files in it.. + ((JniDB) db).compactRange(null, null); + + stats = db.getProperty("leveldb.stats"); + System.out.println(stats); + assertTrue(stats.contains("1 0 0 0")); + assertTrue(stats.contains("2 0 0 0")); + + } + db.close(); + } + + @Test + public void testSuspendAndResumeCompactions() throws Exception { + Options options = new Options().createIfMissing(true); + File path = getTestDirectory(getName()); + DB db = factory.open(path, options); + db.suspendCompactions(); + db.resumeCompactions(); + db.close(); + } + + public void assertEquals(byte[] arg1, byte[] arg2) { + assertTrue(Arrays.equals(arg1, arg2)); + } +} diff --git a/java/leveldbjni/license.txt b/java/leveldbjni/license.txt new file mode 100644 index 00000000..8edd3759 --- /dev/null +++ b/java/leveldbjni/license.txt @@ -0,0 +1,27 @@ +Copyright (c) 2011 FuseSource Corp. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of FuseSource Corp. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/java/leveldbjni/pom.xml b/java/leveldbjni/pom.xml new file mode 100755 index 00000000..755c8dd6 --- /dev/null +++ b/java/leveldbjni/pom.xml @@ -0,0 +1,323 @@ + + + + + 4.0.0 + + org.fusesource + fusesource-pom + 1.9 + + + org.fusesource.leveldbjni.fb + leveldbjni-project + 1.5.7 + pom + + ${project.artifactId} + leveldbjni is a jni library for accessing leveldb. + + + leveldbjni + LEVELDBJNI + UTF-8 + 1.6 + 0.4 + nexus.vip.facebook.com:8181 + 1.7 + + http://${project.nexus.hostPort}/nexus/content/repositories/libs-releases-local + + + http://${project.nexus.hostPort}/nexus/content/repositories/libs-snapshots-local + + + + + leveldbjni + + + http://${forge-project-id}.fusesource.org + 2009 + + + github + https://github.com/fusesource/leveldbjni/issues + + + + + ${forge-project-id} dev + ${forge-project-id}-dev@fusesource.org + ${forge-project-id}-dev-subscribe@fusesource.org + + + ${forge-project-id} commits + ${forge-project-id}-commits@fusesource.org + ${forge-project-id}-commits-subscribe@fusesource.org + + + + + + The BSD 3-Clause License + http://www.opensource.org/licenses/BSD-3-Clause + repo + + + + + scm:git:git://github.com/fusesource/leveldbjni.git + scm:git:git@github.com:fusesource/leveldbjni.git + https://github.com/fusesource/leveldbjni + + + + + libs-releases-local + ${project.libs-releases-local-url} + + + libs-snapshots-local + ${project.libs-snapshots-local-url} + + + + + + chirino + Hiram Chirino + hiram@hiramchirino.com + http://hiramchirino.com + GMT-5 + + + + + + junit + junit + 4.7 + test + + + + + + + + + org.apache.maven.plugins + maven-clean-plugin + 2.3 + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + + org.apache.maven.plugins + maven-release-plugin + 2.3.1 + + false + true + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.4.3 + + true + once + -ea + false + ${project.build.directory} + + **/*Test.java + + + + + + + + + + org.codehaus.mojo + jxr-maven-plugin + 2.0-beta-1 + + true + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.6 + + *.internal + true + + http://java.sun.com/j2se/1.5.0/docs/api + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.1.1 + + + + index + sumary + plugins + dependencies + mailing-list + issue-tracking + license + scm + + + + + + org.codehaus.mojo + surefire-report-maven-plugin + 2.0-beta-1 + + + org.apache.maven.plugins + maven-plugin-plugin + 2.5 + + + + + + + + download + + + fusesource.nexus.snapshot + FuseSource Community Snapshot Repository + http://repo.fusesource.com/nexus/content/groups/public-snapshots + + + sonatype-nexus + Sonatype Nexus + https://oss.sonatype.org/content/repositories/public + true + true + + + + + fusesource.nexus.snapshot + FuseSource Community Snapshot Repository + http://repo.fusesource.com/nexus/content/groups/public-snapshots + + + + + + full + + leveldbjni-osx + leveldbjni-linux32 + leveldbjni-linux64 + leveldbjni-win32 + leveldbjni-win64 + leveldbjni-all + + + + + all + + leveldbjni-all + + + + osx + + leveldbjni-osx + + + + + linux32 + + leveldbjni-linux32 + + + + + linux64 + + leveldbjni-linux64 + + + + + win32 + + true + + + leveldbjni-win32 + + + + + win64 + + true + + + leveldbjni-win64 + + + + + diff --git a/java/leveldbjni/readme.md b/java/leveldbjni/readme.md new file mode 100644 index 00000000..1ca9d42b --- /dev/null +++ b/java/leveldbjni/readme.md @@ -0,0 +1,248 @@ +# LevelDB JNI + +## Description + +LevelDB JNI gives you a Java interface to the +[LevelDB](http://code.google.com/p/leveldb/) C++ library +which is a fast key-value storage library written at Google +that provides an ordered mapping from string keys to string values.. + + +## Using as a Maven Dependency + +You just nee to add the following repositories and dependencies to your Maven pom. + + + + fusesource.nexus.snapshot + FuseSource Community Snapshot Repository + http://repo.fusesource.com/nexus/content/groups/public-snapshots + + + + + + org.fusesource.leveldbjni + leveldbjni-all + 1.1 + + + +## API Usage: + +Recommended Package imports: + + import org.iq80.leveldb.*; + import static org.fusesource.leveldbjni.JniDBFactory.*; + import java.io.*; + +Opening and closing the database. + + Options options = new Options(); + options.createIfMissing(true); + DB db = factory.open(new File("example"), options); + try { + // Use the db in here.... + } finally { + // Make sure you close the db to shutdown the + // database and avoid resource leaks. + db.close(); + } + +Putting, Getting, and Deleting key/values. + + db.put(bytes("Tampa"), bytes("rocks")); + String value = asString(db.get(bytes("Tampa"))); + db.delete(wo, bytes("Tampa")); + +Performing Batch/Bulk/Atomic Updates. + + WriteBatch batch = db.createWriteBatch(); + try { + batch.delete(bytes("Denver")); + batch.put(bytes("Tampa"), bytes("green")); + batch.put(bytes("London"), bytes("red")); + + db.write(batch); + } finally { + // Make sure you close the batch to avoid resource leaks. + batch.close(); + } + +Iterating key/values. + + DBIterator iterator = db.iterator(); + try { + for(iterator.seekToFirst(); iterator.hasNext(); iterator.next()) { + String key = asString(iterator.peekNext().getKey()); + String value = asString(iterator.peekNext().getValue()); + System.out.println(key+" = "+value); + } + } finally { + // Make sure you close the iterator to avoid resource leaks. + iterator.close(); + } + +Working against a Snapshot view of the Database. + + ReadOptions ro = new ReadOptions(); + ro.snapshot(db.getSnapshot()); + try { + + // All read operations will now use the same + // consistent view of the data. + ... = db.iterator(ro); + ... = db.get(bytes("Tampa"), ro); + + } finally { + // Make sure you close the snapshot to avoid resource leaks. + ro.snapshot().close(); + } + +Using a custom Comparator. + + DBComparator comparator = new DBComparator(){ + public int compare(byte[] key1, byte[] key2) { + return new String(key1).compareTo(new String(key2)); + } + public String name() { + return "simple"; + } + public byte[] findShortestSeparator(byte[] start, byte[] limit) { + return start; + } + public byte[] findShortSuccessor(byte[] key) { + return key; + } + }; + Options options = new Options(); + options.comparator(comparator); + DB db = factory.open(new File("example"), options); + +Disabling Compression + + Options options = new Options(); + options.compressionType(CompressionType.NONE); + DB db = factory.open(new File("example"), options); + +Configuring the Cache + + Options options = new Options(); + options.cacheSize(100 * 1048576); // 100MB cache + DB db = factory.open(new File("example"), options); + +Getting approximate sizes. + + long[] sizes = db.getApproximateSizes(new Range(bytes("a"), bytes("k")), new Range(bytes("k"), bytes("z"))); + System.out.println("Size: "+sizes[0]+", "+sizes[1]); + +Getting database status. + + String stats = db.getProperty("leveldb.stats"); + System.out.println(stats); + +Getting informational log messages. + + Logger logger = new Logger() { + public void log(String message) { + System.out.println(message); + } + }; + Options options = new Options(); + options.logger(logger); + DB db = factory.open(new File("example"), options); + +Destroying a database. + + Options options = new Options(); + factory.destroy(new File("example"), options); + +Repairing a database. + + Options options = new Options(); + factory.repair(new File("example"), options); + +Using a memory pool to make native memory allocations more efficient: + + JniDBFactory.pushMemoryPool(1024 * 512); + try { + // .. work with the DB in here, + } finally { + JniDBFactory.popMemoryPool(); + } + +## Building + +### Prerequisites + +* GNU compiler toolchain +* [Maven 3](http://maven.apache.org/download.html) + +### Supported Platforms + +The following worked for me on: + + * OS X Lion with X Code 4 + * CentOS 5.6 (32 and 64 bit) + * Ubuntu 12.04 (32 and 64 bit) + * apt-get install autoconf libtool + +### Build Procedure + +Then download the snappy, leveldb, and leveldbjni project source code: + + wget http://snappy.googlecode.com/files/snappy-1.0.5.tar.gz + tar -zxvf snappy-1.0.5.tar.gz + git clone git://github.com/chirino/leveldb.git + git clone git://github.com/fusesource/leveldbjni.git + export SNAPPY_HOME=`cd snappy-1.0.5; pwd` + export LEVELDB_HOME=`cd leveldb; pwd` + export LEVELDBJNI_HOME=`cd leveldbjni; pwd` + + + +Compile the snappy project. This produces a static library. + + cd ${SNAPPY_HOME} + ./configure --disable-shared --with-pic + make + +Patch and Compile the leveldb project. This produces a static library. + + cd ${LEVELDB_HOME} + export LIBRARY_PATH=${SNAPPY_HOME} + export C_INCLUDE_PATH=${LIBRARY_PATH} + export CPLUS_INCLUDE_PATH=${LIBRARY_PATH} + git apply ../leveldbjni/leveldb.patch + make libleveldb.a + +Now use maven to build the leveldbjni project. + + cd ${LEVELDBJNI_HOME} + mvn clean install -P download -P ${platform} + +Replace ${platform} with one of the following platform identifiers (depending on the platform your building on): + +* osx +* linux32 +* linux64 +* win32 +* win64 + +If your platform does not have the right auto-tools levels available +just copy the `leveldbjni-${version}-SNAPSHOT-native-src.zip` artifact +from a platform the does have the tools available then add the +following argument to your maven build: + + -Dnative-src-url=file:leveldbjni-${verision}-SNAPSHOT-native-src.zip + +### Build Results + +* `leveldbjni/target/leveldbjni-${version}.jar` : The java class file to the library. +* `leveldbjni/target/leveldbjni-${version}-native-src.zip` : A GNU style source project which you can use to build the native library on other systems. +* `leveldbjni-${platform}/target/leveldbjni-${platform}-${version}.jar` : A jar file containing the built native library using your currently platform. + diff --git a/java/leveldbjni/releasing.md b/java/leveldbjni/releasing.md new file mode 100644 index 00000000..1cc797eb --- /dev/null +++ b/java/leveldbjni/releasing.md @@ -0,0 +1,30 @@ +# How To Release + +Since levedbjni has to be build against multiple platforms, the standard maven release plugin will not work to do the release. + +Once you ready to do the release, create a branch for the release using: + + git co -b ${version}.x + +Update the version number in the poms using: + + mvn -P all org.codehaus.mojo:versions-maven-plugin:1.2:set org.codehaus.mojo:versions-maven-plugin:1.2:commit -DnewVersion="${version}" + git commit -am "Preping for a the ${version} release" + git tag "leveldbjni-${version}" + git push origin "leveldbjni-${version}" + +Now release the non-platform specific artifacts using: + + mvn clean deploy -P release -P download + +Then for each platform, shell into the box check out the "leveldbjni-${version}" tag and then: + + cd $platform + mvn clean deploy -Dleveldb=`cd ../../leveldb; pwd` -Dsnappy=`cd ../../snappy-1.0.3; pwd` -P release -P download + +Finally release the `leveldbjni-all` which uber jars all the previously released artifacts. + + cd leveldbjni-all + mvn clean deploy -P release -P download + +Congrats your done. Make sure your releasing the artifacts in Nexus after each step. \ No newline at end of file diff --git a/linters/src/.phutil_module_cache b/linters/src/.phutil_module_cache new file mode 100644 index 00000000..5c93a840 --- /dev/null +++ b/linters/src/.phutil_module_cache @@ -0,0 +1 @@ +{"__symbol_cache_version__":8,"b937ad5f80a8bd1156038b730ff56ec5":{"have":{"class":{"FacebookFbcodeLintEngine":71}},"need":{"class":{"ArcanistLintEngine":104,"ArcanistGeneratedLinter":488,"ArcanistNoLintLinter":577,"ArcanistTextLinter":658,"ArcanistPEP8Linter":1227,"FbcodeCppLinter":1715,"PfffCppLinter":1759,"ArcanistSpellingLinter":1875,"ArcanistFilenameLinter":4207,"Filesystem":357,"ArcanistLintSeverity":778}},"xmap":{"FacebookFbcodeLintEngine":["ArcanistLintEngine"]}},"02e2a613e371424b2108d2d6cb849d39":{"have":{"class":{"PfffCppLinter":71}},"need":{"function":{"Futures":875},"class":{"ArcanistLinter":93,"ExecFuture":756,"ArcanistLintMessage":1270,"ArcanistLintSeverity":1607}},"xmap":{"PfffCppLinter":["ArcanistLinter"]}},"4443484928afb005f585843d07b04190":{"have":{"class":{"FbcodeCppLinter":13}},"need":{"function":{"Futures":1265},"class":{"ArcanistLinter":37,"ExecFuture":934,"ArcanistLintSeverity":1729}},"xmap":{"FbcodeCppLinter":["ArcanistLinter"]}}} \ No newline at end of file diff --git a/linters/src/__phutil_library_init__.php b/linters/src/__phutil_library_init__.php new file mode 100644 index 00000000..4b8d3d13 --- /dev/null +++ b/linters/src/__phutil_library_init__.php @@ -0,0 +1,3 @@ + 2, + 'class' => + array( + 'FacebookFbcodeLintEngine' => 'lint_engine/FacebookFbcodeLintEngine.php', + 'FbcodeCppLinter' => 'cpp_linter/FbcodeCppLinter.php', + 'PfffCppLinter' => 'cpp_linter/PfffCppLinter.php', + ), + 'function' => + array( + ), + 'xmap' => + array( + 'FacebookFbcodeLintEngine' => 'ArcanistLintEngine', + 'FbcodeCppLinter' => 'ArcanistLinter', + 'PfffCppLinter' => 'ArcanistLinter', + ), +)); diff --git a/linters/src/cpp_linter/FbcodeCppLinter.php b/linters/src/cpp_linter/FbcodeCppLinter.php new file mode 100644 index 00000000..e62d3bbe --- /dev/null +++ b/linters/src/cpp_linter/FbcodeCppLinter.php @@ -0,0 +1,99 @@ +getEngine()->getFilePathOnDisk($p); + $lpath_file = file($lpath); + if (preg_match('/\.(c)$/', $lpath) || + preg_match('/-\*-.*Mode: C[; ].*-\*-/', $lpath_file[0]) || + preg_match('/vim(:.*)*:\s*(set\s+)?filetype=c\s*:/', $lpath_file[0]) + ) { + $futures[$p] = new ExecFuture("%s %s %s 2>&1", + $CPP_LINT, self::C_FLAG, + $this->getEngine()->getFilePathOnDisk($p)); + } else { + $futures[$p] = new ExecFuture("%s %s 2>&1", + self::CPPLINT, $this->getEngine()->getFilePathOnDisk($p)); + } + } + + foreach (Futures($futures)->limit(8) as $p => $f) { + $this->rawLintOutput[$p] = $f->resolvex(); + } + } + return; + } + + public function getLinterName() { + return "FBCPP"; + } + + public function lintPath($path) { + $msgs = $this->getCppLintOutput($path); + foreach ($msgs as $m) { + $this->raiseLintAtLine($m['line'], 0, $m['severity'], $m['msg']); + } + } + + public function getLintSeverityMap() { + return array( + self::LINT_WARNING => ArcanistLintSeverity::SEVERITY_WARNING, + self::LINT_ERROR => ArcanistLintSeverity::SEVERITY_ERROR + ); + } + + public function getLintNameMap() { + return array( + self::LINT_WARNING => "CppLint Warning", + self::LINT_ERROR => "CppLint Error" + ); + } + + private function getCppLintOutput($path) { + list($output) = $this->rawLintOutput[$path]; + + $msgs = array(); + $current = null; + foreach (explode("\n", $output) as $line) { + if (preg_match('/[^:]*\((\d+)\):(.*)$/', $line, $matches)) { + if ($current) { + $msgs[] = $current; + } + $line = $matches[1]; + $text = $matches[2]; + $sev = preg_match('/.*Warning.*/', $text) + ? self::LINT_WARNING + : self::LINT_ERROR; + $current = array('line' => $line, + 'msg' => $text, + 'severity' => $sev); + } else if ($current) { + $current['msg'] .= ' ' . $line; + } + } + if ($current) { + $msgs[] = $current; + } + + return $msgs; + } +} + diff --git a/linters/src/cpp_linter/PfffCppLinter.php b/linters/src/cpp_linter/PfffCppLinter.php new file mode 100644 index 00000000..67366143 --- /dev/null +++ b/linters/src/cpp_linter/PfffCppLinter.php @@ -0,0 +1,68 @@ +&1", + $program, $this->getEngine()->getFilePathOnDisk($p)); + } + foreach (Futures($futures)->limit(8) as $p => $f) { + + list($stdout, $stderr) = $f->resolvex(); + $raw = json_decode($stdout, true); + if (!is_array($raw)) { + throw new Exception( + "checkCpp returned invalid JSON!". + "Stdout: {$stdout} Stderr: {$stderr}" + ); + } + foreach($raw as $err) { + $this->addLintMessage( + ArcanistLintMessage::newFromDictionary( + array( + 'path' => $err['file'], + 'line' => $err['line'], + 'char' => 0, + 'name' => $err['name'], + 'description' => $err['info'], + 'code' => $this->getLinterName(), + 'severity' => ArcanistLintSeverity::SEVERITY_WARNING, + ) + ) + ); + } + } + } + return; + } + + public function lintPath($path) { + return; + } +} diff --git a/linters/src/lint_engine/FacebookFbcodeLintEngine.php b/linters/src/lint_engine/FacebookFbcodeLintEngine.php new file mode 100644 index 00000000..c34530c3 --- /dev/null +++ b/linters/src/lint_engine/FacebookFbcodeLintEngine.php @@ -0,0 +1,147 @@ +getPaths(); + + // Remove all deleted files, which are not checked by the + // following linters. + foreach ($paths as $key => $path) { + if (!Filesystem::pathExists($this->getFilePathOnDisk($path))) { + unset($paths[$key]); + } + } + + $generated_linter = new ArcanistGeneratedLinter(); + $linters[] = $generated_linter; + + $nolint_linter = new ArcanistNoLintLinter(); + $linters[] = $nolint_linter; + + $text_linter = new ArcanistTextLinter(); + $text_linter->setCustomSeverityMap(array( + ArcanistTextLinter::LINT_LINE_WRAP + => ArcanistLintSeverity::SEVERITY_ADVICE, + )); + $linters[] = $text_linter; + + $java_text_linter = new ArcanistTextLinter(); + $java_text_linter->setMaxLineLength(100); + $java_text_linter->setCustomSeverityMap(array( + ArcanistTextLinter::LINT_LINE_WRAP + => ArcanistLintSeverity::SEVERITY_ADVICE, + )); + $linters[] = $java_text_linter; + + $pep8_options = $this->getPEP8WithTextOptions().',E302'; + + $python_linter = new ArcanistPEP8Linter(); + $python_linter->setConfig(array('options' => $pep8_options)); + $linters[] = $python_linter; + + $python_2space_linter = new ArcanistPEP8Linter(); + $python_2space_linter->setConfig(array('options' => $pep8_options.',E111')); + $linters[] = $python_2space_linter; + + // Currently we can't run cpplint in commit hook mode, because it + // depends on having access to the working directory. + if (!$this->getCommitHookMode()) { + $cpp_linter = new FbcodeCppLinter(); + $cpp_linter2 = new PfffCppLinter(); + $linters[] = $cpp_linter; + $linters[] = $cpp_linter2; + } + + $spelling_linter = new ArcanistSpellingLinter(); + $linters[] = $spelling_linter; + + foreach ($paths as $path) { + $is_text = false; + + $text_extensions = ( + '/\.('. + 'cpp|cxx|c|cc|h|hpp|hxx|tcc|'. + 'py|rb|hs|pl|pm|tw|'. + 'php|phpt|css|js|'. + 'java|'. + 'thrift|'. + 'lua|'. + 'siv|'. + 'txt'. + ')$/' + ); + if (preg_match($text_extensions, $path)) { + $is_text = true; + } + if ($is_text) { + $nolint_linter->addPath($path); + + $generated_linter->addPath($path); + $generated_linter->addData($path, $this->loadData($path)); + + if (preg_match('/\.java$/', $path)) { + $java_text_linter->addPath($path); + $java_text_linter->addData($path, $this->loadData($path)); + } else { + $text_linter->addPath($path); + $text_linter->addData($path, $this->loadData($path)); + } + + $spelling_linter->addPath($path); + $spelling_linter->addData($path, $this->loadData($path)); + } + if (isset($cpp_linter) && isset($cpp_linter2) && + preg_match('/\.(cpp|c|cc|cxx|h|hh|hpp|hxx|tcc)$/', $path)) { + $cpp_linter->addPath($path); + $cpp_linter->addData($path, $this->loadData($path)); + $cpp_linter2->addPath($path); + $cpp_linter2->addData($path, $this->loadData($path)); + + } + + // Match *.py and contbuild config files + if (preg_match('/(\.(py|tw|smcprops)|^contbuild\/configs\/[^\/]*)$/', + $path)) { + $space_count = 4; + $real_path = $this->getFilePathOnDisk($path); + $dir = dirname($real_path); + do { + if (file_exists($dir.'/.python2space')) { + $space_count = 2; + break; + } + $dir = dirname($dir); + } while ($dir != '/' && $dir != '.'); + + if ($space_count == 4) { + $cur_path_linter = $python_linter; + } else { + $cur_path_linter = $python_2space_linter; + } + $cur_path_linter->addPath($path); + $cur_path_linter->addData($path, $this->loadData($path)); + + if (preg_match('/\.tw$/', $path)) { + $cur_path_linter->setCustomSeverityMap(array( + 'E251' => ArcanistLintSeverity::SEVERITY_DISABLED, + )); + } + } + + + + } + + $name_linter = new ArcanistFilenameLinter(); + $linters[] = $name_linter; + foreach ($paths as $path) { + $name_linter->addPath($path); + } + + return $linters; + } + +} diff --git a/port/README b/port/README new file mode 100644 index 00000000..422563e2 --- /dev/null +++ b/port/README @@ -0,0 +1,10 @@ +This directory contains interfaces and implementations that isolate the +rest of the package from platform details. + +Code in the rest of the package includes "port.h" from this directory. +"port.h" in turn includes a platform specific "port_.h" file +that provides the platform specific implementation. + +See port_posix.h for an example of what must be provided in a platform +specific header file. + diff --git a/port/atomic_pointer.h b/port/atomic_pointer.h new file mode 100644 index 00000000..c58bffbf --- /dev/null +++ b/port/atomic_pointer.h @@ -0,0 +1,152 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +// AtomicPointer provides storage for a lock-free pointer. +// Platform-dependent implementation of AtomicPointer: +// - If the platform provides a cheap barrier, we use it with raw pointers +// - If cstdatomic is present (on newer versions of gcc, it is), we use +// a cstdatomic-based AtomicPointer. However we prefer the memory +// barrier based version, because at least on a gcc 4.4 32-bit build +// on linux, we have encountered a buggy +// implementation. Also, some implementations are much +// slower than a memory-barrier based implementation (~16ns for +// based acquire-load vs. ~1ns for a barrier based +// acquire-load). +// This code is based on atomicops-internals-* in Google's perftools: +// http://code.google.com/p/google-perftools/source/browse/#svn%2Ftrunk%2Fsrc%2Fbase + +#ifndef PORT_ATOMIC_POINTER_H_ +#define PORT_ATOMIC_POINTER_H_ + +#include +#ifdef LEVELDB_CSTDATOMIC_PRESENT +#include +#endif +#ifdef OS_WIN +#include +#endif +#ifdef OS_MACOSX +#include +#endif + +#if defined(_M_X64) || defined(__x86_64__) +#define ARCH_CPU_X86_FAMILY 1 +#elif defined(_M_IX86) || defined(__i386__) || defined(__i386) +#define ARCH_CPU_X86_FAMILY 1 +#elif defined(__ARMEL__) +#define ARCH_CPU_ARM_FAMILY 1 +#endif + +namespace leveldb { +namespace port { + +// Define MemoryBarrier() if available +// Windows on x86 +#if defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY) +// windows.h already provides a MemoryBarrier(void) macro +// http://msdn.microsoft.com/en-us/library/ms684208(v=vs.85).aspx +#define LEVELDB_HAVE_MEMORY_BARRIER + +// Gcc on x86 +#elif defined(ARCH_CPU_X86_FAMILY) && defined(__GNUC__) +inline void MemoryBarrier() { + // See http://gcc.gnu.org/ml/gcc/2003-04/msg01180.html for a discussion on + // this idiom. Also see http://en.wikipedia.org/wiki/Memory_ordering. + __asm__ __volatile__("" : : : "memory"); +} +#define LEVELDB_HAVE_MEMORY_BARRIER + +// Sun Studio +#elif defined(ARCH_CPU_X86_FAMILY) && defined(__SUNPRO_CC) +inline void MemoryBarrier() { + // See http://gcc.gnu.org/ml/gcc/2003-04/msg01180.html for a discussion on + // this idiom. Also see http://en.wikipedia.org/wiki/Memory_ordering. + asm volatile("" : : : "memory"); +} +#define LEVELDB_HAVE_MEMORY_BARRIER + +// Mac OS +#elif defined(OS_MACOSX) +inline void MemoryBarrier() { + OSMemoryBarrier(); +} +#define LEVELDB_HAVE_MEMORY_BARRIER + +// ARM Linux +#elif defined(ARCH_CPU_ARM_FAMILY) && defined(__linux__) +typedef void (*LinuxKernelMemoryBarrierFunc)(void); +// The Linux ARM kernel provides a highly optimized device-specific memory +// barrier function at a fixed memory address that is mapped in every +// user-level process. +// +// This beats using CPU-specific instructions which are, on single-core +// devices, un-necessary and very costly (e.g. ARMv7-A "dmb" takes more +// than 180ns on a Cortex-A8 like the one on a Nexus One). Benchmarking +// shows that the extra function call cost is completely negligible on +// multi-core devices. +// +inline void MemoryBarrier() { + (*(LinuxKernelMemoryBarrierFunc)0xffff0fa0)(); +} +#define LEVELDB_HAVE_MEMORY_BARRIER + +#endif + +// AtomicPointer built using platform-specific MemoryBarrier() +#if defined(LEVELDB_HAVE_MEMORY_BARRIER) +class AtomicPointer { + private: + void* rep_; + public: + AtomicPointer() { } + explicit AtomicPointer(void* p) : rep_(p) {} + inline void* NoBarrier_Load() const { return rep_; } + inline void NoBarrier_Store(void* v) { rep_ = v; } + inline void* Acquire_Load() const { + void* result = rep_; + MemoryBarrier(); + return result; + } + inline void Release_Store(void* v) { + MemoryBarrier(); + rep_ = v; + } +}; + +// AtomicPointer based on +#elif defined(LEVELDB_CSTDATOMIC_PRESENT) +class AtomicPointer { + private: + std::atomic rep_; + public: + AtomicPointer() { } + explicit AtomicPointer(void* v) : rep_(v) { } + inline void* Acquire_Load() const { + return rep_.load(std::memory_order_acquire); + } + inline void Release_Store(void* v) { + rep_.store(v, std::memory_order_release); + } + inline void* NoBarrier_Load() const { + return rep_.load(std::memory_order_relaxed); + } + inline void NoBarrier_Store(void* v) { + rep_.store(v, std::memory_order_relaxed); + } +}; + +// We have neither MemoryBarrier(), nor +#else +#error Please implement AtomicPointer for this platform. + +#endif + +#undef LEVELDB_HAVE_MEMORY_BARRIER +#undef ARCH_CPU_X86_FAMILY +#undef ARCH_CPU_ARM_FAMILY + +} // namespace port +} // namespace leveldb + +#endif // PORT_ATOMIC_POINTER_H_ diff --git a/port/port.h b/port/port.h new file mode 100644 index 00000000..e667db40 --- /dev/null +++ b/port/port.h @@ -0,0 +1,19 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_PORT_PORT_H_ +#define STORAGE_LEVELDB_PORT_PORT_H_ + +#include + +// Include the appropriate platform specific file below. If you are +// porting to a new platform, see "port_example.h" for documentation +// of what the new port_.h file must provide. +#if defined(LEVELDB_PLATFORM_POSIX) +# include "port/port_posix.h" +#elif defined(LEVELDB_PLATFORM_CHROMIUM) +# include "port/port_chromium.h" +#endif + +#endif // STORAGE_LEVELDB_PORT_PORT_H_ diff --git a/port/port_example.h b/port/port_example.h new file mode 100644 index 00000000..ab9e489b --- /dev/null +++ b/port/port_example.h @@ -0,0 +1,135 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// This file contains the specification, but not the implementations, +// of the types/operations/etc. that should be defined by a platform +// specific port_.h file. Use this file as a reference for +// how to port this package to a new platform. + +#ifndef STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ +#define STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ + +namespace leveldb { +namespace port { + +// TODO(jorlow): Many of these belong more in the environment class rather than +// here. We should try moving them and see if it affects perf. + +// The following boolean constant must be true on a little-endian machine +// and false otherwise. +static const bool kLittleEndian = true /* or some other expression */; + +// ------------------ Threading ------------------- + +// A Mutex represents an exclusive lock. +class Mutex { + public: + Mutex(); + ~Mutex(); + + // Lock the mutex. Waits until other lockers have exited. + // Will deadlock if the mutex is already locked by this thread. + void Lock(); + + // Unlock the mutex. + // REQUIRES: This mutex was locked by this thread. + void Unlock(); + + // Optionally crash if this thread does not hold this mutex. + // The implementation must be fast, especially if NDEBUG is + // defined. The implementation is allowed to skip all checks. + void AssertHeld(); +}; + +class CondVar { + public: + explicit CondVar(Mutex* mu); + ~CondVar(); + + // Atomically release *mu and block on this condition variable until + // either a call to SignalAll(), or a call to Signal() that picks + // this thread to wakeup. + // REQUIRES: this thread holds *mu + void Wait(); + + // If there are some threads waiting, wake up at least one of them. + void Signal(); + + // Wake up all waiting threads. + void SignallAll(); +}; + +// Thread-safe initialization. +// Used as follows: +// static port::OnceType init_control = LEVELDB_ONCE_INIT; +// static void Initializer() { ... do something ...; } +// ... +// port::InitOnce(&init_control, &Initializer); +typedef intptr_t OnceType; +#define LEVELDB_ONCE_INIT 0 +extern void InitOnce(port::OnceType*, void (*initializer)()); + +// A type that holds a pointer that can be read or written atomically +// (i.e., without word-tearing.) +class AtomicPointer { + private: + intptr_t rep_; + public: + // Initialize to arbitrary value + AtomicPointer(); + + // Initialize to hold v + explicit AtomicPointer(void* v) : rep_(v) { } + + // Read and return the stored pointer with the guarantee that no + // later memory access (read or write) by this thread can be + // reordered ahead of this read. + void* Acquire_Load() const; + + // Set v as the stored pointer with the guarantee that no earlier + // memory access (read or write) by this thread can be reordered + // after this store. + void Release_Store(void* v); + + // Read the stored pointer with no ordering guarantees. + void* NoBarrier_Load() const; + + // Set va as the stored pointer with no ordering guarantees. + void NoBarrier_Store(void* v); +}; + +// ------------------ Compression ------------------- + +// Store the snappy compression of "input[0,input_length-1]" in *output. +// Returns false if snappy is not supported by this port. +extern bool Snappy_Compress(const char* input, size_t input_length, + std::string* output); + +// If input[0,input_length-1] looks like a valid snappy compressed +// buffer, store the size of the uncompressed data in *result and +// return true. Else return false. +extern bool Snappy_GetUncompressedLength(const char* input, size_t length, + size_t* result); + +// Attempt to snappy uncompress input[0,input_length-1] into *output. +// Returns true if successful, false if the input is invalid lightweight +// compressed data. +// +// REQUIRES: at least the first "n" bytes of output[] must be writable +// where "n" is the result of a successful call to +// Snappy_GetUncompressedLength. +extern bool Snappy_Uncompress(const char* input_data, size_t input_length, + char* output); + +// ------------------ Miscellaneous ------------------- + +// If heap profiling is not supported, returns false. +// Else repeatedly calls (*func)(arg, data, n) and then returns true. +// The concatenation of all "data[0,n-1]" fragments is the heap profile. +extern bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg); + +} // namespace port +} // namespace leveldb + +#endif // STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ diff --git a/port/port_posix.cc b/port/port_posix.cc new file mode 100644 index 00000000..82cecdf2 --- /dev/null +++ b/port/port_posix.cc @@ -0,0 +1,64 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "port/port_posix.h" + +#include +#include +#include +#include "util/logging.h" + +namespace leveldb { +namespace port { + +static void PthreadCall(const char* label, int result) { + if (result != 0) { + fprintf(stderr, "pthread %s: %s\n", label, strerror(result)); + abort(); + } +} + +Mutex::Mutex() { PthreadCall("init mutex", pthread_mutex_init(&mu_, NULL)); } + +Mutex::~Mutex() { PthreadCall("destroy mutex", pthread_mutex_destroy(&mu_)); } + +void Mutex::Lock() { PthreadCall("lock", pthread_mutex_lock(&mu_)); } + +void Mutex::Unlock() { PthreadCall("unlock", pthread_mutex_unlock(&mu_)); } + +CondVar::CondVar(Mutex* mu) + : mu_(mu) { + PthreadCall("init cv", pthread_cond_init(&cv_, NULL)); +} + +CondVar::~CondVar() { PthreadCall("destroy cv", pthread_cond_destroy(&cv_)); } + +void CondVar::Wait() { + PthreadCall("wait", pthread_cond_wait(&cv_, &mu_->mu_)); +} + +void CondVar::Signal() { + PthreadCall("signal", pthread_cond_signal(&cv_)); +} + +void CondVar::SignalAll() { + PthreadCall("broadcast", pthread_cond_broadcast(&cv_)); +} + +RWMutex::RWMutex() { PthreadCall("init mutex", pthread_rwlock_init(&mu_, NULL)); } + +RWMutex::~RWMutex() { PthreadCall("destroy mutex", pthread_rwlock_destroy(&mu_)); } + +void RWMutex::ReadLock() { PthreadCall("read lock", pthread_rwlock_rdlock(&mu_)); } + +void RWMutex::WriteLock() { PthreadCall("write lock", pthread_rwlock_wrlock(&mu_)); } + +void RWMutex::Unlock() { PthreadCall("unlock", pthread_rwlock_unlock(&mu_)); } + +void InitOnce(OnceType* once, void (*initializer)()) { + PthreadCall("once", pthread_once(once, initializer)); +} + +} // namespace port +} // namespace leveldb diff --git a/port/port_posix.h b/port/port_posix.h new file mode 100644 index 00000000..e2540a42 --- /dev/null +++ b/port/port_posix.h @@ -0,0 +1,408 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// See port_example.h for documentation for the following types/functions. + +#ifndef STORAGE_LEVELDB_PORT_PORT_POSIX_H_ +#define STORAGE_LEVELDB_PORT_PORT_POSIX_H_ + +#undef PLATFORM_IS_LITTLE_ENDIAN +#if defined(OS_MACOSX) + #include + #if defined(__DARWIN_LITTLE_ENDIAN) && defined(__DARWIN_BYTE_ORDER) + #define PLATFORM_IS_LITTLE_ENDIAN \ + (__DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN) + #endif +#elif defined(OS_SOLARIS) + #include + #ifdef _LITTLE_ENDIAN + #define PLATFORM_IS_LITTLE_ENDIAN true + #else + #define PLATFORM_IS_LITTLE_ENDIAN false + #endif +#elif defined(OS_FREEBSD) || defined(OS_OPENBSD) || defined(OS_NETBSD) ||\ + defined(OS_DRAGONFLYBSD) || defined(OS_ANDROID) + #include + #include +#else + #include +#endif +#include +#ifdef SNAPPY +#include +#endif + +#ifdef ZLIB +#include +#endif + +#ifdef BZIP2 +#include +#endif + +#include +#include +#include +#include "leveldb/options.h" +#include "port/atomic_pointer.h" + +#ifndef PLATFORM_IS_LITTLE_ENDIAN +#define PLATFORM_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN) +#endif + +#if defined(OS_MACOSX) || defined(OS_SOLARIS) || defined(OS_FREEBSD) ||\ + defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_DRAGONFLYBSD) ||\ + defined(OS_ANDROID) +// Use fread/fwrite/fflush on platforms without _unlocked variants +#define fread_unlocked fread +#define fwrite_unlocked fwrite +#define fflush_unlocked fflush +#endif + +#if defined(OS_MACOSX) || defined(OS_FREEBSD) ||\ + defined(OS_OPENBSD) || defined(OS_DRAGONFLYBSD) +// Use fsync() on platforms without fdatasync() +#define fdatasync fsync +#endif + +#if defined(OS_ANDROID) && __ANDROID_API__ < 9 +// fdatasync() was only introduced in API level 9 on Android. Use fsync() +// when targetting older platforms. +#define fdatasync fsync +#endif + +namespace leveldb { +namespace port { + +static const bool kLittleEndian = PLATFORM_IS_LITTLE_ENDIAN; +#undef PLATFORM_IS_LITTLE_ENDIAN + +class CondVar; + +class Mutex { + public: + Mutex(); + ~Mutex(); + + void Lock(); + void Unlock(); + void AssertHeld() { } + + private: + friend class CondVar; + pthread_mutex_t mu_; + + // No copying + Mutex(const Mutex&); + void operator=(const Mutex&); +}; + +class RWMutex { + public: + RWMutex(); + ~RWMutex(); + + void ReadLock(); + void WriteLock(); + void Unlock(); + void AssertHeld() { } + + private: + pthread_rwlock_t mu_; // the underlying platform mutex + + // No copying allowed + RWMutex(const RWMutex&); + void operator=(const RWMutex&); +}; + +class CondVar { + public: + explicit CondVar(Mutex* mu); + ~CondVar(); + void Wait(); + void Signal(); + void SignalAll(); + private: + pthread_cond_t cv_; + Mutex* mu_; +}; + +typedef pthread_once_t OnceType; +#define LEVELDB_ONCE_INIT PTHREAD_ONCE_INIT +extern void InitOnce(OnceType* once, void (*initializer)()); + +inline bool Snappy_Compress(const CompressionOptions& opts, const char* input, + size_t length, ::std::string* output) { +#ifdef SNAPPY + output->resize(snappy::MaxCompressedLength(length)); + size_t outlen; + snappy::RawCompress(input, length, &(*output)[0], &outlen); + output->resize(outlen); + return true; +#endif + + return false; +} + +inline bool Snappy_GetUncompressedLength(const char* input, size_t length, + size_t* result) { +#ifdef SNAPPY + return snappy::GetUncompressedLength(input, length, result); +#else + return false; +#endif +} + +inline bool Snappy_Uncompress(const char* input, size_t length, + char* output) { +#ifdef SNAPPY + return snappy::RawUncompress(input, length, output); +#else + return false; +#endif +} + +inline bool Zlib_Compress(const CompressionOptions& opts, const char* input, + size_t length, ::std::string* output) { +#ifdef ZLIB + // The memLevel parameter specifies how much memory should be allocated for + // the internal compression state. + // memLevel=1 uses minimum memory but is slow and reduces compression ratio. + // memLevel=9 uses maximum memory for optimal speed. + // The default value is 8. See zconf.h for more details. + static const int memLevel = 8; + z_stream _stream; + memset(&_stream, 0, sizeof(z_stream)); + int st = deflateInit2(&_stream, opts.level, Z_DEFLATED, opts.window_bits, + memLevel, opts.strategy); + if (st != Z_OK) { + return false; + } + + // Resize output to be the plain data length. + // This may not be big enough if the compression actually expands data. + output->resize(length); + + // Compress the input, and put compressed data in output. + _stream.next_in = (Bytef *)input; + _stream.avail_in = length; + + // Initialize the output size. + _stream.avail_out = length; + _stream.next_out = (Bytef *)&(*output)[0]; + + int old_sz =0, new_sz =0; + while(_stream.next_in != NULL && _stream.avail_in != 0) { + int st = deflate(&_stream, Z_FINISH); + switch (st) { + case Z_STREAM_END: + break; + case Z_OK: + // No output space. Increase the output space by 20%. + // (Should we fail the compression since it expands the size?) + old_sz = output->size(); + new_sz = (int)(output->size() * 1.2); + output->resize(new_sz); + // Set more output. + _stream.next_out = (Bytef *)&(*output)[old_sz]; + _stream.avail_out = new_sz - old_sz; + break; + case Z_BUF_ERROR: + default: + deflateEnd(&_stream); + return false; + } + } + + output->resize(output->size() - _stream.avail_out); + deflateEnd(&_stream); + return true; +#endif + return false; +} + +inline char* Zlib_Uncompress(const char* input_data, size_t input_length, + int* decompress_size, int windowBits = -14) { +#ifdef ZLIB + z_stream _stream; + memset(&_stream, 0, sizeof(z_stream)); + + // For raw inflate, the windowBits should be Ð8..Ð15. + // If windowBits is bigger than zero, it will use either zlib + // header or gzip header. Adding 32 to it will do automatic detection. + int st = inflateInit2(&_stream, + windowBits > 0 ? windowBits + 32 : windowBits); + if (st != Z_OK) { + return NULL; + } + + _stream.next_in = (Bytef *)input_data; + _stream.avail_in = input_length; + + // Assume the decompressed data size will 5x of compressed size. + int output_len = input_length * 5; + char* output = new char[output_len]; + int old_sz = output_len; + + _stream.next_out = (Bytef *)output; + _stream.avail_out = output_len; + + char* tmp = NULL; + + while(_stream.next_in != NULL && _stream.avail_in != 0) { + int st = inflate(&_stream, Z_SYNC_FLUSH); + switch (st) { + case Z_STREAM_END: + break; + case Z_OK: + // No output space. Increase the output space by 20%. + old_sz = output_len; + output_len = (int)(output_len * 1.2); + tmp = new char[output_len]; + memcpy(tmp, output, old_sz); + delete[] output; + output = tmp; + + // Set more output. + _stream.next_out = (Bytef *)(output + old_sz); + _stream.avail_out = output_len - old_sz; + break; + case Z_BUF_ERROR: + default: + delete[] output; + inflateEnd(&_stream); + return NULL; + } + } + + *decompress_size = output_len - _stream.avail_out; + inflateEnd(&_stream); + return output; +#endif + + return NULL; +} + +inline bool BZip2_Compress(const CompressionOptions& opts, const char* input, + size_t length, ::std::string* output) { +#ifdef BZIP2 + bz_stream _stream; + memset(&_stream, 0, sizeof(bz_stream)); + + // Block size 1 is 100K. + // 0 is for silent. + // 30 is the default workFactor + int st = BZ2_bzCompressInit(&_stream, 1, 0, 30); + if (st != BZ_OK) { + return false; + } + + // Resize output to be the plain data length. + // This may not be big enough if the compression actually expands data. + output->resize(length); + + // Compress the input, and put compressed data in output. + _stream.next_in = (char *)input; + _stream.avail_in = length; + + // Initialize the output size. + _stream.next_out = (char *)&(*output)[0]; + _stream.avail_out = length; + + int old_sz =0, new_sz =0; + while(_stream.next_in != NULL && _stream.avail_in != 0) { + int st = BZ2_bzCompress(&_stream, BZ_FINISH); + switch (st) { + case BZ_STREAM_END: + break; + case BZ_FINISH_OK: + // No output space. Increase the output space by 20%. + // (Should we fail the compression since it expands the size?) + old_sz = output->size(); + new_sz = (int)(output->size() * 1.2); + output->resize(new_sz); + // Set more output. + _stream.next_out = (char *)&(*output)[old_sz]; + _stream.avail_out = new_sz - old_sz; + break; + case Z_BUF_ERROR: + default: + BZ2_bzCompressEnd(&_stream); + return false; + } + } + + output->resize(output->size() - _stream.avail_out); + BZ2_bzCompressEnd(&_stream); + return true; + return output; +#endif + return false; +} + +inline char* BZip2_Uncompress(const char* input_data, size_t input_length, + int* decompress_size) { +#ifdef BZIP2 + bz_stream _stream; + memset(&_stream, 0, sizeof(bz_stream)); + + int st = BZ2_bzDecompressInit(&_stream, 0, 0); + if (st != BZ_OK) { + return NULL; + } + + _stream.next_in = (char *)input_data; + _stream.avail_in = input_length; + + // Assume the decompressed data size will be 5x of compressed size. + int output_len = input_length * 5; + char* output = new char[output_len]; + int old_sz = output_len; + + _stream.next_out = (char *)output; + _stream.avail_out = output_len; + + char* tmp = NULL; + + while(_stream.next_in != NULL && _stream.avail_in != 0) { + int st = BZ2_bzDecompress(&_stream); + switch (st) { + case BZ_STREAM_END: + break; + case Z_OK: + // No output space. Increase the output space by 20%. + old_sz = output_len; + output_len = (int)(output_len * 1.2); + tmp = new char[output_len]; + memcpy(tmp, output, old_sz); + delete[] output; + output = tmp; + + // Set more output. + _stream.next_out = (char *)(output + old_sz); + _stream.avail_out = output_len - old_sz; + break; + case Z_BUF_ERROR: + default: + delete[] output; + BZ2_bzDecompressEnd(&_stream); + return NULL; + } + } + + *decompress_size = output_len - _stream.avail_out; + BZ2_bzDecompressEnd(&_stream); + return output; +#endif + return NULL; +} + +inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) { + return false; +} + +} // namespace port +} // namespace leveldb + +#endif // STORAGE_LEVELDB_PORT_PORT_POSIX_H_ diff --git a/port/win/stdint.h b/port/win/stdint.h new file mode 100644 index 00000000..39edd0db --- /dev/null +++ b/port/win/stdint.h @@ -0,0 +1,24 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +// MSVC didn't ship with this file until the 2010 version. + +#ifndef STORAGE_LEVELDB_PORT_WIN_STDINT_H_ +#define STORAGE_LEVELDB_PORT_WIN_STDINT_H_ + +#if !defined(_MSC_VER) +#error This file should only be included when compiling with MSVC. +#endif + +// Define C99 equivalent types. +typedef signed char int8_t; +typedef signed short int16_t; +typedef signed int int32_t; +typedef signed long long int64_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +#endif // STORAGE_LEVELDB_PORT_WIN_STDINT_H_ diff --git a/regression_build_test.sh b/regression_build_test.sh new file mode 100755 index 00000000..459fcae1 --- /dev/null +++ b/regression_build_test.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +set -e + +NUM=10000000 + +if [ $# -eq 1 ];then + DATA_DIR=$1 +elif [ $# -eq 2 ];then + DATA_DIR=$1 + STAT_FILE=$2 +fi + +# On the production build servers, set data and stat +# files/directories not in /tmp or else the tempdir cleaning +# scripts will make you very unhappy. +DATA_DIR=${DATA_DIR:-$(mktemp --tmpdir -d leveldb_XXXX)} +STAT_FILE=${STAT_FILE:-$(mktemp --tmpdir -u leveldb_test_stats_XXXX)} + +function cleanup { + rm -rf $DATA_DIR + rm -f $STAT_FILE.fillseq + rm -f $STAT_FILE.readrandom + rm -f $STAT_FILE.overwrite +} + +trap cleanup EXIT + +function send_to_ods { + key="$1" + value="$2" + + if [ -z "$value" ];then + echo >&2 "ERROR: Key $key doesn't have a value." + return + fi + curl -s "https://www.intern.facebook.com/intern/agent/ods_set.php?entity=rocksdb_build&key=$key&value=$value" +} + +make clean +make db_bench -j$(nproc) + +./db_bench \ + --benchmarks=fillseq \ + --db=$DATA_DIR \ + --use_existing_db=0 \ + --bloom_bits=10 \ + --num=$NUM \ + --writes=$NUM \ + --cache_size=6442450944 \ + --cache_numshardbits=6 \ + --open_files=55000 \ + --statistics=1 \ + --histogram=1 \ + --disable_data_sync=1 \ + --disable_wal=1 \ + --sync=0 > ${STAT_FILE}.fillseq + +./db_bench \ + --benchmarks=overwrite \ + --db=$DATA_DIR \ + --use_existing_db=1 \ + --bloom_bits=10 \ + --num=$NUM \ + --writes=$((NUM / 2)) \ + --cache_size=6442450944 \ + --cache_numshardbits=6 \ + --open_files=55000 \ + --statistics=1 \ + --histogram=1 \ + --disable_data_sync=1 \ + --disable_wal=1 \ + --sync=0 \ + --threads=8 > ${STAT_FILE}.overwrite + +./db_bench \ + --benchmarks=readrandom \ + --db=$DATA_DIR \ + --use_existing_db=1 \ + --bloom_bits=10 \ + --num=$NUM \ + --reads=$((NUM / 100)) \ + --cache_size=6442450944 \ + --cache_numshardbits=6 \ + --open_files=55000 \ + --statistics=1 \ + --histogram=1 \ + --disable_data_sync=1 \ + --disable_wal=1 \ + --sync=0 \ + --threads=128 > ${STAT_FILE}.readrandom + +OVERWRITE_OPS=$(awk '/overwrite/ {print $5}' $STAT_FILE.overwrite) +FILLSEQ_OPS=$(awk '/fillseq/ {print $5}' $STAT_FILE.fillseq) +READRANDOM_OPS=$(awk '/readrandom/ {print $5}' $STAT_FILE.readrandom) + +send_to_ods rocksdb.build.overwrite.qps $OVERWRITE_OPS +send_to_ods rocksdb.build.fillseq.qps $FILLSEQ_OPS +send_to_ods rocksdb.build.readrandom.qps $READRANDOM_OPS diff --git a/scribe/if/gen-cpp/scribe.cpp b/scribe/if/gen-cpp/scribe.cpp new file mode 100644 index 00000000..c632e5a1 --- /dev/null +++ b/scribe/if/gen-cpp/scribe.cpp @@ -0,0 +1,1012 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "scribe.h" +#include "folly/ScopeGuard.h" + +namespace Tleveldb { + +uint32_t scribe_Log_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_LIST) { + { + this->messages.clear(); + uint32_t _size14; + apache::thrift::protocol::TType _etype17; + xfer += iprot->readListBegin(_etype17, _size14); + this->messages.resize(_size14); + uint32_t _i18; + for (_i18 = 0; _i18 < _size14; ++_i18) + { + xfer += this->messages[_i18].read(iprot); + } + xfer += iprot->readListEnd(); + } + this->__isset.messages = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t scribe_Log_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("scribe_Log_args"); + xfer += oprot->writeFieldBegin("messages", apache::thrift::protocol::T_LIST, 1); + { + xfer += oprot->writeListBegin(apache::thrift::protocol::T_STRUCT, this->messages.size()); + std::vector ::const_iterator _iter19; + for (_iter19 = this->messages.begin(); _iter19 != this->messages.end(); ++_iter19) + { + xfer += (*_iter19).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t scribe_Log_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("scribe_Log_pargs"); + xfer += oprot->writeFieldBegin("messages", apache::thrift::protocol::T_LIST, 1); + { + xfer += oprot->writeListBegin(apache::thrift::protocol::T_STRUCT, (*(this->messages)).size()); + std::vector ::const_iterator _iter20; + for (_iter20 = (*(this->messages)).begin(); _iter20 != (*(this->messages)).end(); ++_iter20) + { + xfer += (*_iter20).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t scribe_Log_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast21; + xfer += iprot->readI32(ecast21); + this->success = (ResultCode)ecast21; + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t scribe_Log_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("scribe_Log_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_I32, 0); + xfer += oprot->writeI32((int32_t)this->success); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t scribe_Log_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast22; + xfer += iprot->readI32(ecast22); + (*(this->success)) = (ResultCode)ecast22; + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t scribe_LogMulti_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_LIST) { + { + this->messages.clear(); + uint32_t _size23; + apache::thrift::protocol::TType _etype26; + xfer += iprot->readListBegin(_etype26, _size23); + this->messages.resize(_size23); + uint32_t _i27; + for (_i27 = 0; _i27 < _size23; ++_i27) + { + xfer += this->messages[_i27].read(iprot); + } + xfer += iprot->readListEnd(); + } + this->__isset.messages = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t scribe_LogMulti_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("scribe_LogMulti_args"); + xfer += oprot->writeFieldBegin("messages", apache::thrift::protocol::T_LIST, 1); + { + xfer += oprot->writeListBegin(apache::thrift::protocol::T_STRUCT, this->messages.size()); + std::vector ::const_iterator _iter28; + for (_iter28 = this->messages.begin(); _iter28 != this->messages.end(); ++_iter28) + { + xfer += (*_iter28).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t scribe_LogMulti_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("scribe_LogMulti_pargs"); + xfer += oprot->writeFieldBegin("messages", apache::thrift::protocol::T_LIST, 1); + { + xfer += oprot->writeListBegin(apache::thrift::protocol::T_STRUCT, (*(this->messages)).size()); + std::vector ::const_iterator _iter29; + for (_iter29 = (*(this->messages)).begin(); _iter29 != (*(this->messages)).end(); ++_iter29) + { + xfer += (*_iter29).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t scribe_LogMulti_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_LIST) { + { + this->success.clear(); + uint32_t _size30; + apache::thrift::protocol::TType _etype33; + xfer += iprot->readListBegin(_etype33, _size30); + this->success.resize(_size30); + uint32_t _i34; + for (_i34 = 0; _i34 < _size30; ++_i34) + { + int32_t ecast35; + xfer += iprot->readI32(ecast35); + this->success[_i34] = (ResultCode)ecast35; + } + xfer += iprot->readListEnd(); + } + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t scribe_LogMulti_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("scribe_LogMulti_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_LIST, 0); + { + xfer += oprot->writeListBegin(apache::thrift::protocol::T_I32, this->success.size()); + std::vector ::const_iterator _iter36; + for (_iter36 = this->success.begin(); _iter36 != this->success.end(); ++_iter36) + { + xfer += oprot->writeI32((int32_t)(*_iter36)); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t scribe_LogMulti_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_LIST) { + { + (*(this->success)).clear(); + uint32_t _size37; + apache::thrift::protocol::TType _etype40; + xfer += iprot->readListBegin(_etype40, _size37); + (*(this->success)).resize(_size37); + uint32_t _i41; + for (_i41 = 0; _i41 < _size37; ++_i41) + { + int32_t ecast42; + xfer += iprot->readI32(ecast42); + (*(this->success))[_i41] = (ResultCode)ecast42; + } + xfer += iprot->readListEnd(); + } + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t scribe_LogCompressedMsg_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->compressedMessages); + this->__isset.compressedMessages = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t scribe_LogCompressedMsg_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("scribe_LogCompressedMsg_args"); + xfer += oprot->writeFieldBegin("compressedMessages", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary(this->compressedMessages); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t scribe_LogCompressedMsg_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("scribe_LogCompressedMsg_pargs"); + xfer += oprot->writeFieldBegin("compressedMessages", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary((*(this->compressedMessages))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t scribe_LogCompressedMsg_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast43; + xfer += iprot->readI32(ecast43); + this->success = (ResultCode)ecast43; + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t scribe_LogCompressedMsg_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("scribe_LogCompressedMsg_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_I32, 0); + xfer += oprot->writeI32((int32_t)this->success); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t scribe_LogCompressedMsg_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast44; + xfer += iprot->readI32(ecast44); + (*(this->success)) = (ResultCode)ecast44; + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +int32_t scribeClient::getNextSendSequenceId() +{ + return nextSendSequenceId_++; +} + +int32_t scribeClient::getNextRecvSequenceId() +{ + return nextRecvSequenceId_++; +} + +ResultCode scribeClient::Log(const std::vector & messages) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("scribe.Log", NULL); + + try { + send_Log(messages); + return recv_Log(); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "scribe.Log"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "scribe.Log"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void scribeClient::send_Log(const std::vector & messages) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "scribe.Log"); + oprot_->writeMessageBegin("Log", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + scribe_Log_pargs args; + args.messages = &messages; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes45 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "scribe.Log", _bytes45); + return; +} + +ResultCode scribeClient::recv_Log() +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "scribe.Log"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("Log") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + ResultCode _return; + scribe_Log_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "scribe.Log", bytes); + + if (result.__isset.success) { + return _return; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "Log failed: unknown result"); +} + +void scribeClient::LogMulti(std::vector & _return, const std::vector & messages) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("scribe.LogMulti", NULL); + + try { + send_LogMulti(messages); + recv_LogMulti(_return); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "scribe.LogMulti"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "scribe.LogMulti"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void scribeClient::send_LogMulti(const std::vector & messages) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "scribe.LogMulti"); + oprot_->writeMessageBegin("LogMulti", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + scribe_LogMulti_pargs args; + args.messages = &messages; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes46 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "scribe.LogMulti", _bytes46); + return; +} + +void scribeClient::recv_LogMulti(std::vector & _return) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "scribe.LogMulti"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("LogMulti") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + scribe_LogMulti_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "scribe.LogMulti", bytes); + + if (result.__isset.success) { + // _return pointer has now been filled + return; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "LogMulti failed: unknown result"); +} + +ResultCode scribeClient::LogCompressedMsg(const std::string& compressedMessages) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("scribe.LogCompressedMsg", NULL); + + try { + send_LogCompressedMsg(compressedMessages); + return recv_LogCompressedMsg(); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "scribe.LogCompressedMsg"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "scribe.LogCompressedMsg"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void scribeClient::send_LogCompressedMsg(const std::string& compressedMessages) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "scribe.LogCompressedMsg"); + oprot_->writeMessageBegin("LogCompressedMsg", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + scribe_LogCompressedMsg_pargs args; + args.compressedMessages = &compressedMessages; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes47 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "scribe.LogCompressedMsg", _bytes47); + return; +} + +ResultCode scribeClient::recv_LogCompressedMsg() +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "scribe.LogCompressedMsg"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("LogCompressedMsg") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + ResultCode _return; + scribe_LogCompressedMsg_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "scribe.LogCompressedMsg", bytes); + + if (result.__isset.success) { + return _return; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "LogCompressedMsg failed: unknown result"); +} + +bool scribeProcessor::dispatchCall(::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, const std::string& fname, int32_t seqid, apache::thrift::server::TConnectionContext* connectionContext) { + ProcessMap::iterator pfn; + pfn = processMap_.find(fname); + if (pfn == processMap_.end()) { + iprot->skip(apache::thrift::protocol::T_STRUCT); + iprot->readMessageEnd(); + iprot->getTransport()->readEnd(); + apache::thrift::TApplicationException x(apache::thrift::TApplicationException::UNKNOWN_METHOD, "Invalid method name: '"+fname+"'"); + oprot->writeMessageBegin(fname, apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return true; + } + const ProcessFunction& pf = pfn->second; + (this->*pf)(seqid, iprot, oprot, connectionContext); + return true; +} + +void scribeProcessor::process_Log(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("scribe.Log", connectionContext)); + + this->preRead(ctx.get(), "scribe.Log"); + scribe_Log_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "scribe.Log", bytes); + + scribe_Log_result result; + try { + result.success = iface_->Log(args.messages); + result.__isset.success = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "scribe.Log"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("Log", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "scribe.Log"); + oprot->writeMessageBegin("Log", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "scribe.Log", bytes); + +} + +void scribeProcessor::process_LogMulti(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("scribe.LogMulti", connectionContext)); + + this->preRead(ctx.get(), "scribe.LogMulti"); + scribe_LogMulti_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "scribe.LogMulti", bytes); + + scribe_LogMulti_result result; + try { + iface_->LogMulti(result.success, args.messages); + result.__isset.success = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "scribe.LogMulti"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("LogMulti", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "scribe.LogMulti"); + oprot->writeMessageBegin("LogMulti", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "scribe.LogMulti", bytes); + +} + +void scribeProcessor::process_LogCompressedMsg(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("scribe.LogCompressedMsg", connectionContext)); + + this->preRead(ctx.get(), "scribe.LogCompressedMsg"); + scribe_LogCompressedMsg_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "scribe.LogCompressedMsg", bytes); + + scribe_LogCompressedMsg_result result; + try { + result.success = iface_->LogCompressedMsg(args.compressedMessages); + result.__isset.success = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "scribe.LogCompressedMsg"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("LogCompressedMsg", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "scribe.LogCompressedMsg"); + oprot->writeMessageBegin("LogCompressedMsg", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "scribe.LogCompressedMsg", bytes); + +} + +::boost::shared_ptr< ::apache::thrift::TProcessor > scribeProcessorFactory::getProcessor(::apache::thrift::server::TConnectionContext* ctx) { + ::apache::thrift::ReleaseHandler< scribeIfFactory > cleanup(handlerFactory_); + ::boost::shared_ptr< scribeIf > handler(handlerFactory_->getHandler(ctx), cleanup); + ::boost::shared_ptr< ::apache::thrift::TProcessor > processor(new scribeProcessor(handler)); + return processor; +} +} // namespace diff --git a/scribe/if/gen-cpp/scribe.h b/scribe/if/gen-cpp/scribe.h new file mode 100644 index 00000000..5f30edfb --- /dev/null +++ b/scribe/if/gen-cpp/scribe.h @@ -0,0 +1,593 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef _Tleveldb_scribe_H +#define _Tleveldb_scribe_H + +#include +#include "scribe_types.h" + +namespace Tleveldb { + +class scribeIf { + public: + virtual ~scribeIf() {} + virtual ResultCode Log(const std::vector & messages) = 0; + virtual void LogMulti(std::vector & _return, const std::vector & messages) = 0; + virtual ResultCode LogCompressedMsg(const std::string& compressedMessages) = 0; +}; + +class scribeIfFactory { + public: + typedef scribeIf Handler; + + virtual ~scribeIfFactory() {} + + virtual scribeIf* getHandler(::apache::thrift::server::TConnectionContext* ctx) = 0; + virtual void releaseHandler(scribeIf* handler) = 0; +}; + +class scribeIfSingletonFactory : virtual public scribeIfFactory { + public: + scribeIfSingletonFactory(const boost::shared_ptr& iface) : iface_(iface) {} + virtual ~scribeIfSingletonFactory() {} + + virtual scribeIf* getHandler(::apache::thrift::server::TConnectionContext*) { + return iface_.get(); + } + virtual void releaseHandler(scribeIf* handler) {} + + protected: + boost::shared_ptr iface_; +}; + +class scribeNull : virtual public scribeIf { + public: + virtual ~scribeNull() {} + ResultCode Log(const std::vector & /* messages */) { + ResultCode _return = (ResultCode)0; + return _return; + } + void LogMulti(std::vector & /* _return */, const std::vector & /* messages */) { + return; + } + ResultCode LogCompressedMsg(const std::string& /* compressedMessages */) { + ResultCode _return = (ResultCode)0; + return _return; + } +}; + +class scribe_Log_args { + public: + + static const uint64_t _reflection_id = 5902265217339133004U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + scribe_Log_args() { + } + + scribe_Log_args(const scribe_Log_args&) = default; + scribe_Log_args& operator=(const scribe_Log_args&) = default; + scribe_Log_args(scribe_Log_args&&) = default; + scribe_Log_args& operator=(scribe_Log_args&&) = default; + + void __clear() { + messages.clear(); + __isset.__clear(); + } + + virtual ~scribe_Log_args() throw() {} + + std::vector messages; + + struct __isset { + __isset() { __clear(); } + void __clear() { + messages = false; + } + bool messages; + } __isset; + + bool operator == (const scribe_Log_args & rhs) const + { + if (!(this->messages == rhs.messages)) + return false; + return true; + } + bool operator != (const scribe_Log_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const scribe_Log_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class scribe_Log_pargs { + public: + + static const uint64_t _reflection_id = 5555604010648986412U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~scribe_Log_pargs() throw() {} + + const std::vector * messages; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class scribe_Log_result { + public: + + static const uint64_t _reflection_id = 18205781396971565932U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + scribe_Log_result() : success(static_cast(0)) { + } + + scribe_Log_result(const scribe_Log_result&) = default; + scribe_Log_result& operator=(const scribe_Log_result&) = default; + scribe_Log_result(scribe_Log_result&&) = default; + scribe_Log_result& operator=(scribe_Log_result&&) = default; + + void __clear() { + success = static_cast(0); + __isset.__clear(); + } + + virtual ~scribe_Log_result() throw() {} + + ResultCode success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + bool operator == (const scribe_Log_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + return true; + } + bool operator != (const scribe_Log_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const scribe_Log_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class scribe_Log_presult { + public: + + static const uint64_t _reflection_id = 12945584136895385836U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~scribe_Log_presult() throw() {} + + ResultCode* success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class scribe_LogMulti_args { + public: + + static const uint64_t _reflection_id = 7590876486278061516U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + scribe_LogMulti_args() { + } + + scribe_LogMulti_args(const scribe_LogMulti_args&) = default; + scribe_LogMulti_args& operator=(const scribe_LogMulti_args&) = default; + scribe_LogMulti_args(scribe_LogMulti_args&&) = default; + scribe_LogMulti_args& operator=(scribe_LogMulti_args&&) = default; + + void __clear() { + messages.clear(); + __isset.__clear(); + } + + virtual ~scribe_LogMulti_args() throw() {} + + std::vector messages; + + struct __isset { + __isset() { __clear(); } + void __clear() { + messages = false; + } + bool messages; + } __isset; + + bool operator == (const scribe_LogMulti_args & rhs) const + { + if (!(this->messages == rhs.messages)) + return false; + return true; + } + bool operator != (const scribe_LogMulti_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const scribe_LogMulti_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class scribe_LogMulti_pargs { + public: + + static const uint64_t _reflection_id = 9124384543551655628U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~scribe_LogMulti_pargs() throw() {} + + const std::vector * messages; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class scribe_LogMulti_result { + public: + + static const uint64_t _reflection_id = 4828367046341273164U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + scribe_LogMulti_result() { + } + + scribe_LogMulti_result(const scribe_LogMulti_result&) = default; + scribe_LogMulti_result& operator=(const scribe_LogMulti_result&) = default; + scribe_LogMulti_result(scribe_LogMulti_result&&) = default; + scribe_LogMulti_result& operator=(scribe_LogMulti_result&&) = default; + + void __clear() { + success.clear(); + __isset.__clear(); + } + + virtual ~scribe_LogMulti_result() throw() {} + + std::vector success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + bool operator == (const scribe_LogMulti_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + return true; + } + bool operator != (const scribe_LogMulti_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const scribe_LogMulti_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class scribe_LogMulti_presult { + public: + + static const uint64_t _reflection_id = 5642041737363050316U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~scribe_LogMulti_presult() throw() {} + + std::vector * success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class scribe_LogCompressedMsg_args { + public: + + static const uint64_t _reflection_id = 12705053036625273964U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + scribe_LogCompressedMsg_args() : compressedMessages("") { + } + + scribe_LogCompressedMsg_args(const scribe_LogCompressedMsg_args&) = default; + scribe_LogCompressedMsg_args& operator=(const scribe_LogCompressedMsg_args&) = default; + scribe_LogCompressedMsg_args(scribe_LogCompressedMsg_args&&) = default; + scribe_LogCompressedMsg_args& operator=(scribe_LogCompressedMsg_args&&) = default; + + void __clear() { + compressedMessages = ""; + __isset.__clear(); + } + + virtual ~scribe_LogCompressedMsg_args() throw() {} + + std::string compressedMessages; + + struct __isset { + __isset() { __clear(); } + void __clear() { + compressedMessages = false; + } + bool compressedMessages; + } __isset; + + bool operator == (const scribe_LogCompressedMsg_args & rhs) const + { + if (!(this->compressedMessages == rhs.compressedMessages)) + return false; + return true; + } + bool operator != (const scribe_LogCompressedMsg_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const scribe_LogCompressedMsg_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class scribe_LogCompressedMsg_pargs { + public: + + static const uint64_t _reflection_id = 13645577436870531500U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~scribe_LogCompressedMsg_pargs() throw() {} + + const std::string* compressedMessages; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class scribe_LogCompressedMsg_result { + public: + + static const uint64_t _reflection_id = 15026639991904524972U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + scribe_LogCompressedMsg_result() : success(static_cast(0)) { + } + + scribe_LogCompressedMsg_result(const scribe_LogCompressedMsg_result&) = default; + scribe_LogCompressedMsg_result& operator=(const scribe_LogCompressedMsg_result&) = default; + scribe_LogCompressedMsg_result(scribe_LogCompressedMsg_result&&) = default; + scribe_LogCompressedMsg_result& operator=(scribe_LogCompressedMsg_result&&) = default; + + void __clear() { + success = static_cast(0); + __isset.__clear(); + } + + virtual ~scribe_LogCompressedMsg_result() throw() {} + + ResultCode success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + bool operator == (const scribe_LogCompressedMsg_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + return true; + } + bool operator != (const scribe_LogCompressedMsg_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const scribe_LogCompressedMsg_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class scribe_LogCompressedMsg_presult { + public: + + static const uint64_t _reflection_id = 5311776576442573772U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~scribe_LogCompressedMsg_presult() throw() {} + + ResultCode* success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class scribeClient : virtual public scribeIf, virtual public apache::thrift::TClientBase { + public: + scribeClient(boost::shared_ptr prot) : + checkSeqid_(true), + nextSendSequenceId_(1), + nextRecvSequenceId_(1), + piprot_(prot), + poprot_(prot) { + iprot_ = prot.get(); + oprot_ = prot.get(); + } + scribeClient(boost::shared_ptr iprot, boost::shared_ptr oprot) : + checkSeqid_(true), + nextSendSequenceId_(1), + nextRecvSequenceId_(1), + piprot_(iprot), + poprot_(oprot) { + iprot_ = iprot.get(); + oprot_ = oprot.get(); + } + boost::shared_ptr getInputProtocol() { + return piprot_; + } + boost::shared_ptr getOutputProtocol() { + return poprot_; + } + ResultCode Log(const std::vector & messages); + void send_Log(const std::vector & messages); + ResultCode recv_Log(); + void LogMulti(std::vector & _return, const std::vector & messages); + void send_LogMulti(const std::vector & messages); + void recv_LogMulti(std::vector & _return); + ResultCode LogCompressedMsg(const std::string& compressedMessages); + void send_LogCompressedMsg(const std::string& compressedMessages); + ResultCode recv_LogCompressedMsg(); + + /** + * Disable checking the seqid field in server responses. + * + * This should only be used with broken servers that return incorrect seqid values. + */ + void _disableSequenceIdChecks() { + checkSeqid_ = false; + } + + protected: + bool checkSeqid_; + int32_t nextSendSequenceId_; + int32_t nextRecvSequenceId_; + int32_t getNextSendSequenceId(); + int32_t getNextRecvSequenceId(); + boost::shared_ptr piprot_; + boost::shared_ptr poprot_; + apache::thrift::protocol::TProtocol* iprot_; + apache::thrift::protocol::TProtocol* oprot_; +}; + +class scribeProcessor : public ::apache::thrift::TDispatchProcessor { + protected: + boost::shared_ptr iface_; + virtual bool dispatchCall(apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, const std::string& fname, int32_t seqid, apache::thrift::server::TConnectionContext* connectionContext); + private: + typedef void (scribeProcessor::*ProcessFunction)(int32_t, apache::thrift::protocol::TProtocol*, apache::thrift::protocol::TProtocol*, apache::thrift::server::TConnectionContext*); + typedef std::map ProcessMap; + ProcessMap processMap_; + void process_Log(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + void process_LogMulti(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + void process_LogCompressedMsg(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + public: + scribeProcessor(boost::shared_ptr iface) : + iface_(iface) { + processMap_["Log"] = &scribeProcessor::process_Log; + processMap_["LogMulti"] = &scribeProcessor::process_LogMulti; + processMap_["LogCompressedMsg"] = &scribeProcessor::process_LogCompressedMsg; + } + + virtual ~scribeProcessor() {} + + boost::shared_ptr > getProcessFunctions() { + boost::shared_ptr > rSet(new std::set()); + rSet->insert("scribe.Log"); + rSet->insert("scribe.LogMulti"); + rSet->insert("scribe.LogCompressedMsg"); + return rSet; + } +}; + +class scribeProcessorFactory : public ::apache::thrift::TProcessorFactory { + public: + scribeProcessorFactory(const ::boost::shared_ptr< scribeIfFactory >& handlerFactory) : + handlerFactory_(handlerFactory) {} + + ::boost::shared_ptr< ::apache::thrift::TProcessor > getProcessor(::apache::thrift::server::TConnectionContext* ctx); + + protected: + ::boost::shared_ptr< scribeIfFactory > handlerFactory_; +}; + +class scribeMultiface : virtual public scribeIf { + public: + scribeMultiface(std::vector >& ifaces) : ifaces_(ifaces) { + } + virtual ~scribeMultiface() {} + protected: + std::vector > ifaces_; + scribeMultiface() {} + void add(boost::shared_ptr iface) { + ifaces_.push_back(iface); + } + public: + ResultCode Log(const std::vector & messages) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz - 1; ++i) { + ifaces_[i]->Log(messages); + } + return ifaces_[i]->Log(messages); + } + + void LogMulti(std::vector & _return, const std::vector & messages) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz; ++i) { + ifaces_[i]->LogMulti(_return, messages); + } + } + + ResultCode LogCompressedMsg(const std::string& compressedMessages) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz - 1; ++i) { + ifaces_[i]->LogCompressedMsg(compressedMessages); + } + return ifaces_[i]->LogCompressedMsg(compressedMessages); + } + +}; + +} // namespace + +#endif diff --git a/scribe/if/gen-cpp/scribe_constants.cpp b/scribe/if/gen-cpp/scribe_constants.cpp new file mode 100644 index 00000000..048069b5 --- /dev/null +++ b/scribe/if/gen-cpp/scribe_constants.cpp @@ -0,0 +1,17 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "scribe_constants.h" + +namespace Tleveldb { + +const scribeConstants g_scribe_constants; + +scribeConstants::scribeConstants() { + SCRIBE_MAX_MESSAGE_LENGTH = 26214400; +} + +} // namespace diff --git a/scribe/if/gen-cpp/scribe_constants.h b/scribe/if/gen-cpp/scribe_constants.h new file mode 100644 index 00000000..f1210808 --- /dev/null +++ b/scribe/if/gen-cpp/scribe_constants.h @@ -0,0 +1,25 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef scribe_CONSTANTS_H +#define scribe_CONSTANTS_H + +#include "scribe_types.h" + +namespace Tleveldb { + +class scribeConstants { + public: + scribeConstants(); + + int32_t SCRIBE_MAX_MESSAGE_LENGTH; +}; + +extern const scribeConstants g_scribe_constants; + +} // namespace + +#endif diff --git a/scribe/if/gen-cpp/scribe_types.cpp b/scribe/if/gen-cpp/scribe_types.cpp new file mode 100644 index 00000000..a72d36f2 --- /dev/null +++ b/scribe/if/gen-cpp/scribe_types.cpp @@ -0,0 +1,513 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "scribe_types.h" + +#include +#include +#include + +namespace Tleveldb { + +int _kResultCodeValues[] = { + OK, + TRY_LATER, + ERROR_DECOMPRESS +}; + +const char* _kResultCodeNames[] = { + "OK", + "TRY_LATER", + "ERROR_DECOMPRESS" +}; + +const std::map _ResultCode_VALUES_TO_NAMES(apache::thrift::TEnumIterator(3, _kResultCodeValues, _kResultCodeNames), apache::thrift::TEnumIterator(-1, NULL, NULL)); + +const std::map _ResultCode_NAMES_TO_VALUES(apache::thrift::TEnumInverseIterator(3, _kResultCodeValues, _kResultCodeNames), apache::thrift::TEnumInverseIterator(-1, NULL, NULL)); + +} // namespace +namespace apache { namespace thrift { +template<> +const char* TEnumTraits< ::Tleveldb::ResultCode>::findName( ::Tleveldb::ResultCode value) { +return findName( ::Tleveldb::_ResultCode_VALUES_TO_NAMES, value); +} + +template<> +bool TEnumTraits< ::Tleveldb::ResultCode>::findValue(const char* name, ::Tleveldb::ResultCode* out) { +return findValue( ::Tleveldb::_ResultCode_NAMES_TO_VALUES, name, out); +} +}} // apache::thrift + +namespace Tleveldb { +// Reflection initializer for struct scribe.SourceInfo +namespace { +void reflectionInitializer_16557823557777806572(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 16557823557777806572U; + if (schema.dataTypes.count(id)) return; + ::apache::thrift::reflection::DataType dt; + dt.name = "struct scribe.SourceInfo"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 1U; + f.name = "host"; + dt.fields[1] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 5U; + f.name = "port"; + dt.fields[2] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 6U; + f.name = "timestamp"; + dt.fields[3] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t SourceInfo::_reflection_id; +void SourceInfo::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_16557823557777806572(schema); +} +uint32_t SourceInfo::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->host); + this->__isset.host = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->port); + this->__isset.port = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->timestamp); + this->__isset.timestamp = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t SourceInfo::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("SourceInfo"); + xfer += oprot->writeFieldBegin("host", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary(this->host); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("port", apache::thrift::protocol::T_I32, 2); + xfer += oprot->writeI32(this->port); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("timestamp", apache::thrift::protocol::T_I64, 3); + xfer += oprot->writeI64(this->timestamp); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(SourceInfo &a, SourceInfo &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.host, b.host); + swap(a.port, b.port); + swap(a.timestamp, b.timestamp); + swap(a.__isset, b.__isset); +} + +// Reflection initializer for map +namespace { +void reflectionInitializer_9246346592659763371(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 9246346592659763371U; + if (schema.dataTypes.count(id)) return; + ::apache::thrift::reflection::DataType dt; + dt.name = "map"; + dt.__isset.mapKeyType = true; + dt.mapKeyType = 1U; + dt.__isset.valueType = true; + dt.valueType = 1U; + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +// Reflection initializer for struct scribe.LogEntry +namespace { +void reflectionInitializer_15053466696968532300(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 15053466696968532300U; + if (schema.dataTypes.count(id)) return; + reflectionInitializer_16557823557777806572(schema); // struct scribe.SourceInfo + reflectionInitializer_9246346592659763371(schema); // map + ::apache::thrift::reflection::DataType dt; + dt.name = "struct scribe.LogEntry"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 1U; + f.name = "category"; + dt.fields[1] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 1U; + f.name = "message"; + dt.fields[2] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = false; + f.type = 9246346592659763371U; + f.name = "metadata"; + dt.fields[3] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = false; + f.type = 5U; + f.name = "checksum"; + dt.fields[4] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = false; + f.type = 16557823557777806572U; + f.name = "source"; + dt.fields[5] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = false; + f.type = 5U; + f.name = "bucket"; + dt.fields[6] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t LogEntry::_reflection_id; +void LogEntry::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_15053466696968532300(schema); +} +uint32_t LogEntry::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->category); + this->__isset.category = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->message); + this->__isset.message = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == apache::thrift::protocol::T_MAP) { + { + this->metadata.clear(); + uint32_t _size0; + apache::thrift::protocol::TType _ktype1; + apache::thrift::protocol::TType _vtype2; + xfer += iprot->readMapBegin(_ktype1, _vtype2, _size0); + uint32_t _i4; + for (_i4 = 0; _i4 < _size0; ++_i4) + { + std::string _key5; + xfer += iprot->readString(_key5); + std::string& _val6 = this->metadata[_key5]; + xfer += iprot->readString(_val6); + } + xfer += iprot->readMapEnd(); + } + this->__isset.metadata = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->checksum); + this->__isset.checksum = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 5: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->source.read(iprot); + this->__isset.source = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 6: + if (ftype == apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->bucket); + this->__isset.bucket = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t LogEntry::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("LogEntry"); + xfer += oprot->writeFieldBegin("category", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary(this->category); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("message", apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeBinary(this->message); + xfer += oprot->writeFieldEnd(); + if (this->__isset.metadata) { + xfer += oprot->writeFieldBegin("metadata", apache::thrift::protocol::T_MAP, 3); + { + xfer += oprot->writeMapBegin(apache::thrift::protocol::T_STRING, apache::thrift::protocol::T_STRING, this->metadata.size()); + std::map ::const_iterator _iter7; + for (_iter7 = this->metadata.begin(); _iter7 != this->metadata.end(); ++_iter7) + { + xfer += oprot->writeString(_iter7->first); + xfer += oprot->writeString(_iter7->second); + } + xfer += oprot->writeMapEnd(); + } + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.checksum) { + xfer += oprot->writeFieldBegin("checksum", apache::thrift::protocol::T_I32, 4); + xfer += oprot->writeI32(this->checksum); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.source) { + xfer += oprot->writeFieldBegin("source", apache::thrift::protocol::T_STRUCT, 5); + xfer += this->source.write(oprot); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.bucket) { + xfer += oprot->writeFieldBegin("bucket", apache::thrift::protocol::T_I32, 6); + xfer += oprot->writeI32(this->bucket); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(LogEntry &a, LogEntry &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.category, b.category); + swap(a.message, b.message); + swap(a.metadata, b.metadata); + swap(a.checksum, b.checksum); + swap(a.source, b.source); + swap(a.bucket, b.bucket); + swap(a.__isset, b.__isset); +} + +// Reflection initializer for list +namespace { +void reflectionInitializer_10251729064312664553(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 10251729064312664553U; + if (schema.dataTypes.count(id)) return; + reflectionInitializer_15053466696968532300(schema); // struct scribe.LogEntry + ::apache::thrift::reflection::DataType dt; + dt.name = "list"; + dt.__isset.valueType = true; + dt.valueType = 15053466696968532300U; + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +// Reflection initializer for struct scribe.MessageList +namespace { +void reflectionInitializer_5674270912483072844(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 5674270912483072844U; + if (schema.dataTypes.count(id)) return; + reflectionInitializer_10251729064312664553(schema); // list + ::apache::thrift::reflection::DataType dt; + dt.name = "struct scribe.MessageList"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 10251729064312664553U; + f.name = "messages"; + dt.fields[1] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t MessageList::_reflection_id; +void MessageList::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_5674270912483072844(schema); +} +uint32_t MessageList::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_LIST) { + { + this->messages.clear(); + uint32_t _size8; + apache::thrift::protocol::TType _etype11; + xfer += iprot->readListBegin(_etype11, _size8); + this->messages.resize(_size8); + uint32_t _i12; + for (_i12 = 0; _i12 < _size8; ++_i12) + { + xfer += this->messages[_i12].read(iprot); + } + xfer += iprot->readListEnd(); + } + this->__isset.messages = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MessageList::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("MessageList"); + xfer += oprot->writeFieldBegin("messages", apache::thrift::protocol::T_LIST, 1); + { + xfer += oprot->writeListBegin(apache::thrift::protocol::T_STRUCT, this->messages.size()); + std::vector ::const_iterator _iter13; + for (_iter13 = this->messages.begin(); _iter13 != this->messages.end(); ++_iter13) + { + xfer += (*_iter13).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(MessageList &a, MessageList &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.messages, b.messages); + swap(a.__isset, b.__isset); +} + +} // namespace diff --git a/scribe/if/gen-cpp/scribe_types.h b/scribe/if/gen-cpp/scribe_types.h new file mode 100644 index 00000000..bf75a43e --- /dev/null +++ b/scribe/if/gen-cpp/scribe_types.h @@ -0,0 +1,247 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef scribe_TYPES_H +#define scribe_TYPES_H + +#include +#include +#include +#include + +namespace apache { namespace thrift { namespace reflection { +class Schema; +}}} + + +namespace Tleveldb { + +enum ResultCode { + OK = 0, + TRY_LATER = 1, + ERROR_DECOMPRESS = 2 +}; + +extern const std::map _ResultCode_VALUES_TO_NAMES; + +extern const std::map _ResultCode_NAMES_TO_VALUES; + +} // namespace +namespace apache { namespace thrift { +template<> +inline constexpr ::Tleveldb::ResultCode TEnumTraits< ::Tleveldb::ResultCode>::min() { +return ::Tleveldb::ResultCode::OK; +} +template<> +inline constexpr ::Tleveldb::ResultCode TEnumTraits< ::Tleveldb::ResultCode>::max() { +return ::Tleveldb::ResultCode::ERROR_DECOMPRESS; +} +}} // apache:thrift + +namespace Tleveldb { +class SourceInfo { + public: + + static const uint64_t _reflection_id = 16557823557777806572U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + SourceInfo() : host(""), port(0), timestamp(0) { + } + + SourceInfo(const SourceInfo&) = default; + SourceInfo& operator=(const SourceInfo&) = default; + SourceInfo(SourceInfo&&) = default; + SourceInfo& operator=(SourceInfo&&) = default; + + void __clear() { + host = ""; + port = 0; + timestamp = 0; + __isset.__clear(); + } + + virtual ~SourceInfo() throw() {} + + std::string host; + int32_t port; + int64_t timestamp; + + struct __isset { + __isset() { __clear(); } + void __clear() { + host = false; + port = false; + timestamp = false; + } + bool host; + bool port; + bool timestamp; + } __isset; + + bool operator == (const SourceInfo & rhs) const + { + if (!(this->host == rhs.host)) + return false; + if (!(this->port == rhs.port)) + return false; + if (!(this->timestamp == rhs.timestamp)) + return false; + return true; + } + bool operator != (const SourceInfo &rhs) const { + return !(*this == rhs); + } + + bool operator < (const SourceInfo & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class SourceInfo; +void swap(SourceInfo &a, SourceInfo &b); + +class LogEntry { + public: + + static const uint64_t _reflection_id = 15053466696968532300U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + LogEntry() : category(""), message(""), checksum(0), bucket(0) { + } + + LogEntry(const LogEntry&) = default; + LogEntry& operator=(const LogEntry&) = default; + LogEntry(LogEntry&&) = default; + LogEntry& operator=(LogEntry&&) = default; + + void __clear() { + category = ""; + message = ""; + metadata.clear(); + checksum = 0; + source.__clear(); + bucket = 0; + __isset.__clear(); + } + + virtual ~LogEntry() throw() {} + + std::string category; + std::string message; + std::map metadata; + int32_t checksum; + SourceInfo source; + int32_t bucket; + + struct __isset { + __isset() { __clear(); } + void __clear() { + category = false; + message = false; + metadata = false; + checksum = false; + source = false; + bucket = false; + } + bool category; + bool message; + bool metadata; + bool checksum; + bool source; + bool bucket; + } __isset; + + bool operator == (const LogEntry & rhs) const + { + if (!(this->category == rhs.category)) + return false; + if (!(this->message == rhs.message)) + return false; + if (__isset.metadata != rhs.__isset.metadata) + return false; + else if (__isset.metadata && !(metadata == rhs.metadata)) + return false; + if (__isset.checksum != rhs.__isset.checksum) + return false; + else if (__isset.checksum && !(checksum == rhs.checksum)) + return false; + if (__isset.source != rhs.__isset.source) + return false; + else if (__isset.source && !(source == rhs.source)) + return false; + if (__isset.bucket != rhs.__isset.bucket) + return false; + else if (__isset.bucket && !(bucket == rhs.bucket)) + return false; + return true; + } + bool operator != (const LogEntry &rhs) const { + return !(*this == rhs); + } + + bool operator < (const LogEntry & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class LogEntry; +void swap(LogEntry &a, LogEntry &b); + +class MessageList { + public: + + static const uint64_t _reflection_id = 5674270912483072844U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + MessageList() { + } + + MessageList(const MessageList&) = default; + MessageList& operator=(const MessageList&) = default; + MessageList(MessageList&&) = default; + MessageList& operator=(MessageList&&) = default; + + void __clear() { + messages.clear(); + __isset.__clear(); + } + + virtual ~MessageList() throw() {} + + std::vector messages; + + struct __isset { + __isset() { __clear(); } + void __clear() { + messages = false; + } + bool messages; + } __isset; + + bool operator == (const MessageList & rhs) const + { + if (!(this->messages == rhs.messages)) + return false; + return true; + } + bool operator != (const MessageList &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MessageList & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class MessageList; +void swap(MessageList &a, MessageList &b); + +} // namespace + +#endif diff --git a/scribe/if/scribe.thrift b/scribe/if/scribe.thrift new file mode 100644 index 00000000..df09a5e7 --- /dev/null +++ b/scribe/if/scribe.thrift @@ -0,0 +1,82 @@ +#!/usr/local/bin/thrift --cpp --php + +## Copyright (c) 2007-2012 Facebook +## +## Licensed under the Apache License, Version 2.0 (the "License"); +## you may not use this file except in compliance with the License. +## You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## +## See accompanying file LICENSE or visit the Scribe site at: +## http://developers.facebook.com/scribe/ + +namespace cpp Tleveldb +namespace java Tleveldb + +// Max message length allowed to log through scribe +const i32 SCRIBE_MAX_MESSAGE_LENGTH = 26214400; + +enum ResultCode +{ + OK, + TRY_LATER, + ERROR_DECOMPRESS +} + +struct SourceInfo +{ + 1: binary host, + 2: i32 port, + 3: i64 timestamp +} + +struct LogEntry +{ + 1: binary category, + 2: binary message, + 3: optional map metadata, + 4: optional i32 checksum, + 5: optional SourceInfo source, + 6: optional i32 bucket +} + +struct MessageList +{ + 1: list messages +} + +service scribe +{ + # + # Delivers a list of LogEntry messages to the Scribe server. + # A returned ResultCode of anything other than OK indicates that the + # whole batch was unable to be delivered to the server. + # If data loss is a concern, the caller should buffer and retry the messages. + # + ResultCode Log(1: list messages); + + # + # NOTE: FOR INTERNAL USE ONLY! + # + # Delivers a list of LogEntry messages to the Scribe server, but + # allows partial successes. A list of ResultCodes will be returned to + # indicate the success or failure of each message at the corresponding index. + # If data loss is a concern, the caller should retry only the failed messages. + # + list LogMulti(1: list messages); + + # + # NOTE: FOR INTERNAL USE ONLY! + # + # The same as Log(...) except that the list of messages must first be + # serialized and compressed in some internal format. + # + ResultCode LogCompressedMsg(1: binary compressedMessages); +} diff --git a/scribe/scribe_logger.cc b/scribe/scribe_logger.cc new file mode 100644 index 00000000..e39f7f4b --- /dev/null +++ b/scribe/scribe_logger.cc @@ -0,0 +1,82 @@ +#include "scribe_logger.h" + +namespace leveldb { + +const std::string ScribeLogger::COL_SEPERATOR = "\x1"; +const std::string ScribeLogger::DEPLOY_STATS_CATEGORY = "leveldb_deploy_stats"; + +ScribeLogger::ScribeLogger(const std::string& host, int port, + int retry_times, uint32_t retry_intervals) + : host_(host), + port_(port), + retry_times_(retry_times), + retry_intervals_ (retry_intervals) { + shared_ptr socket(new TSocket(host_, port_)); + shared_ptr framedTransport(new TFramedTransport(socket)); + framedTransport->open(); + shared_ptr protocol(new TBinaryProtocol(framedTransport)); + scribe_client_ = new scribeClient(protocol); +} + +void ScribeLogger::Log(const std::string& category, + const std::string& message) { + LogEntry entry; + entry.category = category; + entry.message = message; + + std::vector logs; + logs.push_back(entry); + + logger_mutex_.Lock(); + ResultCode ret = scribe_client_->Log(logs); + int retries_left = retry_times_; + while (ret == TRY_LATER && retries_left > 0) { + Env::Default()->SleepForMicroseconds(retry_intervals_); + ret = scribe_client_->Log(logs); + retries_left--; + } + + logger_mutex_.Unlock(); +} + +void ScribeLogger::MakeScribeMessage(std::string& output, + std::vector& cols) { + int sz = cols.size(); + int i = 0; + for (; i < sz - 1; i++) { + std::string& col = cols.at(i); + output += col; + output += ScribeLogger::COL_SEPERATOR; + } + std::string& col = cols.at(i); + output+=col; +} + +void ScribeLogger::Log_Deploy_Stats( + const std::string& db_version, + const std::string& machine_info, + const std::string& data_dir, + const uint64_t data_size, + const uint32_t file_number, + const std::string& data_size_per_level, + const std::string& file_number_per_level, + const int64_t& ts_unix) { + std::string message; + std::vector cols; + cols.push_back(db_version); + cols.push_back(machine_info); + cols.push_back(data_dir); + cols.push_back(boost::lexical_cast(data_size)); + cols.push_back(boost::lexical_cast(file_number)); + cols.push_back(data_size_per_level); + cols.push_back(file_number_per_level); + cols.push_back(boost::lexical_cast(ts_unix)); + MakeScribeMessage(message, cols); + return Log(ScribeLogger::DEPLOY_STATS_CATEGORY, message); +} + +ScribeLogger::~ScribeLogger(){ + delete scribe_client_; +} + +} diff --git a/scribe/scribe_logger.h b/scribe/scribe_logger.h new file mode 100644 index 00000000..bd986eeb --- /dev/null +++ b/scribe/scribe_logger.h @@ -0,0 +1,69 @@ +#ifndef SCRIBE_LOGGER_H_ +#define SCRIBE_LOGGER_H_ + +#include "scribe/if/gen-cpp/scribe.h" +#include "scribe/if/gen-cpp/scribe_types.h" +#include "thrift/lib/cpp/protocol/TProtocol.h" +#include "thrift/lib/cpp/transport/TSocket.h" +#include "thrift/lib/cpp/protocol/TBinaryProtocol.h" +#include "thrift/lib/cpp/transport/TBufferTransports.h" + +#include "leveldb/env.h" +#include "port/port.h" +#include "util/stats_logger.h" + +#include "boost/lexical_cast.hpp" + +using namespace Tleveldb; +using Tleveldb::scribeClient; + +using namespace apache::thrift; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; +using boost::shared_ptr; + + +using namespace ::Tleveldb; + +namespace leveldb { + +class ScribeLogger : public StatsLogger{ +private: + std::string host_; + int port_; + int batch_size_; + + scribeClient* scribe_client_; + port::Mutex logger_mutex_; + + int retry_times_; + uint32_t retry_intervals_; + + void MakeScribeMessage(std::string& output, std::vector& cols); + +public: + + static const std::string COL_SEPERATOR; + static const std::string DEPLOY_STATS_CATEGORY; + + ScribeLogger(const std::string& host, int port, + int retry_times=3, uint32_t retry_intervals=1000000); + virtual ~ScribeLogger(); + + virtual void Log(const std::string& category, const std::string& message); + + virtual void Log_Deploy_Stats( + const std::string& db_version, + const std::string& machine_info, + const std::string& data_dir, + const uint64_t data_size, + const uint32_t file_number, + const std::string& data_size_per_level, + const std::string& file_number_per_level, + const int64_t& ts_unix + ); + +}; +} + +#endif /* SCRIBE_LOGGER_H_ */ diff --git a/snappy/README b/snappy/README new file mode 100644 index 00000000..0b6f90a3 --- /dev/null +++ b/snappy/README @@ -0,0 +1,14 @@ +This is a pre-compiled version of snappy 1.0.5 from +http://code.google.com/p/snappy/downloads/detail?name=snappy-1.0.5.tar.gz + +This is compiled using gcc-4.6.2-glibc-2.13 on centos5.2 +and uses jemalloc. This is here so that one can compile leveldb to use +snappy easily. + +To compile,: +cd ./snappy-1.0.5 +execute either make or compile.sh. +This will create *.so and *.a in snappy-1.0.5/.libs. + +run unit tests: +./snappy-1.0.5/snappy_unittest diff --git a/snappy/libs b/snappy/libs new file mode 120000 index 00000000..39191d85 --- /dev/null +++ b/snappy/libs @@ -0,0 +1 @@ +snappy-1.0.5/.libs \ No newline at end of file diff --git a/snappy/snappy-1.0.5/.deps/snappy-c.Plo b/snappy/snappy-1.0.5/.deps/snappy-c.Plo new file mode 100644 index 00000000..c35fd226 --- /dev/null +++ b/snappy/snappy-1.0.5/.deps/snappy-c.Plo @@ -0,0 +1,237 @@ +snappy-c.lo: snappy-c.cc snappy.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stddef.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/string \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++config.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/os_defines.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/features.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/cdefs.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wordsize.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs-64.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/cpu_defines.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stringfwd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/char_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_algobase.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/functexcept.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/exception_defines.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cpp_type_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/type_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/numeric_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_pair.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/move.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/concept_check.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_types.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_funcs.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/debug/debug.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/postypes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cwchar \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/wchar.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdio.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdarg.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wchar.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/xlocale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/allocator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++allocator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/new_allocator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/new \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/exception \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/localefwd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++locale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/clocale \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/locale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/locale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/iosfwd \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cctype \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/ctype.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/types.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/typesizes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/endian.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/endian.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/byteswap.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ostream_insert.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cxxabi_forced.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_function.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/backward/binders.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/range_access.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/atomicity.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr-default.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/pthread.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sched.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/time.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sched.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/time.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/pthreadtypes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/setjmp.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/unistd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/posix_opt.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/environments.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/confname.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/getopt.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/atomic_word.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/initializer_list \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.tcc \ + snappy-stubs-public.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdint.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdint.h \ + snappy-c.h + +snappy.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stddef.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/string: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++config.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/os_defines.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/features.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/cdefs.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wordsize.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs-64.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/cpu_defines.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stringfwd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/char_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_algobase.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/functexcept.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/exception_defines.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cpp_type_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/type_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/numeric_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_pair.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/move.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/concept_check.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_types.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_funcs.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/debug/debug.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/postypes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cwchar: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/wchar.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdio.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdarg.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wchar.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/xlocale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/allocator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++allocator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/new_allocator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/new: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/exception: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/localefwd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++locale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/clocale: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/locale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/locale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/iosfwd: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cctype: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/ctype.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/types.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/typesizes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/endian.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/endian.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/byteswap.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ostream_insert.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cxxabi_forced.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_function.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/backward/binders.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/range_access.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/atomicity.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr-default.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/pthread.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sched.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/time.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sched.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/time.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/pthreadtypes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/setjmp.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/unistd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/posix_opt.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/environments.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/confname.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/getopt.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/atomic_word.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/initializer_list: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.tcc: + +snappy-stubs-public.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdint.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdint.h: + +snappy-c.h: diff --git a/snappy/snappy-1.0.5/.deps/snappy-sinksource.Plo b/snappy/snappy-1.0.5/.deps/snappy-sinksource.Plo new file mode 100644 index 00000000..242185dc --- /dev/null +++ b/snappy/snappy-1.0.5/.deps/snappy-sinksource.Plo @@ -0,0 +1,28 @@ +snappy-sinksource.lo: snappy-sinksource.cc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/string.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/features.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/cdefs.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wordsize.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs-64.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stddef.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/xlocale.h \ + snappy-sinksource.h + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/string.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/features.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/cdefs.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wordsize.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs-64.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stddef.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/xlocale.h: + +snappy-sinksource.h: diff --git a/snappy/snappy-1.0.5/.deps/snappy-stubs-internal.Plo b/snappy/snappy-1.0.5/.deps/snappy-stubs-internal.Plo new file mode 100644 index 00000000..e32b8be4 --- /dev/null +++ b/snappy/snappy-1.0.5/.deps/snappy-stubs-internal.Plo @@ -0,0 +1,363 @@ +snappy-stubs-internal.lo: snappy-stubs-internal.cc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/algorithm \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/utility \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++config.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/os_defines.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/features.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/cdefs.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wordsize.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs-64.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/cpu_defines.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_relops.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_pair.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/move.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/concept_check.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_algobase.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/functexcept.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/exception_defines.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cpp_type_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/type_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/numeric_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_types.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_funcs.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/debug/debug.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_algo.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cstdlib \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdlib.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stddef.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/waitflags.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/waitstatus.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/endian.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/endian.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/byteswap.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/xlocale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/types.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/types.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/typesizes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/time.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/select.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/select.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sigset.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/time.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/sysmacros.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/pthreadtypes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/alloca.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/algorithmfwd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/initializer_list \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_heap.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_tempbuf.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_construct.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/new \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/exception \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/string \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stringfwd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/char_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/postypes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cwchar \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/wchar.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdio.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdarg.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wchar.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/allocator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++allocator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/new_allocator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/localefwd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++locale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/clocale \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/locale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/locale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/iosfwd \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cctype \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/ctype.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ostream_insert.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cxxabi_forced.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_function.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/backward/binders.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/range_access.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/atomicity.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr-default.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/pthread.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sched.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sched.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/setjmp.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/unistd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/posix_opt.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/environments.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/confname.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/getopt.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/atomic_word.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.tcc \ + snappy-stubs-internal.h config.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/iostream \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ostream \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ios \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ios_base.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_classes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_classes.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/streambuf \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/streambuf.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_ios.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_facets.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cwctype \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/wctype.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/ctype_base.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/streambuf_iterator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/ctype_inline.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_facets.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_ios.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ostream.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/istream \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/istream.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/assert.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/string.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/mman.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/mman.h \ + snappy-stubs-public.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdint.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdint.h + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/algorithm: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/utility: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++config.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/os_defines.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/features.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/cdefs.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wordsize.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs-64.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/cpu_defines.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_relops.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_pair.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/move.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/concept_check.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_algobase.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/functexcept.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/exception_defines.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cpp_type_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/type_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/numeric_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_types.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_funcs.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/debug/debug.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_algo.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cstdlib: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdlib.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stddef.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/waitflags.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/waitstatus.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/endian.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/endian.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/byteswap.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/xlocale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/types.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/types.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/typesizes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/time.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/select.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/select.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sigset.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/time.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/sysmacros.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/pthreadtypes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/alloca.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/algorithmfwd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/initializer_list: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_heap.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_tempbuf.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_construct.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/new: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/exception: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/string: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stringfwd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/char_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/postypes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cwchar: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/wchar.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdio.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdarg.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wchar.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/allocator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++allocator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/new_allocator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/localefwd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++locale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/clocale: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/locale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/locale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/iosfwd: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cctype: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/ctype.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ostream_insert.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cxxabi_forced.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_function.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/backward/binders.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/range_access.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/atomicity.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr-default.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/pthread.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sched.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sched.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/setjmp.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/unistd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/posix_opt.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/environments.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/confname.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/getopt.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/atomic_word.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.tcc: + +snappy-stubs-internal.h: + +config.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/iostream: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ostream: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ios: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ios_base.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_classes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_classes.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/streambuf: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/streambuf.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_ios.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_facets.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cwctype: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/wctype.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/ctype_base.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/streambuf_iterator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/ctype_inline.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_facets.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_ios.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ostream.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/istream: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/istream.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/assert.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/string.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/mman.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/mman.h: + +snappy-stubs-public.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdint.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdint.h: diff --git a/snappy/snappy-1.0.5/.deps/snappy.Plo b/snappy/snappy-1.0.5/.deps/snappy.Plo new file mode 100644 index 00000000..2022daf1 --- /dev/null +++ b/snappy/snappy-1.0.5/.deps/snappy.Plo @@ -0,0 +1,400 @@ +snappy.lo: snappy.cc snappy.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stddef.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/string \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++config.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/os_defines.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/features.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/cdefs.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wordsize.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs-64.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/cpu_defines.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stringfwd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/char_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_algobase.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/functexcept.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/exception_defines.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cpp_type_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/type_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/numeric_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_pair.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/move.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/concept_check.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_types.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_funcs.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/debug/debug.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/postypes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cwchar \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/wchar.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdio.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdarg.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wchar.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/xlocale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/allocator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++allocator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/new_allocator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/new \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/exception \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/localefwd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++locale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/clocale \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/locale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/locale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/iosfwd \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cctype \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/ctype.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/types.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/typesizes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/endian.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/endian.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/byteswap.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ostream_insert.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cxxabi_forced.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_function.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/backward/binders.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/range_access.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/atomicity.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr-default.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/pthread.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sched.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/time.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sched.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/time.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/pthreadtypes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/setjmp.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/unistd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/posix_opt.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/environments.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/confname.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/getopt.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/atomic_word.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/initializer_list \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.tcc \ + snappy-stubs-public.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdint.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdint.h \ + snappy-internal.h snappy-stubs-internal.h config.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/iostream \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ostream \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ios \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ios_base.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_classes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_classes.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/streambuf \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/streambuf.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_ios.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_facets.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cwctype \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/wctype.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/ctype_base.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/streambuf_iterator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/ctype_inline.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_facets.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_ios.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ostream.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/istream \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/istream.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/assert.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdlib.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/waitflags.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/waitstatus.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/types.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/select.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/select.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sigset.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/sysmacros.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/alloca.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/string.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/mman.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/mman.h \ + snappy-sinksource.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/libio.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/_G_config.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/stdio_lim.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sys_errlist.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/stdio.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/algorithm \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/utility \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_relops.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_algo.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cstdlib \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/algorithmfwd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_heap.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_tempbuf.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_construct.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/vector \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_uninitialized.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_vector.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_bvector.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/vector.tcc + +snappy.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stddef.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/string: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++config.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/os_defines.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/features.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/cdefs.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wordsize.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs-64.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/cpu_defines.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stringfwd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/char_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_algobase.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/functexcept.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/exception_defines.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cpp_type_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/type_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/numeric_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_pair.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/move.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/concept_check.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_types.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_funcs.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/debug/debug.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/postypes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cwchar: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/wchar.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdio.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdarg.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wchar.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/xlocale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/allocator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++allocator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/new_allocator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/new: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/exception: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/localefwd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++locale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/clocale: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/locale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/locale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/iosfwd: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cctype: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/ctype.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/types.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/typesizes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/endian.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/endian.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/byteswap.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ostream_insert.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cxxabi_forced.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_function.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/backward/binders.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/range_access.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/atomicity.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr-default.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/pthread.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sched.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/time.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sched.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/time.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/pthreadtypes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/setjmp.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/unistd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/posix_opt.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/environments.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/confname.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/getopt.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/atomic_word.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/initializer_list: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.tcc: + +snappy-stubs-public.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdint.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdint.h: + +snappy-internal.h: + +snappy-stubs-internal.h: + +config.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/iostream: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ostream: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ios: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ios_base.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_classes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_classes.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/streambuf: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/streambuf.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_ios.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_facets.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cwctype: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/wctype.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/ctype_base.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/streambuf_iterator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/ctype_inline.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_facets.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_ios.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ostream.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/istream: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/istream.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/assert.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdlib.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/waitflags.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/waitstatus.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/types.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/select.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/select.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sigset.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/sysmacros.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/alloca.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/string.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/mman.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/mman.h: + +snappy-sinksource.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/libio.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/_G_config.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/stdio_lim.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sys_errlist.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/stdio.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/algorithm: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/utility: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_relops.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_algo.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cstdlib: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/algorithmfwd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_heap.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_tempbuf.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_construct.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/vector: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_uninitialized.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_vector.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_bvector.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/vector.tcc: diff --git a/snappy/snappy-1.0.5/.deps/snappy_unittest-snappy-test.Po b/snappy/snappy-1.0.5/.deps/snappy_unittest-snappy-test.Po new file mode 100644 index 00000000..49ccf1c9 --- /dev/null +++ b/snappy/snappy-1.0.5/.deps/snappy_unittest-snappy-test.Po @@ -0,0 +1,389 @@ +snappy_unittest-snappy-test.o: snappy-test.cc snappy-test.h \ + snappy-stubs-internal.h config.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/iostream \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++config.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/os_defines.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/features.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/cdefs.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wordsize.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs-64.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/cpu_defines.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ostream \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ios \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/iosfwd \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stringfwd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/postypes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cwchar \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/wchar.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdio.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdarg.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wchar.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stddef.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/xlocale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/exception \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/char_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_algobase.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/functexcept.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/exception_defines.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cpp_type_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/type_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/numeric_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_pair.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/move.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/concept_check.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_types.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_funcs.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/debug/debug.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/localefwd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++locale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/clocale \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/locale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/locale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cctype \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/ctype.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/types.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/typesizes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/endian.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/endian.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/byteswap.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ios_base.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/atomicity.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr-default.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/pthread.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sched.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/time.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sched.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/time.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/pthreadtypes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/setjmp.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/unistd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/posix_opt.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/environments.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/confname.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/getopt.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/atomic_word.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_classes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/string \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/allocator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++allocator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/new_allocator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/new \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ostream_insert.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cxxabi_forced.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_function.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/backward/binders.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/range_access.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/initializer_list \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_classes.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/streambuf \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/streambuf.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_ios.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_facets.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cwctype \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/wctype.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/ctype_base.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/streambuf_iterator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/ctype_inline.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_facets.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_ios.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ostream.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/istream \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/istream.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/assert.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdlib.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/waitflags.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/waitstatus.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/types.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/select.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/select.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sigset.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/sysmacros.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/alloca.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/string.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/mman.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/mman.h \ + snappy-stubs-public.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdint.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdint.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/libio.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/_G_config.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/stdio_lim.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sys_errlist.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/stdio.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/resource.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/resource.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/time.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/algorithm \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/utility \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_relops.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_algo.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cstdlib \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/algorithmfwd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_heap.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_tempbuf.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_construct.h + +snappy-test.h: + +snappy-stubs-internal.h: + +config.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/iostream: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++config.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/os_defines.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/features.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/cdefs.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wordsize.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs-64.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/cpu_defines.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ostream: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ios: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/iosfwd: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stringfwd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/postypes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cwchar: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/wchar.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdio.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdarg.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wchar.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stddef.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/xlocale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/exception: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/char_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_algobase.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/functexcept.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/exception_defines.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cpp_type_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/type_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/numeric_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_pair.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/move.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/concept_check.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_types.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_funcs.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/debug/debug.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/localefwd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++locale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/clocale: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/locale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/locale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cctype: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/ctype.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/types.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/typesizes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/endian.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/endian.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/byteswap.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ios_base.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/atomicity.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr-default.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/pthread.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sched.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/time.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sched.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/time.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/pthreadtypes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/setjmp.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/unistd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/posix_opt.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/environments.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/confname.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/getopt.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/atomic_word.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_classes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/string: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/allocator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++allocator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/new_allocator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/new: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ostream_insert.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cxxabi_forced.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_function.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/backward/binders.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/range_access.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/initializer_list: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_classes.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/streambuf: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/streambuf.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_ios.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_facets.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cwctype: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/wctype.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/ctype_base.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/streambuf_iterator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/ctype_inline.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_facets.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_ios.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ostream.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/istream: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/istream.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/assert.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdlib.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/waitflags.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/waitstatus.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/types.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/select.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/select.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sigset.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/sysmacros.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/alloca.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/string.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/mman.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/mman.h: + +snappy-stubs-public.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdint.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdint.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/libio.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/_G_config.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/stdio_lim.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sys_errlist.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/stdio.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/resource.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/resource.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/time.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/algorithm: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/utility: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_relops.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_algo.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cstdlib: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/algorithmfwd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_heap.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_tempbuf.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_construct.h: diff --git a/snappy/snappy-1.0.5/.deps/snappy_unittest-snappy_unittest.Po b/snappy/snappy-1.0.5/.deps/snappy_unittest-snappy_unittest.Po new file mode 100644 index 00000000..c92b0689 --- /dev/null +++ b/snappy/snappy-1.0.5/.deps/snappy_unittest-snappy_unittest.Po @@ -0,0 +1,439 @@ +snappy_unittest-snappy_unittest.o: snappy_unittest.cc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/math.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/features.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/cdefs.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wordsize.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs-64.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/huge_val.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/huge_valf.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/huge_vall.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/inf.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/nan.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/mathdef.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/mathcalls.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/mathinline.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdlib.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stddef.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/waitflags.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/waitstatus.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/endian.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/endian.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/byteswap.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/xlocale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/types.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/types.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/typesizes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/time.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/select.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/select.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sigset.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/time.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/sysmacros.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/pthreadtypes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/alloca.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/algorithm \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/utility \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++config.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/os_defines.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/cpu_defines.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_relops.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_pair.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/move.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/concept_check.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_algobase.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/functexcept.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/exception_defines.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cpp_type_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/type_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/numeric_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_types.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_funcs.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/debug/debug.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_algo.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cstdlib \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/algorithmfwd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/initializer_list \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_heap.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_tempbuf.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_construct.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/new \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/exception \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/string \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stringfwd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/char_traits.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/postypes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cwchar \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/wchar.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdio.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdarg.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wchar.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/allocator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++allocator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/new_allocator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/localefwd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++locale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/clocale \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/locale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/locale.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/iosfwd \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cctype \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/ctype.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ostream_insert.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cxxabi_forced.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_function.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/backward/binders.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/range_access.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/atomicity.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr-default.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/pthread.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sched.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sched.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/setjmp.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/unistd.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/posix_opt.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/environments.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/confname.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/getopt.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/atomic_word.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/vector \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_uninitialized.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_vector.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_bvector.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/vector.tcc \ + snappy.h snappy-stubs-public.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdint.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdint.h \ + snappy-internal.h snappy-stubs-internal.h config.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/iostream \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ostream \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ios \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ios_base.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_classes.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_classes.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/streambuf \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/streambuf.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_ios.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_facets.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cwctype \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/wctype.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/ctype_base.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/streambuf_iterator.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/ctype_inline.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_facets.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_ios.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ostream.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/istream \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/istream.tcc \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/assert.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/string.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/mman.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/mman.h \ + snappy-test.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/libio.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/_G_config.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/stdio_lim.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sys_errlist.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/stdio.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/resource.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/resource.h \ + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/time.h \ + snappy-sinksource.h + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/math.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/features.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/cdefs.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wordsize.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/gnu/stubs-64.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/huge_val.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/huge_valf.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/huge_vall.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/inf.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/nan.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/mathdef.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/mathcalls.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/mathinline.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdlib.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stddef.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/waitflags.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/waitstatus.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/endian.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/endian.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/byteswap.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/xlocale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/types.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/types.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/typesizes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/time.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/select.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/select.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sigset.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/time.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/sysmacros.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/pthreadtypes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/alloca.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/algorithm: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/utility: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++config.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/os_defines.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/cpu_defines.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_relops.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_pair.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/move.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/concept_check.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_algobase.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/functexcept.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/exception_defines.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cpp_type_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/type_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/numeric_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_types.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator_base_funcs.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_iterator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/debug/debug.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_algo.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cstdlib: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/algorithmfwd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/initializer_list: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_heap.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_tempbuf.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_construct.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/new: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/exception: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/string: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stringfwd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/char_traits.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/postypes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cwchar: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/wchar.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdio.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdarg.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/wchar.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/allocator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++allocator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/new_allocator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/localefwd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/c++locale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/clocale: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/locale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/locale.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/iosfwd: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cctype: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/ctype.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ostream_insert.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/cxxabi_forced.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_function.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/backward/binders.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/range_access.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ext/atomicity.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/gthr-default.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/pthread.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sched.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sched.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/setjmp.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/unistd.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/posix_opt.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/environments.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/confname.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/getopt.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/atomic_word.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_string.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/vector: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_uninitialized.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_vector.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/stl_bvector.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/vector.tcc: + +snappy.h: + +snappy-stubs-public.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib/gcc/x86_64-redhat-linux-gnu/4.6.2/include/stdint.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdint.h: + +snappy-internal.h: + +snappy-stubs-internal.h: + +config.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/iostream: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ostream: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/ios: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ios_base.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_classes.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_classes.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/streambuf: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/streambuf.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_ios.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_facets.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/cwctype: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/wctype.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/ctype_base.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/streambuf_iterator.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/x86_64-facebook-linux/bits/ctype_inline.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/locale_facets.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/basic_ios.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/ostream.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/istream: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/include/c++/4.6.2/bits/istream.tcc: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/assert.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/string.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/mman.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/mman.h: + +snappy-test.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/libio.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/_G_config.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/stdio_lim.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/sys_errlist.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/stdio.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/resource.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/bits/resource.h: + +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/sys/time.h: + +snappy-sinksource.h: diff --git a/snappy/snappy-1.0.5/.libs/libsnappy.a b/snappy/snappy-1.0.5/.libs/libsnappy.a new file mode 100644 index 00000000..c1e8169a Binary files /dev/null and b/snappy/snappy-1.0.5/.libs/libsnappy.a differ diff --git a/snappy/snappy-1.0.5/.libs/libsnappy.la b/snappy/snappy-1.0.5/.libs/libsnappy.la new file mode 120000 index 00000000..e51e4065 --- /dev/null +++ b/snappy/snappy-1.0.5/.libs/libsnappy.la @@ -0,0 +1 @@ +../libsnappy.la \ No newline at end of file diff --git a/snappy/snappy-1.0.5/.libs/libsnappy.lai b/snappy/snappy-1.0.5/.libs/libsnappy.lai new file mode 100644 index 00000000..c93ed670 --- /dev/null +++ b/snappy/snappy-1.0.5/.libs/libsnappy.lai @@ -0,0 +1,41 @@ +# libsnappy.la - a libtool library file +# Generated by ltmain.sh (GNU libtool) 2.2.6b Debian-2.2.6b-2ubuntu1 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='libsnappy.so.1' + +# Names of this library. +library_names='libsnappy.so.1.1.1 libsnappy.so.1 libsnappy.so' + +# The name of the static archive. +old_library='libsnappy.a' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='' + +# Libraries that this one depends upon. +dependency_libs='' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for libsnappy. +current=2 +age=1 +revision=1 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/usr/local/lib' diff --git a/snappy/snappy-1.0.5/.libs/libsnappy.so b/snappy/snappy-1.0.5/.libs/libsnappy.so new file mode 120000 index 00000000..74b25e0f --- /dev/null +++ b/snappy/snappy-1.0.5/.libs/libsnappy.so @@ -0,0 +1 @@ +libsnappy.so.1.0.5 \ No newline at end of file diff --git a/snappy/snappy-1.0.5/.libs/libsnappy.so.1 b/snappy/snappy-1.0.5/.libs/libsnappy.so.1 new file mode 120000 index 00000000..74b25e0f --- /dev/null +++ b/snappy/snappy-1.0.5/.libs/libsnappy.so.1 @@ -0,0 +1 @@ +libsnappy.so.1.0.5 \ No newline at end of file diff --git a/snappy/snappy-1.0.5/.libs/libsnappy.so.1.0.5 b/snappy/snappy-1.0.5/.libs/libsnappy.so.1.0.5 new file mode 100755 index 00000000..27366aa4 Binary files /dev/null and b/snappy/snappy-1.0.5/.libs/libsnappy.so.1.0.5 differ diff --git a/snappy/snappy-1.0.5/.libs/snappy_unittest b/snappy/snappy-1.0.5/.libs/snappy_unittest new file mode 100755 index 00000000..3607949f Binary files /dev/null and b/snappy/snappy-1.0.5/.libs/snappy_unittest differ diff --git a/snappy/snappy-1.0.5/AUTHORS b/snappy/snappy-1.0.5/AUTHORS new file mode 100644 index 00000000..4858b377 --- /dev/null +++ b/snappy/snappy-1.0.5/AUTHORS @@ -0,0 +1 @@ +opensource@google.com diff --git a/snappy/snappy-1.0.5/COPYING b/snappy/snappy-1.0.5/COPYING new file mode 100644 index 00000000..8d6bd9fe --- /dev/null +++ b/snappy/snappy-1.0.5/COPYING @@ -0,0 +1,28 @@ +Copyright 2011, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/snappy/snappy-1.0.5/ChangeLog b/snappy/snappy-1.0.5/ChangeLog new file mode 100644 index 00000000..f79491b5 --- /dev/null +++ b/snappy/snappy-1.0.5/ChangeLog @@ -0,0 +1,1217 @@ +------------------------------------------------------------------------ +r60 | snappy.mirrorbot@gmail.com | 2012-02-23 18:00:36 +0100 (Thu, 23 Feb 2012) | 57 lines + +For 32-bit platforms, do not try to accelerate multiple neighboring +32-bit loads with a 64-bit load during compression (it's not a win). + +The main target for this optimization is ARM, but 32-bit x86 gets +a small gain, too, although there is noise in the microbenchmarks. +It's a no-op for 64-bit x86. It does not affect decompression. + +Microbenchmark results on a Cortex-A9 1GHz, using g++ 4.6.2 (from +Ubuntu/Linaro), -O2 -DNDEBUG -Wa,-march=armv7a -mtune=cortex-a9 +-mthumb-interwork, minimum 1000 iterations: + + Benchmark Time(ns) CPU(ns) Iterations + --------------------------------------------------- + BM_ZFlat/0 1158277 1160000 1000 84.2MB/s html (23.57 %) [ +4.3%] + BM_ZFlat/1 14861782 14860000 1000 45.1MB/s urls (50.89 %) [ +1.1%] + BM_ZFlat/2 393595 390000 1000 310.5MB/s jpg (99.88 %) [ +0.0%] + BM_ZFlat/3 650583 650000 1000 138.4MB/s pdf (82.13 %) [ +3.1%] + BM_ZFlat/4 4661480 4660000 1000 83.8MB/s html4 (23.55 %) [ +4.3%] + BM_ZFlat/5 491973 490000 1000 47.9MB/s cp (48.12 %) [ +2.0%] + BM_ZFlat/6 193575 192678 1038 55.2MB/s c (42.40 %) [ +9.0%] + BM_ZFlat/7 62343 62754 3187 56.5MB/s lsp (48.37 %) [ +2.6%] + BM_ZFlat/8 17708468 17710000 1000 55.5MB/s xls (41.34 %) [ -0.3%] + BM_ZFlat/9 3755345 3760000 1000 38.6MB/s txt1 (59.81 %) [ +8.2%] + BM_ZFlat/10 3324217 3320000 1000 36.0MB/s txt2 (64.07 %) [ +4.2%] + BM_ZFlat/11 10139932 10140000 1000 40.1MB/s txt3 (57.11 %) [ +6.4%] + BM_ZFlat/12 13532109 13530000 1000 34.0MB/s txt4 (68.35 %) [ +5.0%] + BM_ZFlat/13 4690847 4690000 1000 104.4MB/s bin (18.21 %) [ +4.1%] + BM_ZFlat/14 830682 830000 1000 43.9MB/s sum (51.88 %) [ +1.2%] + BM_ZFlat/15 84784 85011 2235 47.4MB/s man (59.36 %) [ +1.1%] + BM_ZFlat/16 1293254 1290000 1000 87.7MB/s pb (23.15 %) [ +2.3%] + BM_ZFlat/17 2775155 2780000 1000 63.2MB/s gaviota (38.27 %) [+12.2%] + +Core i7 in 32-bit mode (only one run and 100 iterations, though, so noisy): + + Benchmark Time(ns) CPU(ns) Iterations + --------------------------------------------------- + BM_ZFlat/0 227582 223464 3043 437.0MB/s html (23.57 %) [ +7.4%] + BM_ZFlat/1 2982430 2918455 233 229.4MB/s urls (50.89 %) [ +2.9%] + BM_ZFlat/2 46967 46658 15217 2.5GB/s jpg (99.88 %) [ +0.0%] + BM_ZFlat/3 115298 114864 5833 783.2MB/s pdf (82.13 %) [ +1.5%] + BM_ZFlat/4 913440 899743 778 434.2MB/s html4 (23.55 %) [ +0.3%] + BM_ZFlat/5 110302 108571 7000 216.1MB/s cp (48.12 %) [ +0.0%] + BM_ZFlat/6 44409 43372 15909 245.2MB/s c (42.40 %) [ +0.8%] + BM_ZFlat/7 15713 15643 46667 226.9MB/s lsp (48.37 %) [ +2.7%] + BM_ZFlat/8 2625539 2602230 269 377.4MB/s xls (41.34 %) [ +1.4%] + BM_ZFlat/9 808884 811429 875 178.8MB/s txt1 (59.81 %) [ -3.9%] + BM_ZFlat/10 709532 700000 1000 170.5MB/s txt2 (64.07 %) [ +0.0%] + BM_ZFlat/11 2177682 2162162 333 188.2MB/s txt3 (57.11 %) [ -1.4%] + BM_ZFlat/12 2849640 2840000 250 161.8MB/s txt4 (68.35 %) [ -1.4%] + BM_ZFlat/13 849760 835476 778 585.8MB/s bin (18.21 %) [ +1.2%] + BM_ZFlat/14 165940 164571 4375 221.6MB/s sum (51.88 %) [ +1.4%] + BM_ZFlat/15 20939 20571 35000 196.0MB/s man (59.36 %) [ +2.1%] + BM_ZFlat/16 239209 236544 2917 478.1MB/s pb (23.15 %) [ +4.2%] + BM_ZFlat/17 616206 610000 1000 288.2MB/s gaviota (38.27 %) [ -1.6%] + +R=sanjay + +------------------------------------------------------------------------ +r59 | snappy.mirrorbot@gmail.com | 2012-02-21 18:02:17 +0100 (Tue, 21 Feb 2012) | 107 lines + +Enable the use of unaligned loads and stores for ARM-based architectures +where they are available (ARMv7 and higher). This gives a significant +speed boost on ARM, both for compression and decompression. +It should not affect x86 at all. + +There are more changes possible to speed up ARM, but it might not be +that easy to do without hurting x86 or making the code uglier. +Also, we de not try to use NEON yet. + +Microbenchmark results on a Cortex-A9 1GHz, using g++ 4.6.2 (from Ubuntu/Linaro), +-O2 -DNDEBUG -Wa,-march=armv7a -mtune=cortex-a9 -mthumb-interwork: + +Benchmark Time(ns) CPU(ns) Iterations +--------------------------------------------------- +BM_UFlat/0 524806 529100 378 184.6MB/s html [+33.6%] +BM_UFlat/1 5139790 5200000 100 128.8MB/s urls [+28.8%] +BM_UFlat/2 86540 84166 1901 1.4GB/s jpg [ +0.6%] +BM_UFlat/3 215351 210176 904 428.0MB/s pdf [+29.8%] +BM_UFlat/4 2144490 2100000 100 186.0MB/s html4 [+33.3%] +BM_UFlat/5 194482 190000 1000 123.5MB/s cp [+36.2%] +BM_UFlat/6 91843 90175 2107 117.9MB/s c [+38.6%] +BM_UFlat/7 28535 28426 6684 124.8MB/s lsp [+34.7%] +BM_UFlat/8 9206600 9200000 100 106.7MB/s xls [+42.4%] +BM_UFlat/9 1865273 1886792 106 76.9MB/s txt1 [+32.5%] +BM_UFlat/10 1576809 1587301 126 75.2MB/s txt2 [+32.3%] +BM_UFlat/11 4968450 4900000 100 83.1MB/s txt3 [+32.7%] +BM_UFlat/12 6673970 6700000 100 68.6MB/s txt4 [+32.8%] +BM_UFlat/13 2391470 2400000 100 203.9MB/s bin [+29.2%] +BM_UFlat/14 334601 344827 522 105.8MB/s sum [+30.6%] +BM_UFlat/15 37404 38080 5252 105.9MB/s man [+33.8%] +BM_UFlat/16 535470 540540 370 209.2MB/s pb [+31.2%] +BM_UFlat/17 1875245 1886792 106 93.2MB/s gaviota [+37.8%] +BM_UValidate/0 178425 179533 1114 543.9MB/s html [ +2.7%] +BM_UValidate/1 2100450 2000000 100 334.8MB/s urls [ +5.0%] +BM_UValidate/2 1039 1044 172413 113.3GB/s jpg [ +3.4%] +BM_UValidate/3 59423 59470 3363 1.5GB/s pdf [ +7.8%] +BM_UValidate/4 760716 766283 261 509.8MB/s html4 [ +6.5%] +BM_ZFlat/0 1204632 1204819 166 81.1MB/s html (23.57 %) [+32.8%] +BM_ZFlat/1 15656190 15600000 100 42.9MB/s urls (50.89 %) [+27.6%] +BM_ZFlat/2 403336 410677 487 294.8MB/s jpg (99.88 %) [+16.5%] +BM_ZFlat/3 664073 671140 298 134.0MB/s pdf (82.13 %) [+28.4%] +BM_ZFlat/4 4961940 4900000 100 79.7MB/s html4 (23.55 %) [+30.6%] +BM_ZFlat/5 500664 501253 399 46.8MB/s cp (48.12 %) [+33.4%] +BM_ZFlat/6 217276 215982 926 49.2MB/s c (42.40 %) [+25.0%] +BM_ZFlat/7 64122 65487 3054 54.2MB/s lsp (48.37 %) [+36.1%] +BM_ZFlat/8 18045730 18000000 100 54.6MB/s xls (41.34 %) [+34.4%] +BM_ZFlat/9 4051530 4000000 100 36.3MB/s txt1 (59.81 %) [+25.0%] +BM_ZFlat/10 3451800 3500000 100 34.1MB/s txt2 (64.07 %) [+25.7%] +BM_ZFlat/11 11052340 11100000 100 36.7MB/s txt3 (57.11 %) [+24.3%] +BM_ZFlat/12 14538690 14600000 100 31.5MB/s txt4 (68.35 %) [+24.7%] +BM_ZFlat/13 5041850 5000000 100 97.9MB/s bin (18.21 %) [+32.0%] +BM_ZFlat/14 908840 909090 220 40.1MB/s sum (51.88 %) [+22.2%] +BM_ZFlat/15 86921 86206 1972 46.8MB/s man (59.36 %) [+42.2%] +BM_ZFlat/16 1312315 1315789 152 86.0MB/s pb (23.15 %) [+34.5%] +BM_ZFlat/17 3173120 3200000 100 54.9MB/s gaviota (38.27%) [+28.1%] + + +The move from 64-bit to 32-bit operations for the copies also affected 32-bit x86; +positive on the decompression side, and slightly negative on the compression side +(unless that is noise; I only ran once): + +Benchmark Time(ns) CPU(ns) Iterations +----------------------------------------------------- +BM_UFlat/0 86279 86140 7778 1.1GB/s html [ +7.5%] +BM_UFlat/1 839265 822622 778 813.9MB/s urls [ +9.4%] +BM_UFlat/2 9180 9143 87500 12.9GB/s jpg [ +1.2%] +BM_UFlat/3 35080 35000 20000 2.5GB/s pdf [+10.1%] +BM_UFlat/4 350318 345000 2000 1.1GB/s html4 [ +7.0%] +BM_UFlat/5 33808 33472 21212 701.0MB/s cp [ +9.0%] +BM_UFlat/6 15201 15214 46667 698.9MB/s c [+14.9%] +BM_UFlat/7 4652 4651 159091 762.9MB/s lsp [ +7.5%] +BM_UFlat/8 1285551 1282528 538 765.7MB/s xls [+10.7%] +BM_UFlat/9 282510 281690 2414 514.9MB/s txt1 [+13.6%] +BM_UFlat/10 243494 239286 2800 498.9MB/s txt2 [+14.4%] +BM_UFlat/11 743625 740000 1000 550.0MB/s txt3 [+14.3%] +BM_UFlat/12 999441 989717 778 464.3MB/s txt4 [+16.1%] +BM_UFlat/13 412402 410076 1707 1.2GB/s bin [ +7.3%] +BM_UFlat/14 54876 54000 10000 675.3MB/s sum [+13.0%] +BM_UFlat/15 6146 6100 100000 660.8MB/s man [+14.8%] +BM_UFlat/16 90496 90286 8750 1.2GB/s pb [ +4.0%] +BM_UFlat/17 292650 292000 2500 602.0MB/s gaviota [+18.1%] +BM_UValidate/0 49620 49699 14286 1.9GB/s html [ +0.0%] +BM_UValidate/1 501371 500000 1000 1.3GB/s urls [ +0.0%] +BM_UValidate/2 232 227 3043478 521.5GB/s jpg [ +1.3%] +BM_UValidate/3 17250 17143 43750 5.1GB/s pdf [ -1.3%] +BM_UValidate/4 198643 200000 3500 1.9GB/s html4 [ -0.9%] +BM_ZFlat/0 227128 229415 3182 425.7MB/s html (23.57 %) [ -1.4%] +BM_ZFlat/1 2970089 2960000 250 226.2MB/s urls (50.89 %) [ -1.9%] +BM_ZFlat/2 45683 44999 15556 2.6GB/s jpg (99.88 %) [ +2.2%] +BM_ZFlat/3 114661 113136 6364 795.1MB/s pdf (82.13 %) [ -1.5%] +BM_ZFlat/4 919702 914286 875 427.2MB/s html4 (23.55%) [ -1.3%] +BM_ZFlat/5 108189 108422 6364 216.4MB/s cp (48.12 %) [ -1.2%] +BM_ZFlat/6 44525 44000 15909 241.7MB/s c (42.40 %) [ -2.9%] +BM_ZFlat/7 15973 15857 46667 223.8MB/s lsp (48.37 %) [ +0.0%] +BM_ZFlat/8 2677888 2639405 269 372.1MB/s xls (41.34 %) [ -1.4%] +BM_ZFlat/9 800715 780000 1000 186.0MB/s txt1 (59.81 %) [ -0.4%] +BM_ZFlat/10 700089 700000 1000 170.5MB/s txt2 (64.07 %) [ -2.9%] +BM_ZFlat/11 2159356 2138365 318 190.3MB/s txt3 (57.11 %) [ -0.3%] +BM_ZFlat/12 2796143 2779923 259 165.3MB/s txt4 (68.35 %) [ -1.4%] +BM_ZFlat/13 856458 835476 778 585.8MB/s bin (18.21 %) [ -0.1%] +BM_ZFlat/14 166908 166857 4375 218.6MB/s sum (51.88 %) [ -1.4%] +BM_ZFlat/15 21181 20857 35000 193.3MB/s man (59.36 %) [ -0.8%] +BM_ZFlat/16 244009 239973 2917 471.3MB/s pb (23.15 %) [ -1.4%] +BM_ZFlat/17 596362 590000 1000 297.9MB/s gaviota (38.27%) [ +0.0%] + +R=sanjay + +------------------------------------------------------------------------ +r58 | snappy.mirrorbot@gmail.com | 2012-02-11 23:11:22 +0100 (Sat, 11 Feb 2012) | 9 lines + +Lower the size allocated in the "corrupted input" unit test from 256 MB +to 2 MB. This fixes issues with running the unit test on platforms with +little RAM (e.g. some ARM boards). + +Also, reactivate the 2 MB test for 64-bit platforms; there's no good +reason why it shouldn't be. + +R=sanjay + +------------------------------------------------------------------------ +r57 | snappy.mirrorbot@gmail.com | 2012-01-08 18:55:48 +0100 (Sun, 08 Jan 2012) | 2 lines + +Minor refactoring to accomodate changes in Google's internal code tree. + +------------------------------------------------------------------------ +r56 | snappy.mirrorbot@gmail.com | 2012-01-04 14:10:46 +0100 (Wed, 04 Jan 2012) | 19 lines + +Fix public issue r57: Fix most warnings with -Wall, mostly signed/unsigned +warnings. There are still some in the unit test, but the main .cc file should +be clean. We haven't enabled -Wall for the default build, since the unit test +is still not clean. + +This also fixes a real bug in the open-source implementation of +ReadFileToStringOrDie(); it would not detect errors correctly. + +I had to go through some pains to avoid performance loss as the types +were changed; I think there might still be some with 32-bit if and only if LFS +is enabled (ie., size_t is 64-bit), but for regular 32-bit and 64-bit I can't +see any losses, and I've diffed the generated GCC assembler between the old and +new code without seeing any significant choices. If anything, it's ever so +slightly faster. + +This may or may not enable compression of very large blocks (>2^32 bytes) +when size_t is 64-bit, but I haven't checked, and it is still not a supported +case. + +------------------------------------------------------------------------ +r55 | snappy.mirrorbot@gmail.com | 2012-01-04 11:46:39 +0100 (Wed, 04 Jan 2012) | 6 lines + +Add a framing format description. We do not have any implementation of this at +the current point, but there seems to be enough of a general interest in the +topic (cf. public bug #34). + +R=csilvers,sanjay + +------------------------------------------------------------------------ +r54 | snappy.mirrorbot@gmail.com | 2011-12-05 22:27:26 +0100 (Mon, 05 Dec 2011) | 81 lines + +Speed up decompression by moving the refill check to the end of the loop. + +This seems to work because in most of the branches, the compiler can evaluate +“ip_limit_ - ip” in a more efficient way than reloading ip_limit_ from memory +(either by already having the entire expression in a register, or reconstructing +it from “avail”, or something else). Memory loads, even from L1, are seemingly +costly in the big picture at the current decompression speeds. + +Microbenchmarks (64-bit, opt mode): + +Westmere (Intel Core i7): + + Benchmark Time(ns) CPU(ns) Iterations + -------------------------------------------- + BM_UFlat/0 74492 74491 187894 1.3GB/s html [ +5.9%] + BM_UFlat/1 712268 712263 19644 940.0MB/s urls [ +3.8%] + BM_UFlat/2 10591 10590 1000000 11.2GB/s jpg [ -6.8%] + BM_UFlat/3 29643 29643 469915 3.0GB/s pdf [ +7.9%] + BM_UFlat/4 304669 304667 45930 1.3GB/s html4 [ +4.8%] + BM_UFlat/5 28508 28507 490077 823.1MB/s cp [ +4.0%] + BM_UFlat/6 12415 12415 1000000 856.5MB/s c [ +8.6%] + BM_UFlat/7 3415 3415 4084723 1039.0MB/s lsp [+18.0%] + BM_UFlat/8 979569 979563 14261 1002.5MB/s xls [ +5.8%] + BM_UFlat/9 230150 230148 60934 630.2MB/s txt1 [ +5.2%] + BM_UFlat/10 197167 197166 71135 605.5MB/s txt2 [ +4.7%] + BM_UFlat/11 607394 607390 23041 670.1MB/s txt3 [ +5.6%] + BM_UFlat/12 808502 808496 17316 568.4MB/s txt4 [ +5.0%] + BM_UFlat/13 372791 372788 37564 1.3GB/s bin [ +3.3%] + BM_UFlat/14 44541 44541 313969 818.8MB/s sum [ +5.7%] + BM_UFlat/15 4833 4833 2898697 834.1MB/s man [ +4.8%] + BM_UFlat/16 79855 79855 175356 1.4GB/s pb [ +4.8%] + BM_UFlat/17 245845 245843 56838 715.0MB/s gaviota [ +5.8%] + +Clovertown (Intel Core 2): + + Benchmark Time(ns) CPU(ns) Iterations + -------------------------------------------- + BM_UFlat/0 107911 107890 100000 905.1MB/s html [ +2.2%] + BM_UFlat/1 1011237 1011041 10000 662.3MB/s urls [ +2.5%] + BM_UFlat/2 26775 26770 523089 4.4GB/s jpg [ +0.0%] + BM_UFlat/3 48103 48095 290618 1.8GB/s pdf [ +3.4%] + BM_UFlat/4 437724 437644 31937 892.6MB/s html4 [ +2.1%] + BM_UFlat/5 39607 39600 358284 592.5MB/s cp [ +2.4%] + BM_UFlat/6 18227 18224 768191 583.5MB/s c [ +2.7%] + BM_UFlat/7 5171 5170 2709437 686.4MB/s lsp [ +3.9%] + BM_UFlat/8 1560291 1559989 8970 629.5MB/s xls [ +3.6%] + BM_UFlat/9 335401 335343 41731 432.5MB/s txt1 [ +3.0%] + BM_UFlat/10 287014 286963 48758 416.0MB/s txt2 [ +2.8%] + BM_UFlat/11 888522 888356 15752 458.1MB/s txt3 [ +2.9%] + BM_UFlat/12 1186600 1186378 10000 387.3MB/s txt4 [ +3.1%] + BM_UFlat/13 572295 572188 24468 855.4MB/s bin [ +2.1%] + BM_UFlat/14 64060 64049 218401 569.4MB/s sum [ +4.1%] + BM_UFlat/15 7264 7263 1916168 555.0MB/s man [ +1.4%] + BM_UFlat/16 108853 108836 100000 1039.1MB/s pb [ +1.7%] + BM_UFlat/17 364289 364223 38419 482.6MB/s gaviota [ +4.9%] + +Barcelona (AMD Opteron): + + Benchmark Time(ns) CPU(ns) Iterations + -------------------------------------------- + BM_UFlat/0 103900 103871 100000 940.2MB/s html [ +8.3%] + BM_UFlat/1 1000435 1000107 10000 669.5MB/s urls [ +6.6%] + BM_UFlat/2 24659 24652 567362 4.8GB/s jpg [ +0.1%] + BM_UFlat/3 48206 48193 291121 1.8GB/s pdf [ +5.0%] + BM_UFlat/4 421980 421850 33174 926.0MB/s html4 [ +7.3%] + BM_UFlat/5 40368 40357 346994 581.4MB/s cp [ +8.7%] + BM_UFlat/6 19836 19830 708695 536.2MB/s c [ +8.0%] + BM_UFlat/7 6100 6098 2292774 581.9MB/s lsp [ +9.0%] + BM_UFlat/8 1693093 1692514 8261 580.2MB/s xls [ +8.0%] + BM_UFlat/9 365991 365886 38225 396.4MB/s txt1 [ +7.1%] + BM_UFlat/10 311330 311238 44950 383.6MB/s txt2 [ +7.6%] + BM_UFlat/11 975037 974737 14376 417.5MB/s txt3 [ +6.9%] + BM_UFlat/12 1303558 1303175 10000 352.6MB/s txt4 [ +7.3%] + BM_UFlat/13 517448 517290 27144 946.2MB/s bin [ +5.5%] + BM_UFlat/14 66537 66518 210352 548.3MB/s sum [ +7.5%] + BM_UFlat/15 7976 7974 1760383 505.6MB/s man [ +5.6%] + BM_UFlat/16 103121 103092 100000 1097.0MB/s pb [ +8.7%] + BM_UFlat/17 391431 391314 35733 449.2MB/s gaviota [ +6.5%] + +R=sanjay + +------------------------------------------------------------------------ +r53 | snappy.mirrorbot@gmail.com | 2011-11-23 12:14:17 +0100 (Wed, 23 Nov 2011) | 88 lines + +Speed up decompression by making the fast path for literals faster. + +We do the fast-path step as soon as possible; in fact, as soon as we know the +literal length. Since we usually hit the fast path, we can then skip the checks +for long literals and available input space (beyond what the fast path check +already does). + +Note that this changes the decompression Writer API; however, it does not +change the ABI, since writers are always templatized and as such never +cross compilation units. The new API is slightly more general, in that it +doesn't hard-code the value 16. Note that we also take care to check +for len <= 16 first, since the other two checks almost always succeed +(so we don't want to waste time checking for them until we have to). + +The improvements are most marked on Nehalem, but are generally positive +on other platforms as well. All microbenchmarks are 64-bit, opt. + +Clovertown (Core 2): + + Benchmark Time(ns) CPU(ns) Iterations + -------------------------------------------- + BM_UFlat/0 110226 110224 100000 886.0MB/s html [ +1.5%] + BM_UFlat/1 1036523 1036508 10000 646.0MB/s urls [ -0.8%] + BM_UFlat/2 26775 26775 522570 4.4GB/s jpg [ +0.0%] + BM_UFlat/3 49738 49737 280974 1.8GB/s pdf [ +0.3%] + BM_UFlat/4 446790 446792 31334 874.3MB/s html4 [ +0.8%] + BM_UFlat/5 40561 40562 350424 578.5MB/s cp [ +1.3%] + BM_UFlat/6 18722 18722 746903 568.0MB/s c [ +1.4%] + BM_UFlat/7 5373 5373 2608632 660.5MB/s lsp [ +8.3%] + BM_UFlat/8 1615716 1615718 8670 607.8MB/s xls [ +2.0%] + BM_UFlat/9 345278 345281 40481 420.1MB/s txt1 [ +1.4%] + BM_UFlat/10 294855 294855 47452 404.9MB/s txt2 [ +1.6%] + BM_UFlat/11 914263 914263 15316 445.2MB/s txt3 [ +1.1%] + BM_UFlat/12 1222694 1222691 10000 375.8MB/s txt4 [ +1.4%] + BM_UFlat/13 584495 584489 23954 837.4MB/s bin [ -0.6%] + BM_UFlat/14 66662 66662 210123 547.1MB/s sum [ +1.2%] + BM_UFlat/15 7368 7368 1881856 547.1MB/s man [ +4.0%] + BM_UFlat/16 110727 110726 100000 1021.4MB/s pb [ +2.3%] + BM_UFlat/17 382138 382141 36616 460.0MB/s gaviota [ -0.7%] + +Westmere (Core i7): + + Benchmark Time(ns) CPU(ns) Iterations + -------------------------------------------- + BM_UFlat/0 78861 78853 177703 1.2GB/s html [ +2.1%] + BM_UFlat/1 739560 739491 18912 905.4MB/s urls [ +3.4%] + BM_UFlat/2 9867 9866 1419014 12.0GB/s jpg [ +3.4%] + BM_UFlat/3 31989 31986 438385 2.7GB/s pdf [ +0.2%] + BM_UFlat/4 319406 319380 43771 1.2GB/s html4 [ +1.9%] + BM_UFlat/5 29639 29636 472862 791.7MB/s cp [ +5.2%] + BM_UFlat/6 13478 13477 1000000 789.0MB/s c [ +2.3%] + BM_UFlat/7 4030 4029 3475364 880.7MB/s lsp [ +8.7%] + BM_UFlat/8 1036585 1036492 10000 947.5MB/s xls [ +6.9%] + BM_UFlat/9 242127 242105 57838 599.1MB/s txt1 [ +3.0%] + BM_UFlat/10 206499 206480 67595 578.2MB/s txt2 [ +3.4%] + BM_UFlat/11 641635 641570 21811 634.4MB/s txt3 [ +2.4%] + BM_UFlat/12 848847 848769 16443 541.4MB/s txt4 [ +3.1%] + BM_UFlat/13 384968 384938 36366 1.2GB/s bin [ +0.3%] + BM_UFlat/14 47106 47101 297770 774.3MB/s sum [ +4.4%] + BM_UFlat/15 5063 5063 2772202 796.2MB/s man [ +7.7%] + BM_UFlat/16 83663 83656 167697 1.3GB/s pb [ +1.8%] + BM_UFlat/17 260224 260198 53823 675.6MB/s gaviota [ -0.5%] + +Barcelona (Opteron): + + Benchmark Time(ns) CPU(ns) Iterations + -------------------------------------------- + BM_UFlat/0 112490 112457 100000 868.4MB/s html [ -0.4%] + BM_UFlat/1 1066719 1066339 10000 627.9MB/s urls [ +1.0%] + BM_UFlat/2 24679 24672 563802 4.8GB/s jpg [ +0.7%] + BM_UFlat/3 50603 50589 277285 1.7GB/s pdf [ +2.6%] + BM_UFlat/4 452982 452849 30900 862.6MB/s html4 [ -0.2%] + BM_UFlat/5 43860 43848 319554 535.1MB/s cp [ +1.2%] + BM_UFlat/6 21419 21413 653573 496.6MB/s c [ +1.0%] + BM_UFlat/7 6646 6645 2105405 534.1MB/s lsp [ +0.3%] + BM_UFlat/8 1828487 1827886 7658 537.3MB/s xls [ +2.6%] + BM_UFlat/9 391824 391714 35708 370.3MB/s txt1 [ +2.2%] + BM_UFlat/10 334913 334816 41885 356.6MB/s txt2 [ +1.7%] + BM_UFlat/11 1042062 1041674 10000 390.7MB/s txt3 [ +1.1%] + BM_UFlat/12 1398902 1398456 10000 328.6MB/s txt4 [ +1.7%] + BM_UFlat/13 545706 545530 25669 897.2MB/s bin [ -0.4%] + BM_UFlat/14 71512 71505 196035 510.0MB/s sum [ +1.4%] + BM_UFlat/15 8422 8421 1665036 478.7MB/s man [ +2.6%] + BM_UFlat/16 112053 112048 100000 1009.3MB/s pb [ -0.4%] + BM_UFlat/17 416723 416713 33612 421.8MB/s gaviota [ -2.0%] + +R=sanjay + +------------------------------------------------------------------------ +r52 | snappy.mirrorbot@gmail.com | 2011-11-08 15:46:39 +0100 (Tue, 08 Nov 2011) | 5 lines + +Fix public issue #53: Update the README to the API we actually open-sourced +with. + +R=sanjay + +------------------------------------------------------------------------ +r51 | snappy.mirrorbot@gmail.com | 2011-10-05 14:27:12 +0200 (Wed, 05 Oct 2011) | 5 lines + +In the format description, use a clearer example to emphasize that varints are +stored in little-endian. Patch from Christian von Roques. + +R=csilvers + +------------------------------------------------------------------------ +r50 | snappy.mirrorbot@gmail.com | 2011-09-15 21:34:06 +0200 (Thu, 15 Sep 2011) | 4 lines + +Release Snappy 1.0.4. + +R=sanjay + +------------------------------------------------------------------------ +r49 | snappy.mirrorbot@gmail.com | 2011-09-15 11:50:05 +0200 (Thu, 15 Sep 2011) | 5 lines + +Fix public issue #50: Include generic byteswap macros. +Also include Solaris 10 and FreeBSD versions. + +R=csilvers + +------------------------------------------------------------------------ +r48 | snappy.mirrorbot@gmail.com | 2011-08-10 20:57:27 +0200 (Wed, 10 Aug 2011) | 5 lines + +Partially fix public issue 50: Remove an extra comma from the end of some +enum declarations, as it seems the Sun compiler does not like it. + +Based on patch by Travis Vitek. + +------------------------------------------------------------------------ +r47 | snappy.mirrorbot@gmail.com | 2011-08-10 20:44:16 +0200 (Wed, 10 Aug 2011) | 4 lines + +Use the right #ifdef test for sys/mman.h. + +Based on patch by Travis Vitek. + +------------------------------------------------------------------------ +r46 | snappy.mirrorbot@gmail.com | 2011-08-10 03:22:09 +0200 (Wed, 10 Aug 2011) | 6 lines + +Fix public issue #47: Small comment cleanups in the unit test. + +Originally based on a patch by Patrick Pelletier. + +R=sanjay + +------------------------------------------------------------------------ +r45 | snappy.mirrorbot@gmail.com | 2011-08-10 03:14:43 +0200 (Wed, 10 Aug 2011) | 8 lines + +Fix public issue #46: Format description said "3-byte offset" +instead of "4-byte offset" for the longest copies. + +Also fix an inconsistency in the heading for section 2.2.3. +Both patches by Patrick Pelletier. + +R=csilvers + +------------------------------------------------------------------------ +r44 | snappy.mirrorbot@gmail.com | 2011-06-28 13:40:25 +0200 (Tue, 28 Jun 2011) | 8 lines + +Fix public issue #44: Make the definition and declaration of CompressFragment +identical, even regarding cv-qualifiers. + +This is required to work around a bug in the Solaris Studio C++ compiler +(it does not properly disregard cv-qualifiers when doing name mangling). + +R=sanjay + +------------------------------------------------------------------------ +r43 | snappy.mirrorbot@gmail.com | 2011-06-04 12:19:05 +0200 (Sat, 04 Jun 2011) | 7 lines + +Correct an inaccuracy in the Snappy format description. +(I stumbled into this when changing the way we decompress literals.) + +R=csilvers + +Revision created by MOE tool push_codebase. + +------------------------------------------------------------------------ +r42 | snappy.mirrorbot@gmail.com | 2011-06-03 22:53:06 +0200 (Fri, 03 Jun 2011) | 50 lines + +Speed up decompression by removing a fast-path attempt. + +Whenever we try to enter a copy fast-path, there is a certain cost in checking +that all the preconditions are in place, but it's normally offset by the fact +that we can usually take the cheaper path. However, in a certain path we've +already established that "avail < literal_length", which usually means that +either the available space is small, or the literal is big. Both will disqualify +us from taking the fast path, and thus we take the hit from the precondition +checking without gaining much from having a fast path. Thus, simply don't try +the fast path in this situation -- we're already on a slow path anyway +(one where we need to refill more data from the reader). + +I'm a bit surprised at how much this gained; it could be that this path is +more common than I thought, or that the simpler structure somehow makes the +compiler happier. I haven't looked at the assembler, but it's a win across +the board on both Core 2, Core i7 and Opteron, at least for the cases we +typically care about. The gains seem to be the largest on Core i7, though. +Results from my Core i7 workstation: + + + Benchmark Time(ns) CPU(ns) Iterations + --------------------------------------------------- + BM_UFlat/0 73337 73091 190996 1.3GB/s html [ +1.7%] + BM_UFlat/1 696379 693501 20173 965.5MB/s urls [ +2.7%] + BM_UFlat/2 9765 9734 1472135 12.1GB/s jpg [ +0.7%] + BM_UFlat/3 29720 29621 472973 3.0GB/s pdf [ +1.8%] + BM_UFlat/4 294636 293834 47782 1.3GB/s html4 [ +2.3%] + BM_UFlat/5 28399 28320 494700 828.5MB/s cp [ +3.5%] + BM_UFlat/6 12795 12760 1000000 833.3MB/s c [ +1.2%] + BM_UFlat/7 3984 3973 3526448 893.2MB/s lsp [ +5.7%] + BM_UFlat/8 991996 989322 14141 992.6MB/s xls [ +3.3%] + BM_UFlat/9 228620 227835 61404 636.6MB/s txt1 [ +4.0%] + BM_UFlat/10 197114 196494 72165 607.5MB/s txt2 [ +3.5%] + BM_UFlat/11 605240 603437 23217 674.4MB/s txt3 [ +3.7%] + BM_UFlat/12 804157 802016 17456 573.0MB/s txt4 [ +3.9%] + BM_UFlat/13 347860 346998 40346 1.4GB/s bin [ +1.2%] + BM_UFlat/14 44684 44559 315315 818.4MB/s sum [ +2.3%] + BM_UFlat/15 5120 5106 2739726 789.4MB/s man [ +3.3%] + BM_UFlat/16 76591 76355 183486 1.4GB/s pb [ +2.8%] + BM_UFlat/17 238564 237828 58824 739.1MB/s gaviota [ +1.6%] + BM_UValidate/0 42194 42060 333333 2.3GB/s html [ -0.1%] + BM_UValidate/1 433182 432005 32407 1.5GB/s urls [ -0.1%] + BM_UValidate/2 197 196 71428571 603.3GB/s jpg [ +0.5%] + BM_UValidate/3 14494 14462 972222 6.1GB/s pdf [ +0.5%] + BM_UValidate/4 168444 167836 83832 2.3GB/s html4 [ +0.1%] + +R=jeff + +Revision created by MOE tool push_codebase. + +------------------------------------------------------------------------ +r41 | snappy.mirrorbot@gmail.com | 2011-06-03 22:47:14 +0200 (Fri, 03 Jun 2011) | 43 lines + +Speed up decompression by not needing a lookup table for literal items. + +Looking up into and decoding the values from char_table has long shown up as a +hotspot in the decompressor. While it turns out that it's hard to make a more +efficient decoder for the copy ops, the literals are simple enough that we can +decode them without needing a table lookup. (This means that 1/4 of the table +is now unused, although that in itself doesn't buy us anything.) + +The gains are small, but definitely present; some tests win as much as 10%, +but 1-4% is more typical. These results are from Core i7, in 64-bit mode; +Core 2 and Opteron show similar results. (I've run with more iterations +than unusual to make sure the smaller gains don't drown entirely in noise.) + + Benchmark Time(ns) CPU(ns) Iterations + --------------------------------------------------- + BM_UFlat/0 74665 74428 182055 1.3GB/s html [ +3.1%] + BM_UFlat/1 714106 711997 19663 940.4MB/s urls [ +4.4%] + BM_UFlat/2 9820 9789 1427115 12.1GB/s jpg [ -1.2%] + BM_UFlat/3 30461 30380 465116 2.9GB/s pdf [ +0.8%] + BM_UFlat/4 301445 300568 46512 1.3GB/s html4 [ +2.2%] + BM_UFlat/5 29338 29263 479452 801.8MB/s cp [ +1.6%] + BM_UFlat/6 13004 12970 1000000 819.9MB/s c [ +2.1%] + BM_UFlat/7 4180 4168 3349282 851.4MB/s lsp [ +1.3%] + BM_UFlat/8 1026149 1024000 10000 959.0MB/s xls [+10.7%] + BM_UFlat/9 237441 236830 59072 612.4MB/s txt1 [ +0.3%] + BM_UFlat/10 203966 203298 69307 587.2MB/s txt2 [ +0.8%] + BM_UFlat/11 627230 625000 22400 651.2MB/s txt3 [ +0.7%] + BM_UFlat/12 836188 833979 16787 551.0MB/s txt4 [ +1.3%] + BM_UFlat/13 351904 350750 39886 1.4GB/s bin [ +3.8%] + BM_UFlat/14 45685 45562 308370 800.4MB/s sum [ +5.9%] + BM_UFlat/15 5286 5270 2656546 764.9MB/s man [ +1.5%] + BM_UFlat/16 78774 78544 178117 1.4GB/s pb [ +4.3%] + BM_UFlat/17 242270 241345 58091 728.3MB/s gaviota [ +1.2%] + BM_UValidate/0 42149 42000 333333 2.3GB/s html [ -3.0%] + BM_UValidate/1 432741 431303 32483 1.5GB/s urls [ +7.8%] + BM_UValidate/2 198 197 71428571 600.7GB/s jpg [+16.8%] + BM_UValidate/3 14560 14521 965517 6.1GB/s pdf [ -4.1%] + BM_UValidate/4 169065 168671 83832 2.3GB/s html4 [ -2.9%] + +R=jeff + +Revision created by MOE tool push_codebase. + +------------------------------------------------------------------------ +r40 | snappy.mirrorbot@gmail.com | 2011-06-03 00:57:41 +0200 (Fri, 03 Jun 2011) | 2 lines + +Release Snappy 1.0.3. + +------------------------------------------------------------------------ +r39 | snappy.mirrorbot@gmail.com | 2011-06-02 20:06:54 +0200 (Thu, 02 Jun 2011) | 11 lines + +Remove an unneeded goto in the decompressor; it turns out that the +state of ip_ after decompression (or attempted decompresion) is +completely irrelevant, so we don't need the trailer. + +Performance is, as expected, mostly flat -- there's a curious ~3-5% +loss in the "lsp" test, but that test case is so short it is hard to say +anything definitive about why (most likely, it's some sort of +unrelated effect). + +R=jeff + +------------------------------------------------------------------------ +r38 | snappy.mirrorbot@gmail.com | 2011-06-02 19:59:40 +0200 (Thu, 02 Jun 2011) | 52 lines + +Speed up decompression by caching ip_. + +It is seemingly hard for the compiler to understand that ip_, the current input +pointer into the compressed data stream, can not alias on anything else, and +thus using it directly will incur memory traffic as it cannot be kept in a +register. The code already knew about this and cached it into a local +variable, but since Step() only decoded one tag, it had to move ip_ back into +place between every tag. This seems to have cost us a significant amount of +performance, so changing Step() into a function that decodes as much as it can +before it saves ip_ back and returns. (Note that Step() was already inlined, +so it is not the manual inlining that buys the performance here.) + +The wins are about 3-6% for Core 2, 6-13% on Core i7 and 5-12% on Opteron +(for plain array-to-array decompression, in 64-bit opt mode). + +There is a tiny difference in the behavior here; if an invalid literal is +encountered (ie., the writer refuses the Append() operation), ip_ will now +point to the byte past the tag byte, instead of where the literal was +originally thought to end. However, we don't use ip_ for anything after +DecompressAllTags() has returned, so this should not change external behavior +in any way. + +Microbenchmark results for Core i7, 64-bit (Opteron results are similar): + +Benchmark Time(ns) CPU(ns) Iterations +--------------------------------------------------- +BM_UFlat/0 79134 79110 8835 1.2GB/s html [ +6.2%] +BM_UFlat/1 786126 786096 891 851.8MB/s urls [+10.0%] +BM_UFlat/2 9948 9948 69125 11.9GB/s jpg [ -1.3%] +BM_UFlat/3 31999 31998 21898 2.7GB/s pdf [ +6.5%] +BM_UFlat/4 318909 318829 2204 1.2GB/s html4 [ +6.5%] +BM_UFlat/5 31384 31390 22363 747.5MB/s cp [ +9.2%] +BM_UFlat/6 14037 14034 49858 757.7MB/s c [+10.6%] +BM_UFlat/7 4612 4612 151395 769.5MB/s lsp [ +9.5%] +BM_UFlat/8 1203174 1203007 582 816.3MB/s xls [+19.3%] +BM_UFlat/9 253869 253955 2757 571.1MB/s txt1 [+11.4%] +BM_UFlat/10 219292 219290 3194 544.4MB/s txt2 [+12.1%] +BM_UFlat/11 672135 672131 1000 605.5MB/s txt3 [+11.2%] +BM_UFlat/12 902512 902492 776 509.2MB/s txt4 [+12.5%] +BM_UFlat/13 372110 371998 1881 1.3GB/s bin [ +5.8%] +BM_UFlat/14 50407 50407 10000 723.5MB/s sum [+13.5%] +BM_UFlat/15 5699 5701 100000 707.2MB/s man [+12.4%] +BM_UFlat/16 83448 83424 8383 1.3GB/s pb [ +5.7%] +BM_UFlat/17 256958 256963 2723 684.1MB/s gaviota [ +7.9%] +BM_UValidate/0 42795 42796 16351 2.2GB/s html [+25.8%] +BM_UValidate/1 490672 490622 1427 1.3GB/s urls [+22.7%] +BM_UValidate/2 237 237 2950297 499.0GB/s jpg [+24.9%] +BM_UValidate/3 14610 14611 47901 6.0GB/s pdf [+26.8%] +BM_UValidate/4 171973 171990 4071 2.2GB/s html4 [+25.7%] + + + +------------------------------------------------------------------------ +r37 | snappy.mirrorbot@gmail.com | 2011-05-17 10:48:25 +0200 (Tue, 17 May 2011) | 10 lines + + +Fix the numbering of the headlines in the Snappy format description. + +R=csilvers +DELTA=4 (0 added, 0 deleted, 4 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1906 + +------------------------------------------------------------------------ +r36 | snappy.mirrorbot@gmail.com | 2011-05-16 10:59:18 +0200 (Mon, 16 May 2011) | 12 lines + + +Fix public issue #32: Add compressed format documentation for Snappy. +This text is new, but an earlier version from Zeev Tarantov was used +as reference. + +R=csilvers +DELTA=112 (111 added, 0 deleted, 1 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1867 + +------------------------------------------------------------------------ +r35 | snappy.mirrorbot@gmail.com | 2011-05-09 23:29:02 +0200 (Mon, 09 May 2011) | 12 lines + + +Fix public issue #39: Pick out the median runs based on CPU time, +not real time. Also, use nth_element instead of sort, since we +only need one element. + +R=csilvers +DELTA=5 (3 added, 0 deleted, 2 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1799 + +------------------------------------------------------------------------ +r34 | snappy.mirrorbot@gmail.com | 2011-05-09 23:28:45 +0200 (Mon, 09 May 2011) | 19 lines + + +Fix public issue #38: Make the microbenchmark framework handle +properly cases where gettimeofday() can stand return the same +result twice (as sometimes on GNU/Hurd) or go backwards +(as when the user adjusts the clock). We avoid a division-by-zero, +and put a lower bound on the number of iterations -- the same +amount as we use to calibrate. + +We should probably use CLOCK_MONOTONIC for platforms that support +it, to be robust against clock adjustments; we already use Windows' +monotonic timers. However, that's for a later changelist. + +R=csilvers +DELTA=7 (5 added, 0 deleted, 2 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1798 + +------------------------------------------------------------------------ +r33 | snappy.mirrorbot@gmail.com | 2011-05-04 01:22:52 +0200 (Wed, 04 May 2011) | 11 lines + + +Fix public issue #37: Only link snappy_unittest against -lz and other autodetected +libraries, not libsnappy.so (which doesn't need any such dependency). + +R=csilvers +DELTA=20 (14 added, 0 deleted, 6 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1710 + +------------------------------------------------------------------------ +r32 | snappy.mirrorbot@gmail.com | 2011-05-04 01:22:33 +0200 (Wed, 04 May 2011) | 11 lines + + +Release Snappy 1.0.2, to get the license change and various other fixes into +a release. + +R=csilvers +DELTA=239 (236 added, 0 deleted, 3 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1709 + +------------------------------------------------------------------------ +r31 | snappy.mirrorbot@gmail.com | 2011-04-26 14:34:55 +0200 (Tue, 26 Apr 2011) | 15 lines + + +Fix public issue #30: Stop using gettimeofday() altogether on Win32, +as MSVC doesn't include it. Replace with QueryPerformanceCounter(), +which is monotonic and probably reasonably high-resolution. +(Some machines have traditionally had bugs in QPC, but they should +be relatively rare these days, and there's really no much better +alternative that I know of.) + +R=csilvers +DELTA=74 (55 added, 19 deleted, 0 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1556 + +------------------------------------------------------------------------ +r30 | snappy.mirrorbot@gmail.com | 2011-04-26 14:34:37 +0200 (Tue, 26 Apr 2011) | 11 lines + + +Fix public issue #31: Don't reset PATH in autogen.sh; instead, do the trickery +we need for our own build system internally. + +R=csilvers +DELTA=16 (13 added, 1 deleted, 2 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1555 + +------------------------------------------------------------------------ +r29 | snappy.mirrorbot@gmail.com | 2011-04-16 00:55:56 +0200 (Sat, 16 Apr 2011) | 12 lines + + +When including , define WIN32_LEAN_AND_MEAN first, +so we won't pull in macro definitions of things like min() and max(), +which can conflict with . + +R=csilvers +DELTA=1 (1 added, 0 deleted, 0 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1485 + +------------------------------------------------------------------------ +r28 | snappy.mirrorbot@gmail.com | 2011-04-11 11:07:01 +0200 (Mon, 11 Apr 2011) | 15 lines + + +Fix public issue #29: Write CPU timing code for Windows, based on GetProcessTimes() +instead of getursage(). + +I thought I'd already committed this patch, so that the 1.0.1 release already +would have a Windows-compatible snappy_unittest, but I'd seemingly deleted it +instead, so this is a reconstruction. + +R=csilvers +DELTA=43 (39 added, 3 deleted, 1 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1295 + +------------------------------------------------------------------------ +r27 | snappy.mirrorbot@gmail.com | 2011-04-08 11:51:53 +0200 (Fri, 08 Apr 2011) | 22 lines + + +Include C bindings of Snappy, contributed by Martin Gieseking. + +I've made a few changes since Martin's version; mostly style nits, but also +a semantic change -- most functions that return bool in the C++ version now +return an enum, to better match typical C (and zlib) semantics. + +I've kept the copyright notice, since Martin is obviously the author here; +he has signed the contributor license agreement, though, so this should not +hinder Google's use in the future. + +We'll need to update the libtool version number to match the added interface, +but as of http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html +I'm going to wait until public release. + +R=csilvers +DELTA=238 (233 added, 0 deleted, 5 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1294 + +------------------------------------------------------------------------ +r26 | snappy.mirrorbot@gmail.com | 2011-04-07 18:36:43 +0200 (Thu, 07 Apr 2011) | 13 lines + + +Replace geo.protodata with a newer version. + +The data compresses/decompresses slightly faster than the old data, and has +similar density. + +R=lookingbill +DELTA=1 (0 added, 0 deleted, 1 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1288 + +------------------------------------------------------------------------ +r25 | snappy.mirrorbot@gmail.com | 2011-03-30 22:27:53 +0200 (Wed, 30 Mar 2011) | 12 lines + + +Fix public issue #27: Add HAVE_CONFIG_H tests around the config.h +inclusion in snappy-stubs-internal.h, which eases compiling outside the +automake/autoconf framework. + +R=csilvers +DELTA=5 (4 added, 1 deleted, 0 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1152 + +------------------------------------------------------------------------ +r24 | snappy.mirrorbot@gmail.com | 2011-03-30 22:27:39 +0200 (Wed, 30 Mar 2011) | 13 lines + + +Fix public issue #26: Take memory allocation and reallocation entirely out of the +Measure() loop. This gives all algorithms a small speed boost, except Snappy which +already didn't do reallocation (so the measurements were slightly biased in its +favor). + +R=csilvers +DELTA=92 (69 added, 9 deleted, 14 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1151 + +------------------------------------------------------------------------ +r23 | snappy.mirrorbot@gmail.com | 2011-03-30 22:25:09 +0200 (Wed, 30 Mar 2011) | 18 lines + + +Renamed "namespace zippy" to "namespace snappy" to reduce +the differences from the opensource code. Will make it easier +in the future to mix-and-match third-party code that uses +snappy with google code. + +Currently, csearch shows that the only external user of +"namespace zippy" is some bigtable code that accesses +a TEST variable, which is temporarily kept in the zippy +namespace. + +R=sesse +DELTA=123 (18 added, 3 deleted, 102 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1150 + +------------------------------------------------------------------------ +r22 | snappy.mirrorbot@gmail.com | 2011-03-29 00:17:04 +0200 (Tue, 29 Mar 2011) | 11 lines + + +Put back the final few lines of what was truncated during the +license header change. + +R=csilvers +DELTA=5 (4 added, 0 deleted, 1 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1094 + +------------------------------------------------------------------------ +r21 | snappy.mirrorbot@gmail.com | 2011-03-26 03:34:34 +0100 (Sat, 26 Mar 2011) | 20 lines + + +Change on 2011-03-25 19:18:00-07:00 by sesse + + Replace the Apache 2.0 license header by the BSD-type license header; + somehow a lot of the files were missed in the last round. + + R=dannyb,csilvers + DELTA=147 (74 added, 2 deleted, 71 changed) + +Change on 2011-03-25 19:25:07-07:00 by sesse + + Unbreak the build; the relicensing removed a bit too much (only comments + were intended, but I also accidentially removed some of the top lines of + the actual source). + + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1072 + +------------------------------------------------------------------------ +r20 | snappy.mirrorbot@gmail.com | 2011-03-25 17:14:41 +0100 (Fri, 25 Mar 2011) | 10 lines + + +Change Snappy from the Apache 2.0 to a BSD-type license. + +R=dannyb +DELTA=328 (80 added, 184 deleted, 64 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1061 + +------------------------------------------------------------------------ +r19 | snappy.mirrorbot@gmail.com | 2011-03-25 01:39:01 +0100 (Fri, 25 Mar 2011) | 11 lines + + +Release Snappy 1.0.1, to soup up all the various small changes +that have been made since release. + +R=csilvers +DELTA=266 (260 added, 0 deleted, 6 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1057 + +------------------------------------------------------------------------ +r18 | snappy.mirrorbot@gmail.com | 2011-03-24 20:15:54 +0100 (Thu, 24 Mar 2011) | 11 lines + + +Fix a microbenchmark crash on mingw32; seemingly %lld is not universally +supported on Windows, and %I64d is recommended instead. + +R=csilvers +DELTA=6 (5 added, 0 deleted, 1 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1034 + +------------------------------------------------------------------------ +r17 | snappy.mirrorbot@gmail.com | 2011-03-24 20:15:27 +0100 (Thu, 24 Mar 2011) | 13 lines + + +Fix public issue #19: Fix unit test when Google Test is installed but the +gflags package isn't (Google Test is not properly initialized). + +Patch by Martin Gieseking. + +R=csilvers +DELTA=2 (1 added, 0 deleted, 1 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1033 + +------------------------------------------------------------------------ +r16 | snappy.mirrorbot@gmail.com | 2011-03-24 20:13:57 +0100 (Thu, 24 Mar 2011) | 15 lines + + +Make the unit test work on systems without mmap(). This is required for, +among others, Windows support. For Windows in specific, we could have used +CreateFileMapping/MapViewOfFile, but this should at least get us a bit closer +to compiling, and is of course also relevant for embedded systems with no MMU. + +(Part 2/2) + +R=csilvers +DELTA=15 (12 added, 3 deleted, 0 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1032 + +------------------------------------------------------------------------ +r15 | snappy.mirrorbot@gmail.com | 2011-03-24 20:12:27 +0100 (Thu, 24 Mar 2011) | 15 lines + + +Make the unit test work on systems without mmap(). This is required for, +among others, Windows support. For Windows in specific, we could have used +CreateFileMapping/MapViewOfFile, but this should at least get us a bit closer +to compiling, and is of course also relevant for embedded systems with no MMU. + +(Part 1/2) + +R=csilvers +DELTA=9 (8 added, 0 deleted, 1 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1031 + +------------------------------------------------------------------------ +r14 | snappy.mirrorbot@gmail.com | 2011-03-24 00:17:36 +0100 (Thu, 24 Mar 2011) | 14 lines + + +Fix public issue #12: Don't keep autogenerated auto* files in Subversion; +it causes problems with others sending patches etc.. + +We can't get this 100% hermetic anyhow, due to files like lt~obsolete.m4, +so we can just as well go cleanly in the other direction. + +R=csilvers +DELTA=21038 (0 added, 21036 deleted, 2 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=1012 + +------------------------------------------------------------------------ +r13 | snappy.mirrorbot@gmail.com | 2011-03-23 18:50:49 +0100 (Wed, 23 Mar 2011) | 11 lines + + +Fix public issue tracker bug #3: Call AC_SUBST([LIBTOOL_DEPS]), or the rule +to rebuild libtool in Makefile.am won't work. + +R=csilvers +DELTA=1 (1 added, 0 deleted, 0 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=997 + +------------------------------------------------------------------------ +r12 | snappy.mirrorbot@gmail.com | 2011-03-23 12:16:39 +0100 (Wed, 23 Mar 2011) | 11 lines + + +Fix public issue #10: Don't add GTEST_CPPFLAGS to snappy_unittest_CXXFLAGS; +it's not needed (CPPFLAGS are always included when compiling). + +R=csilvers +DELTA=1 (0 added, 1 deleted, 0 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=994 + +------------------------------------------------------------------------ +r11 | snappy.mirrorbot@gmail.com | 2011-03-23 12:16:18 +0100 (Wed, 23 Mar 2011) | 11 lines + + +Fix public issue #9: Add -Wall -Werror to automake flags. +(This concerns automake itself, not the C++ compiler.) + +R=csilvers +DELTA=4 (3 added, 0 deleted, 1 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=993 + +------------------------------------------------------------------------ +r10 | snappy.mirrorbot@gmail.com | 2011-03-23 12:13:37 +0100 (Wed, 23 Mar 2011) | 10 lines + + +Fix a typo in the Snappy README file. + +R=csilvers +DELTA=1 (0 added, 0 deleted, 1 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=992 + +------------------------------------------------------------------------ +r9 | snappy.mirrorbot@gmail.com | 2011-03-23 12:13:13 +0100 (Wed, 23 Mar 2011) | 11 lines + + +Fix public issue #6: Add a --with-gflags for disabling gflags autodetection +and using a manually given setting (use/don't use) instead. + +R=csilvers +DELTA=16 (13 added, 0 deleted, 3 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=991 + +------------------------------------------------------------------------ +r8 | snappy.mirrorbot@gmail.com | 2011-03-23 12:12:44 +0100 (Wed, 23 Mar 2011) | 12 lines + + +Fix public issue #5: Replace the EXTRA_LIBSNAPPY_LDFLAGS setup with something +slightly more standard, that also doesn't leak libtool command-line into +configure.ac. + +R=csilvers +DELTA=7 (0 added, 4 deleted, 3 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=990 + +------------------------------------------------------------------------ +r7 | snappy.mirrorbot@gmail.com | 2011-03-23 12:12:22 +0100 (Wed, 23 Mar 2011) | 10 lines + + +Fix public issue #4: Properly quote all macro arguments in configure.ac. + +R=csilvers +DELTA=16 (0 added, 0 deleted, 16 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=989 + +------------------------------------------------------------------------ +r6 | snappy.mirrorbot@gmail.com | 2011-03-23 12:11:54 +0100 (Wed, 23 Mar 2011) | 11 lines + + +Fix public issue #7: Don't use internal variables named ac_*, as those belong +to autoconf's namespace. + +R=csilvers +DELTA=6 (0 added, 0 deleted, 6 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=988 + +------------------------------------------------------------------------ +r5 | snappy.mirrorbot@gmail.com | 2011-03-23 12:11:09 +0100 (Wed, 23 Mar 2011) | 10 lines + + +Add missing licensing headers to a few files. (Part 2/2.) + +R=csilvers +DELTA=12 (12 added, 0 deleted, 0 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=987 + +------------------------------------------------------------------------ +r4 | snappy.mirrorbot@gmail.com | 2011-03-23 12:10:39 +0100 (Wed, 23 Mar 2011) | 10 lines + + +Add mising licensing headers to a few files. (Part 1/2.) + +R=csilvers +DELTA=24 (24 added, 0 deleted, 0 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=986 + +------------------------------------------------------------------------ +r3 | snappy.mirrorbot@gmail.com | 2011-03-23 12:10:04 +0100 (Wed, 23 Mar 2011) | 11 lines + + +Use the correct license file for the Apache 2.0 license; +spotted by Florian Weimer. + +R=csilvers +DELTA=202 (174 added, 0 deleted, 28 changed) + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION=985 + +------------------------------------------------------------------------ +r2 | snappy.mirrorbot@gmail.com | 2011-03-18 18:14:15 +0100 (Fri, 18 Mar 2011) | 6 lines + + + + +Revision created by MOE tool push_codebase. +MOE_MIGRATION= + +------------------------------------------------------------------------ +r1 | sesse@google.com | 2011-03-18 18:13:52 +0100 (Fri, 18 Mar 2011) | 2 lines + +Create trunk directory. + +------------------------------------------------------------------------ diff --git a/snappy/snappy-1.0.5/INSTALL b/snappy/snappy-1.0.5/INSTALL new file mode 100644 index 00000000..7d1c323b --- /dev/null +++ b/snappy/snappy-1.0.5/INSTALL @@ -0,0 +1,365 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006, 2007, 2008, 2009 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. + +Basic Installation +================== + + Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + + The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package, generally using the just-built uninstalled binaries. + + 4. Type `make install' to install the programs and any data files and + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. + + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. + +Installation Names +================== + + By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS + KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/snappy/snappy-1.0.5/Makefile b/snappy/snappy-1.0.5/Makefile new file mode 100644 index 00000000..cfa78497 --- /dev/null +++ b/snappy/snappy-1.0.5/Makefile @@ -0,0 +1,927 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# Makefile. Generated from Makefile.in by configure. + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + + + + + + +pkgdatadir = $(datadir)/snappy +pkgincludedir = $(includedir)/snappy +pkglibdir = $(libdir)/snappy +pkglibexecdir = $(libexecdir)/snappy +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = x86_64-unknown-linux-gnu +host_triplet = x86_64-unknown-linux-gnu +TESTS = snappy_unittest$(EXEEXT) +noinst_PROGRAMS = $(am__EXEEXT_1) +subdir = . +DIST_COMMON = README $(am__configure_deps) $(dist_doc_DATA) \ + $(include_HEADERS) $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(srcdir)/snappy-stubs-public.h.in $(top_srcdir)/configure \ + AUTHORS COPYING ChangeLog INSTALL NEWS config.guess config.sub \ + depcomp install-sh ltmain.sh missing +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gtest.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = snappy-stubs-public.h +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" \ + "$(DESTDIR)$(includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +libsnappy_la_LIBADD = +am_libsnappy_la_OBJECTS = snappy.lo snappy-sinksource.lo \ + snappy-stubs-internal.lo snappy-c.lo +libsnappy_la_OBJECTS = $(am_libsnappy_la_OBJECTS) +libsnappy_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(libsnappy_la_LDFLAGS) $(LDFLAGS) -o $@ +am__EXEEXT_1 = snappy_unittest$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +am_snappy_unittest_OBJECTS = \ + snappy_unittest-snappy_unittest.$(OBJEXT) \ + snappy_unittest-snappy-test.$(OBJEXT) +snappy_unittest_OBJECTS = $(am_snappy_unittest_OBJECTS) +am__DEPENDENCIES_1 = +snappy_unittest_DEPENDENCIES = libsnappy.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +snappy_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(snappy_unittest_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I. +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libsnappy_la_SOURCES) $(snappy_unittest_SOURCES) +DIST_SOURCES = $(libsnappy_la_SOURCES) $(snappy_unittest_SOURCES) +DATA = $(dist_doc_DATA) +HEADERS = $(include_HEADERS) $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +am__tty_colors = \ +red=; grn=; lgn=; blu=; std= +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + { test ! -d "$(distdir)" \ + || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr "$(distdir)"; }; } +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +distcleancheck_listfiles = find . -type f -print +ACLOCAL = ${SHELL} /home/dhruba/local/externals/java/leveldb/source/snappy-1.0.5/missing --run aclocal-1.11 +AMTAR = ${SHELL} /home/dhruba/local/externals/java/leveldb/source/snappy-1.0.5/missing --run tar +AR = ar +AUTOCONF = ${SHELL} /home/dhruba/local/externals/java/leveldb/source/snappy-1.0.5/missing --run autoconf +AUTOHEADER = ${SHELL} /home/dhruba/local/externals/java/leveldb/source/snappy-1.0.5/missing --run autoheader +AUTOMAKE = ${SHELL} /home/dhruba/local/externals/java/leveldb/source/snappy-1.0.5/missing --run automake-1.11 +AWK = gawk +CC = gcc +CCDEPMODE = depmode=gcc3 +CFLAGS = -g -O2 +CPP = gcc -E +CPPFLAGS = +CXX = g++ +CXXCPP = g++ -E +CXXDEPMODE = depmode=gcc3 +CXXFLAGS = -g -O2 +CYGPATH_W = echo +DEFS = -DHAVE_CONFIG_H +DEPDIR = .deps +DSYMUTIL = +DUMPBIN = +ECHO_C = +ECHO_N = -n +ECHO_T = +EGREP = /bin/grep -E +EXEEXT = +FGREP = /bin/grep -F +GREP = /bin/grep +GTEST_CONFIG = +GTEST_CPPFLAGS = +GTEST_CXXFLAGS = +GTEST_LDFLAGS = +GTEST_LIBS = +GTEST_VERSION = +HAVE_GTEST = no +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} +INSTALL_SCRIPT = ${INSTALL} +INSTALL_STRIP_PROGRAM = $(install_sh) -c -s +LD = /usr/bin/ld -m elf_x86_64 +LDFLAGS = +LIBOBJS = +LIBS = +LIBTOOL = $(SHELL) $(top_builddir)/libtool +LIBTOOL_DEPS = ./ltmain.sh +LIPO = +LN_S = ln -s +LTLIBOBJS = +MAKEINFO = ${SHELL} /home/dhruba/local/externals/java/leveldb/source/snappy-1.0.5/missing --run makeinfo +MKDIR_P = /bin/mkdir -p +NM = /usr/bin/nm -B +NMEDIT = +OBJDUMP = objdump +OBJEXT = o +OTOOL = +OTOOL64 = +PACKAGE = snappy +PACKAGE_BUGREPORT = +PACKAGE_NAME = snappy +PACKAGE_STRING = snappy 1.0.5 +PACKAGE_TARNAME = snappy +PACKAGE_URL = +PACKAGE_VERSION = 1.0.5 +PATH_SEPARATOR = : +PKG_CONFIG = /usr/bin/pkg-config +RANLIB = ranlib +SED = /bin/sed +SET_MAKE = +SHELL = /bin/sh +SNAPPY_LTVERSION = 1:5:0 +SNAPPY_MAJOR = 1 +SNAPPY_MINOR = 0 +SNAPPY_PATCHLEVEL = 5 +STRIP = strip +UNITTEST_LIBS = -lz +VERSION = 1.0.5 +abs_builddir = /home/dhruba/local/externals/java/leveldb/source/snappy-1.0.5 +abs_srcdir = /home/dhruba/local/externals/java/leveldb/source/snappy-1.0.5 +abs_top_builddir = /home/dhruba/local/externals/java/leveldb/source/snappy-1.0.5 +abs_top_srcdir = /home/dhruba/local/externals/java/leveldb/source/snappy-1.0.5 +ac_ct_CC = gcc +ac_ct_CXX = g++ +ac_ct_DUMPBIN = +ac_cv_have_stddef_h = 1 +ac_cv_have_stdint_h = 1 +am__include = include +am__leading_dot = . +am__quote = +am__tar = ${AMTAR} chof - "$$tardir" +am__untar = ${AMTAR} xf - +bindir = ${exec_prefix}/bin +build = x86_64-unknown-linux-gnu +build_alias = +build_cpu = x86_64 +build_os = linux-gnu +build_vendor = unknown +builddir = . +datadir = ${datarootdir} +datarootdir = ${prefix}/share +docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} +dvidir = ${docdir} +exec_prefix = ${prefix} +gflags_CFLAGS = +gflags_LIBS = +host = x86_64-unknown-linux-gnu +host_alias = +host_cpu = x86_64 +host_os = linux-gnu +host_vendor = unknown +htmldir = ${docdir} +includedir = ${prefix}/include +infodir = ${datarootdir}/info +install_sh = ${SHELL} /home/dhruba/local/externals/java/leveldb/source/snappy-1.0.5/install-sh +libdir = ${exec_prefix}/lib +libexecdir = ${exec_prefix}/libexec +localedir = ${datarootdir}/locale +localstatedir = ${prefix}/var +lt_ECHO = echo +mandir = ${datarootdir}/man +mkdir_p = /bin/mkdir -p +oldincludedir = /usr/include +pdfdir = ${docdir} +prefix = /usr/local +program_transform_name = s,x,x, +psdir = ${docdir} +sbindir = ${exec_prefix}/sbin +sharedstatedir = ${prefix}/com +srcdir = . +sysconfdir = ${prefix}/etc +target_alias = +top_build_prefix = +top_builddir = . +top_srcdir = . +ACLOCAL_AMFLAGS = -I m4 + +# Library. +lib_LTLIBRARIES = libsnappy.la +libsnappy_la_SOURCES = snappy.cc snappy-sinksource.cc snappy-stubs-internal.cc snappy-c.cc +libsnappy_la_LDFLAGS = -version-info $(SNAPPY_LTVERSION) +include_HEADERS = snappy.h snappy-sinksource.h snappy-stubs-public.h snappy-c.h +noinst_HEADERS = snappy-internal.h snappy-stubs-internal.h snappy-test.h + +# Unit tests and benchmarks. +snappy_unittest_CPPFLAGS = $(gflags_CFLAGS) $(GTEST_CPPFLAGS) +snappy_unittest_SOURCES = snappy_unittest.cc snappy-test.cc +snappy_unittest_LDFLAGS = $(GTEST_LDFLAGS) +snappy_unittest_LDADD = libsnappy.la $(UNITTEST_LIBS) $(gflags_LIBS) $(GTEST_LIBS) +EXTRA_DIST = autogen.sh testdata/alice29.txt testdata/asyoulik.txt testdata/baddata1.snappy testdata/baddata2.snappy testdata/baddata3.snappy testdata/cp.html testdata/fields.c testdata/geo.protodata testdata/grammar.lsp testdata/house.jpg testdata/html testdata/html_x_4 testdata/kennedy.xls testdata/kppkn.gtb testdata/lcet10.txt testdata/mapreduce-osdi-1.pdf testdata/plrabn12.txt testdata/ptt5 testdata/sum testdata/urls.10K testdata/xargs.1 +dist_doc_DATA = ChangeLog COPYING INSTALL NEWS README format_description.txt +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +am--refresh: + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +snappy-stubs-public.h: $(top_builddir)/config.status $(srcdir)/snappy-stubs-public.h.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libsnappy.la: $(libsnappy_la_OBJECTS) $(libsnappy_la_DEPENDENCIES) + $(libsnappy_la_LINK) -rpath $(libdir) $(libsnappy_la_OBJECTS) $(libsnappy_la_LIBADD) $(LIBS) + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +snappy_unittest$(EXEEXT): $(snappy_unittest_OBJECTS) $(snappy_unittest_DEPENDENCIES) + @rm -f snappy_unittest$(EXEEXT) + $(snappy_unittest_LINK) $(snappy_unittest_OBJECTS) $(snappy_unittest_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +include ./$(DEPDIR)/snappy-c.Plo +include ./$(DEPDIR)/snappy-sinksource.Plo +include ./$(DEPDIR)/snappy-stubs-internal.Plo +include ./$(DEPDIR)/snappy.Plo +include ./$(DEPDIR)/snappy_unittest-snappy-test.Po +include ./$(DEPDIR)/snappy_unittest-snappy_unittest.Po + +.cc.o: + $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< + $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXXCOMPILE) -c -o $@ $< + +.cc.obj: + $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` + $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: + $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< + $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +# source='$<' object='$@' libtool=yes \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(LTCXXCOMPILE) -c -o $@ $< + +snappy_unittest-snappy_unittest.o: snappy_unittest.cc + $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT snappy_unittest-snappy_unittest.o -MD -MP -MF $(DEPDIR)/snappy_unittest-snappy_unittest.Tpo -c -o snappy_unittest-snappy_unittest.o `test -f 'snappy_unittest.cc' || echo '$(srcdir)/'`snappy_unittest.cc + $(am__mv) $(DEPDIR)/snappy_unittest-snappy_unittest.Tpo $(DEPDIR)/snappy_unittest-snappy_unittest.Po +# source='snappy_unittest.cc' object='snappy_unittest-snappy_unittest.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o snappy_unittest-snappy_unittest.o `test -f 'snappy_unittest.cc' || echo '$(srcdir)/'`snappy_unittest.cc + +snappy_unittest-snappy_unittest.obj: snappy_unittest.cc + $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT snappy_unittest-snappy_unittest.obj -MD -MP -MF $(DEPDIR)/snappy_unittest-snappy_unittest.Tpo -c -o snappy_unittest-snappy_unittest.obj `if test -f 'snappy_unittest.cc'; then $(CYGPATH_W) 'snappy_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/snappy_unittest.cc'; fi` + $(am__mv) $(DEPDIR)/snappy_unittest-snappy_unittest.Tpo $(DEPDIR)/snappy_unittest-snappy_unittest.Po +# source='snappy_unittest.cc' object='snappy_unittest-snappy_unittest.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o snappy_unittest-snappy_unittest.obj `if test -f 'snappy_unittest.cc'; then $(CYGPATH_W) 'snappy_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/snappy_unittest.cc'; fi` + +snappy_unittest-snappy-test.o: snappy-test.cc + $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT snappy_unittest-snappy-test.o -MD -MP -MF $(DEPDIR)/snappy_unittest-snappy-test.Tpo -c -o snappy_unittest-snappy-test.o `test -f 'snappy-test.cc' || echo '$(srcdir)/'`snappy-test.cc + $(am__mv) $(DEPDIR)/snappy_unittest-snappy-test.Tpo $(DEPDIR)/snappy_unittest-snappy-test.Po +# source='snappy-test.cc' object='snappy_unittest-snappy-test.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o snappy_unittest-snappy-test.o `test -f 'snappy-test.cc' || echo '$(srcdir)/'`snappy-test.cc + +snappy_unittest-snappy-test.obj: snappy-test.cc + $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT snappy_unittest-snappy-test.obj -MD -MP -MF $(DEPDIR)/snappy_unittest-snappy-test.Tpo -c -o snappy_unittest-snappy-test.obj `if test -f 'snappy-test.cc'; then $(CYGPATH_W) 'snappy-test.cc'; else $(CYGPATH_W) '$(srcdir)/snappy-test.cc'; fi` + $(am__mv) $(DEPDIR)/snappy_unittest-snappy-test.Tpo $(DEPDIR)/snappy_unittest-snappy-test.Po +# source='snappy-test.cc' object='snappy_unittest-snappy-test.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o snappy_unittest-snappy-test.obj `if test -f 'snappy-test.cc'; then $(CYGPATH_W) 'snappy-test.cc'; else $(CYGPATH_W) '$(srcdir)/snappy-test.cc'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt +install-dist_docDATA: $(dist_doc_DATA) + @$(NORMAL_INSTALL) + test -z "$(docdir)" || $(MKDIR_P) "$(DESTDIR)$(docdir)" + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ + done + +uninstall-dist_docDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(docdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(docdir)" && rm -f $$files +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(includedir)" && rm -f $$files + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + echo "$$grn$$dashes"; \ + else \ + echo "$$red$$dashes"; \ + fi; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes$$std"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-lzma: distdir + tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma + $(am__remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lzma*) \ + lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @$(am__cd) '$(distuninstallcheck_dir)' \ + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) $(HEADERS) \ + config.h +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_docDATA install-includeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_docDATA uninstall-includeHEADERS \ + uninstall-libLTLIBRARIES + +.MAKE: all check-am install-am install-strip + +.PHONY: CTAGS GTAGS all all-am am--refresh check check-TESTS check-am \ + clean clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstPROGRAMS ctags dist dist-all dist-bzip2 dist-gzip \ + dist-lzma dist-shar dist-tarZ dist-xz dist-zip distcheck \ + distclean distclean-compile distclean-generic distclean-hdr \ + distclean-libtool distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_docDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am \ + install-includeHEADERS install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-dist_docDATA \ + uninstall-includeHEADERS uninstall-libLTLIBRARIES + + +libtool: $(LIBTOOL_DEPS) + $(SHELL) ./config.status --recheck + +# 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/snappy/snappy-1.0.5/Makefile.am b/snappy/snappy-1.0.5/Makefile.am new file mode 100644 index 00000000..f17b2e35 --- /dev/null +++ b/snappy/snappy-1.0.5/Makefile.am @@ -0,0 +1,23 @@ +ACLOCAL_AMFLAGS = -I m4 + +# Library. +lib_LTLIBRARIES = libsnappy.la +libsnappy_la_SOURCES = snappy.cc snappy-sinksource.cc snappy-stubs-internal.cc snappy-c.cc +libsnappy_la_LDFLAGS = -version-info $(SNAPPY_LTVERSION) + +include_HEADERS = snappy.h snappy-sinksource.h snappy-stubs-public.h snappy-c.h +noinst_HEADERS = snappy-internal.h snappy-stubs-internal.h snappy-test.h + +# Unit tests and benchmarks. +snappy_unittest_CPPFLAGS = $(gflags_CFLAGS) $(GTEST_CPPFLAGS) +snappy_unittest_SOURCES = snappy_unittest.cc snappy-test.cc +snappy_unittest_LDFLAGS = $(GTEST_LDFLAGS) +snappy_unittest_LDADD = libsnappy.la $(UNITTEST_LIBS) $(gflags_LIBS) $(GTEST_LIBS) +TESTS = snappy_unittest +noinst_PROGRAMS = $(TESTS) + +EXTRA_DIST = autogen.sh testdata/alice29.txt testdata/asyoulik.txt testdata/baddata1.snappy testdata/baddata2.snappy testdata/baddata3.snappy testdata/cp.html testdata/fields.c testdata/geo.protodata testdata/grammar.lsp testdata/house.jpg testdata/html testdata/html_x_4 testdata/kennedy.xls testdata/kppkn.gtb testdata/lcet10.txt testdata/mapreduce-osdi-1.pdf testdata/plrabn12.txt testdata/ptt5 testdata/sum testdata/urls.10K testdata/xargs.1 +dist_doc_DATA = ChangeLog COPYING INSTALL NEWS README format_description.txt framing_format.txt + +libtool: $(LIBTOOL_DEPS) + $(SHELL) ./config.status --recheck diff --git a/snappy/snappy-1.0.5/Makefile.in b/snappy/snappy-1.0.5/Makefile.in new file mode 100644 index 00000000..79ac8555 --- /dev/null +++ b/snappy/snappy-1.0.5/Makefile.in @@ -0,0 +1,927 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +TESTS = snappy_unittest$(EXEEXT) +noinst_PROGRAMS = $(am__EXEEXT_1) +subdir = . +DIST_COMMON = README $(am__configure_deps) $(dist_doc_DATA) \ + $(include_HEADERS) $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(srcdir)/snappy-stubs-public.h.in $(top_srcdir)/configure \ + AUTHORS COPYING ChangeLog INSTALL NEWS config.guess config.sub \ + depcomp install-sh ltmain.sh missing +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gtest.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = snappy-stubs-public.h +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" \ + "$(DESTDIR)$(includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +libsnappy_la_LIBADD = +am_libsnappy_la_OBJECTS = snappy.lo snappy-sinksource.lo \ + snappy-stubs-internal.lo snappy-c.lo +libsnappy_la_OBJECTS = $(am_libsnappy_la_OBJECTS) +libsnappy_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(libsnappy_la_LDFLAGS) $(LDFLAGS) -o $@ +am__EXEEXT_1 = snappy_unittest$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +am_snappy_unittest_OBJECTS = \ + snappy_unittest-snappy_unittest.$(OBJEXT) \ + snappy_unittest-snappy-test.$(OBJEXT) +snappy_unittest_OBJECTS = $(am_snappy_unittest_OBJECTS) +am__DEPENDENCIES_1 = +snappy_unittest_DEPENDENCIES = libsnappy.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +snappy_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(snappy_unittest_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libsnappy_la_SOURCES) $(snappy_unittest_SOURCES) +DIST_SOURCES = $(libsnappy_la_SOURCES) $(snappy_unittest_SOURCES) +DATA = $(dist_doc_DATA) +HEADERS = $(include_HEADERS) $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +am__tty_colors = \ +red=; grn=; lgn=; blu=; std= +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + { test ! -d "$(distdir)" \ + || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr "$(distdir)"; }; } +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GTEST_CONFIG = @GTEST_CONFIG@ +GTEST_CPPFLAGS = @GTEST_CPPFLAGS@ +GTEST_CXXFLAGS = @GTEST_CXXFLAGS@ +GTEST_LDFLAGS = @GTEST_LDFLAGS@ +GTEST_LIBS = @GTEST_LIBS@ +GTEST_VERSION = @GTEST_VERSION@ +HAVE_GTEST = @HAVE_GTEST@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SNAPPY_LTVERSION = @SNAPPY_LTVERSION@ +SNAPPY_MAJOR = @SNAPPY_MAJOR@ +SNAPPY_MINOR = @SNAPPY_MINOR@ +SNAPPY_PATCHLEVEL = @SNAPPY_PATCHLEVEL@ +STRIP = @STRIP@ +UNITTEST_LIBS = @UNITTEST_LIBS@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_cv_have_stddef_h = @ac_cv_have_stddef_h@ +ac_cv_have_stdint_h = @ac_cv_have_stdint_h@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gflags_CFLAGS = @gflags_CFLAGS@ +gflags_LIBS = @gflags_LIBS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I m4 + +# Library. +lib_LTLIBRARIES = libsnappy.la +libsnappy_la_SOURCES = snappy.cc snappy-sinksource.cc snappy-stubs-internal.cc snappy-c.cc +libsnappy_la_LDFLAGS = -version-info $(SNAPPY_LTVERSION) +include_HEADERS = snappy.h snappy-sinksource.h snappy-stubs-public.h snappy-c.h +noinst_HEADERS = snappy-internal.h snappy-stubs-internal.h snappy-test.h + +# Unit tests and benchmarks. +snappy_unittest_CPPFLAGS = $(gflags_CFLAGS) $(GTEST_CPPFLAGS) +snappy_unittest_SOURCES = snappy_unittest.cc snappy-test.cc +snappy_unittest_LDFLAGS = $(GTEST_LDFLAGS) +snappy_unittest_LDADD = libsnappy.la $(UNITTEST_LIBS) $(gflags_LIBS) $(GTEST_LIBS) +EXTRA_DIST = autogen.sh testdata/alice29.txt testdata/asyoulik.txt testdata/baddata1.snappy testdata/baddata2.snappy testdata/baddata3.snappy testdata/cp.html testdata/fields.c testdata/geo.protodata testdata/grammar.lsp testdata/house.jpg testdata/html testdata/html_x_4 testdata/kennedy.xls testdata/kppkn.gtb testdata/lcet10.txt testdata/mapreduce-osdi-1.pdf testdata/plrabn12.txt testdata/ptt5 testdata/sum testdata/urls.10K testdata/xargs.1 +dist_doc_DATA = ChangeLog COPYING INSTALL NEWS README format_description.txt framing_format.txt +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +am--refresh: + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +snappy-stubs-public.h: $(top_builddir)/config.status $(srcdir)/snappy-stubs-public.h.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libsnappy.la: $(libsnappy_la_OBJECTS) $(libsnappy_la_DEPENDENCIES) + $(libsnappy_la_LINK) -rpath $(libdir) $(libsnappy_la_OBJECTS) $(libsnappy_la_LIBADD) $(LIBS) + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +snappy_unittest$(EXEEXT): $(snappy_unittest_OBJECTS) $(snappy_unittest_DEPENDENCIES) + @rm -f snappy_unittest$(EXEEXT) + $(snappy_unittest_LINK) $(snappy_unittest_OBJECTS) $(snappy_unittest_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snappy-c.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snappy-sinksource.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snappy-stubs-internal.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snappy.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snappy_unittest-snappy-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snappy_unittest-snappy_unittest.Po@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +snappy_unittest-snappy_unittest.o: snappy_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT snappy_unittest-snappy_unittest.o -MD -MP -MF $(DEPDIR)/snappy_unittest-snappy_unittest.Tpo -c -o snappy_unittest-snappy_unittest.o `test -f 'snappy_unittest.cc' || echo '$(srcdir)/'`snappy_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/snappy_unittest-snappy_unittest.Tpo $(DEPDIR)/snappy_unittest-snappy_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='snappy_unittest.cc' object='snappy_unittest-snappy_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o snappy_unittest-snappy_unittest.o `test -f 'snappy_unittest.cc' || echo '$(srcdir)/'`snappy_unittest.cc + +snappy_unittest-snappy_unittest.obj: snappy_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT snappy_unittest-snappy_unittest.obj -MD -MP -MF $(DEPDIR)/snappy_unittest-snappy_unittest.Tpo -c -o snappy_unittest-snappy_unittest.obj `if test -f 'snappy_unittest.cc'; then $(CYGPATH_W) 'snappy_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/snappy_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/snappy_unittest-snappy_unittest.Tpo $(DEPDIR)/snappy_unittest-snappy_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='snappy_unittest.cc' object='snappy_unittest-snappy_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o snappy_unittest-snappy_unittest.obj `if test -f 'snappy_unittest.cc'; then $(CYGPATH_W) 'snappy_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/snappy_unittest.cc'; fi` + +snappy_unittest-snappy-test.o: snappy-test.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT snappy_unittest-snappy-test.o -MD -MP -MF $(DEPDIR)/snappy_unittest-snappy-test.Tpo -c -o snappy_unittest-snappy-test.o `test -f 'snappy-test.cc' || echo '$(srcdir)/'`snappy-test.cc +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/snappy_unittest-snappy-test.Tpo $(DEPDIR)/snappy_unittest-snappy-test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='snappy-test.cc' object='snappy_unittest-snappy-test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o snappy_unittest-snappy-test.o `test -f 'snappy-test.cc' || echo '$(srcdir)/'`snappy-test.cc + +snappy_unittest-snappy-test.obj: snappy-test.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT snappy_unittest-snappy-test.obj -MD -MP -MF $(DEPDIR)/snappy_unittest-snappy-test.Tpo -c -o snappy_unittest-snappy-test.obj `if test -f 'snappy-test.cc'; then $(CYGPATH_W) 'snappy-test.cc'; else $(CYGPATH_W) '$(srcdir)/snappy-test.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/snappy_unittest-snappy-test.Tpo $(DEPDIR)/snappy_unittest-snappy-test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='snappy-test.cc' object='snappy_unittest-snappy-test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o snappy_unittest-snappy-test.obj `if test -f 'snappy-test.cc'; then $(CYGPATH_W) 'snappy-test.cc'; else $(CYGPATH_W) '$(srcdir)/snappy-test.cc'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt +install-dist_docDATA: $(dist_doc_DATA) + @$(NORMAL_INSTALL) + test -z "$(docdir)" || $(MKDIR_P) "$(DESTDIR)$(docdir)" + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ + done + +uninstall-dist_docDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(docdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(docdir)" && rm -f $$files +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(includedir)" && rm -f $$files + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + echo "$$grn$$dashes"; \ + else \ + echo "$$red$$dashes"; \ + fi; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes$$std"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-lzma: distdir + tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma + $(am__remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lzma*) \ + lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @$(am__cd) '$(distuninstallcheck_dir)' \ + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) $(HEADERS) \ + config.h +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_docDATA install-includeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_docDATA uninstall-includeHEADERS \ + uninstall-libLTLIBRARIES + +.MAKE: all check-am install-am install-strip + +.PHONY: CTAGS GTAGS all all-am am--refresh check check-TESTS check-am \ + clean clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstPROGRAMS ctags dist dist-all dist-bzip2 dist-gzip \ + dist-lzma dist-shar dist-tarZ dist-xz dist-zip distcheck \ + distclean distclean-compile distclean-generic distclean-hdr \ + distclean-libtool distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_docDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am \ + install-includeHEADERS install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-dist_docDATA \ + uninstall-includeHEADERS uninstall-libLTLIBRARIES + + +libtool: $(LIBTOOL_DEPS) + $(SHELL) ./config.status --recheck + +# 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/snappy/snappy-1.0.5/Makefile.in.orig b/snappy/snappy-1.0.5/Makefile.in.orig new file mode 100644 index 00000000..79ac8555 --- /dev/null +++ b/snappy/snappy-1.0.5/Makefile.in.orig @@ -0,0 +1,927 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +TESTS = snappy_unittest$(EXEEXT) +noinst_PROGRAMS = $(am__EXEEXT_1) +subdir = . +DIST_COMMON = README $(am__configure_deps) $(dist_doc_DATA) \ + $(include_HEADERS) $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(srcdir)/snappy-stubs-public.h.in $(top_srcdir)/configure \ + AUTHORS COPYING ChangeLog INSTALL NEWS config.guess config.sub \ + depcomp install-sh ltmain.sh missing +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gtest.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = snappy-stubs-public.h +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" \ + "$(DESTDIR)$(includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +libsnappy_la_LIBADD = +am_libsnappy_la_OBJECTS = snappy.lo snappy-sinksource.lo \ + snappy-stubs-internal.lo snappy-c.lo +libsnappy_la_OBJECTS = $(am_libsnappy_la_OBJECTS) +libsnappy_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(libsnappy_la_LDFLAGS) $(LDFLAGS) -o $@ +am__EXEEXT_1 = snappy_unittest$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +am_snappy_unittest_OBJECTS = \ + snappy_unittest-snappy_unittest.$(OBJEXT) \ + snappy_unittest-snappy-test.$(OBJEXT) +snappy_unittest_OBJECTS = $(am_snappy_unittest_OBJECTS) +am__DEPENDENCIES_1 = +snappy_unittest_DEPENDENCIES = libsnappy.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +snappy_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(snappy_unittest_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libsnappy_la_SOURCES) $(snappy_unittest_SOURCES) +DIST_SOURCES = $(libsnappy_la_SOURCES) $(snappy_unittest_SOURCES) +DATA = $(dist_doc_DATA) +HEADERS = $(include_HEADERS) $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +am__tty_colors = \ +red=; grn=; lgn=; blu=; std= +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + { test ! -d "$(distdir)" \ + || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr "$(distdir)"; }; } +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GTEST_CONFIG = @GTEST_CONFIG@ +GTEST_CPPFLAGS = @GTEST_CPPFLAGS@ +GTEST_CXXFLAGS = @GTEST_CXXFLAGS@ +GTEST_LDFLAGS = @GTEST_LDFLAGS@ +GTEST_LIBS = @GTEST_LIBS@ +GTEST_VERSION = @GTEST_VERSION@ +HAVE_GTEST = @HAVE_GTEST@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SNAPPY_LTVERSION = @SNAPPY_LTVERSION@ +SNAPPY_MAJOR = @SNAPPY_MAJOR@ +SNAPPY_MINOR = @SNAPPY_MINOR@ +SNAPPY_PATCHLEVEL = @SNAPPY_PATCHLEVEL@ +STRIP = @STRIP@ +UNITTEST_LIBS = @UNITTEST_LIBS@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_cv_have_stddef_h = @ac_cv_have_stddef_h@ +ac_cv_have_stdint_h = @ac_cv_have_stdint_h@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gflags_CFLAGS = @gflags_CFLAGS@ +gflags_LIBS = @gflags_LIBS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I m4 + +# Library. +lib_LTLIBRARIES = libsnappy.la +libsnappy_la_SOURCES = snappy.cc snappy-sinksource.cc snappy-stubs-internal.cc snappy-c.cc +libsnappy_la_LDFLAGS = -version-info $(SNAPPY_LTVERSION) +include_HEADERS = snappy.h snappy-sinksource.h snappy-stubs-public.h snappy-c.h +noinst_HEADERS = snappy-internal.h snappy-stubs-internal.h snappy-test.h + +# Unit tests and benchmarks. +snappy_unittest_CPPFLAGS = $(gflags_CFLAGS) $(GTEST_CPPFLAGS) +snappy_unittest_SOURCES = snappy_unittest.cc snappy-test.cc +snappy_unittest_LDFLAGS = $(GTEST_LDFLAGS) +snappy_unittest_LDADD = libsnappy.la $(UNITTEST_LIBS) $(gflags_LIBS) $(GTEST_LIBS) +EXTRA_DIST = autogen.sh testdata/alice29.txt testdata/asyoulik.txt testdata/baddata1.snappy testdata/baddata2.snappy testdata/baddata3.snappy testdata/cp.html testdata/fields.c testdata/geo.protodata testdata/grammar.lsp testdata/house.jpg testdata/html testdata/html_x_4 testdata/kennedy.xls testdata/kppkn.gtb testdata/lcet10.txt testdata/mapreduce-osdi-1.pdf testdata/plrabn12.txt testdata/ptt5 testdata/sum testdata/urls.10K testdata/xargs.1 +dist_doc_DATA = ChangeLog COPYING INSTALL NEWS README format_description.txt framing_format.txt +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +am--refresh: + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +snappy-stubs-public.h: $(top_builddir)/config.status $(srcdir)/snappy-stubs-public.h.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libsnappy.la: $(libsnappy_la_OBJECTS) $(libsnappy_la_DEPENDENCIES) + $(libsnappy_la_LINK) -rpath $(libdir) $(libsnappy_la_OBJECTS) $(libsnappy_la_LIBADD) $(LIBS) + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +snappy_unittest$(EXEEXT): $(snappy_unittest_OBJECTS) $(snappy_unittest_DEPENDENCIES) + @rm -f snappy_unittest$(EXEEXT) + $(snappy_unittest_LINK) $(snappy_unittest_OBJECTS) $(snappy_unittest_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snappy-c.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snappy-sinksource.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snappy-stubs-internal.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snappy.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snappy_unittest-snappy-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snappy_unittest-snappy_unittest.Po@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +snappy_unittest-snappy_unittest.o: snappy_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT snappy_unittest-snappy_unittest.o -MD -MP -MF $(DEPDIR)/snappy_unittest-snappy_unittest.Tpo -c -o snappy_unittest-snappy_unittest.o `test -f 'snappy_unittest.cc' || echo '$(srcdir)/'`snappy_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/snappy_unittest-snappy_unittest.Tpo $(DEPDIR)/snappy_unittest-snappy_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='snappy_unittest.cc' object='snappy_unittest-snappy_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o snappy_unittest-snappy_unittest.o `test -f 'snappy_unittest.cc' || echo '$(srcdir)/'`snappy_unittest.cc + +snappy_unittest-snappy_unittest.obj: snappy_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT snappy_unittest-snappy_unittest.obj -MD -MP -MF $(DEPDIR)/snappy_unittest-snappy_unittest.Tpo -c -o snappy_unittest-snappy_unittest.obj `if test -f 'snappy_unittest.cc'; then $(CYGPATH_W) 'snappy_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/snappy_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/snappy_unittest-snappy_unittest.Tpo $(DEPDIR)/snappy_unittest-snappy_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='snappy_unittest.cc' object='snappy_unittest-snappy_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o snappy_unittest-snappy_unittest.obj `if test -f 'snappy_unittest.cc'; then $(CYGPATH_W) 'snappy_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/snappy_unittest.cc'; fi` + +snappy_unittest-snappy-test.o: snappy-test.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT snappy_unittest-snappy-test.o -MD -MP -MF $(DEPDIR)/snappy_unittest-snappy-test.Tpo -c -o snappy_unittest-snappy-test.o `test -f 'snappy-test.cc' || echo '$(srcdir)/'`snappy-test.cc +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/snappy_unittest-snappy-test.Tpo $(DEPDIR)/snappy_unittest-snappy-test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='snappy-test.cc' object='snappy_unittest-snappy-test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o snappy_unittest-snappy-test.o `test -f 'snappy-test.cc' || echo '$(srcdir)/'`snappy-test.cc + +snappy_unittest-snappy-test.obj: snappy-test.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT snappy_unittest-snappy-test.obj -MD -MP -MF $(DEPDIR)/snappy_unittest-snappy-test.Tpo -c -o snappy_unittest-snappy-test.obj `if test -f 'snappy-test.cc'; then $(CYGPATH_W) 'snappy-test.cc'; else $(CYGPATH_W) '$(srcdir)/snappy-test.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/snappy_unittest-snappy-test.Tpo $(DEPDIR)/snappy_unittest-snappy-test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='snappy-test.cc' object='snappy_unittest-snappy-test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o snappy_unittest-snappy-test.obj `if test -f 'snappy-test.cc'; then $(CYGPATH_W) 'snappy-test.cc'; else $(CYGPATH_W) '$(srcdir)/snappy-test.cc'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt +install-dist_docDATA: $(dist_doc_DATA) + @$(NORMAL_INSTALL) + test -z "$(docdir)" || $(MKDIR_P) "$(DESTDIR)$(docdir)" + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ + done + +uninstall-dist_docDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(docdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(docdir)" && rm -f $$files +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(includedir)" && rm -f $$files + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + echo "$$grn$$dashes"; \ + else \ + echo "$$red$$dashes"; \ + fi; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes$$std"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-lzma: distdir + tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma + $(am__remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lzma*) \ + lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @$(am__cd) '$(distuninstallcheck_dir)' \ + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) $(HEADERS) \ + config.h +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_docDATA install-includeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_docDATA uninstall-includeHEADERS \ + uninstall-libLTLIBRARIES + +.MAKE: all check-am install-am install-strip + +.PHONY: CTAGS GTAGS all all-am am--refresh check check-TESTS check-am \ + clean clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstPROGRAMS ctags dist dist-all dist-bzip2 dist-gzip \ + dist-lzma dist-shar dist-tarZ dist-xz dist-zip distcheck \ + distclean distclean-compile distclean-generic distclean-hdr \ + distclean-libtool distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_docDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am \ + install-includeHEADERS install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-dist_docDATA \ + uninstall-includeHEADERS uninstall-libLTLIBRARIES + + +libtool: $(LIBTOOL_DEPS) + $(SHELL) ./config.status --recheck + +# 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/snappy/snappy-1.0.5/Makefile.orig b/snappy/snappy-1.0.5/Makefile.orig new file mode 100644 index 00000000..58498520 --- /dev/null +++ b/snappy/snappy-1.0.5/Makefile.orig @@ -0,0 +1,927 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# Makefile. Generated from Makefile.in by configure. + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + + + + + + +pkgdatadir = $(datadir)/snappy +pkgincludedir = $(includedir)/snappy +pkglibdir = $(libdir)/snappy +pkglibexecdir = $(libexecdir)/snappy +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +TESTS = snappy_unittest$(EXEEXT) +noinst_PROGRAMS = $(am__EXEEXT_1) +subdir = . +DIST_COMMON = README $(am__configure_deps) $(dist_doc_DATA) \ + $(include_HEADERS) $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(srcdir)/snappy-stubs-public.h.in $(top_srcdir)/configure \ + AUTHORS COPYING ChangeLog INSTALL NEWS config.guess config.sub \ + depcomp install-sh ltmain.sh missing +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gtest.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = snappy-stubs-public.h +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" \ + "$(DESTDIR)$(includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +libsnappy_la_LIBADD = +am_libsnappy_la_OBJECTS = snappy.lo snappy-sinksource.lo \ + snappy-stubs-internal.lo snappy-c.lo +libsnappy_la_OBJECTS = $(am_libsnappy_la_OBJECTS) +libsnappy_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(libsnappy_la_LDFLAGS) $(LDFLAGS) -o $@ +am__EXEEXT_1 = snappy_unittest$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +am_snappy_unittest_OBJECTS = \ + snappy_unittest-snappy_unittest.$(OBJEXT) \ + snappy_unittest-snappy-test.$(OBJEXT) +snappy_unittest_OBJECTS = $(am_snappy_unittest_OBJECTS) +am__DEPENDENCIES_1 = +snappy_unittest_DEPENDENCIES = libsnappy.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +snappy_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(snappy_unittest_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libsnappy_la_SOURCES) $(snappy_unittest_SOURCES) +DIST_SOURCES = $(libsnappy_la_SOURCES) $(snappy_unittest_SOURCES) +DATA = $(dist_doc_DATA) +HEADERS = $(include_HEADERS) $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +am__tty_colors = \ +red=; grn=; lgn=; blu=; std= +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + { test ! -d "$(distdir)" \ + || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr "$(distdir)"; }; } +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +distcleancheck_listfiles = find . -type f -print +ACLOCAL = ${SHELL} /home/dhruba/local/snappy-1.0.5/missing --run aclocal-1.9 +AMTAR = ${SHELL} /home/dhruba/local/snappy-1.0.5/missing --run tar +AR = @AR@ +AUTOCONF = ${SHELL} /home/dhruba/local/snappy-1.0.5/missing --run autoconf +AUTOHEADER = ${SHELL} /home/dhruba/local/snappy-1.0.5/missing --run autoheader +AUTOMAKE = ${SHELL} /home/dhruba/local/snappy-1.0.5/missing --run automake-1.9 +AWK = gawk +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = +CXX = g++ +CXXCPP = g++ -E +CXXDEPMODE = depmode=gcc3 +CXXFLAGS = -g -O2 +CYGPATH_W = echo +DEFS = -DHAVE_CONFIG_H +DEPDIR = .deps +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = +ECHO_N = -n +ECHO_T = +EGREP = grep -E +EXEEXT = +FGREP = @FGREP@ +GREP = @GREP@ +GTEST_CONFIG = +GTEST_CPPFLAGS = +GTEST_CXXFLAGS = +GTEST_LDFLAGS = +GTEST_LIBS = +GTEST_VERSION = +HAVE_GTEST = no +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} +INSTALL_SCRIPT = ${INSTALL} +INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s +LD = @LD@ +LDFLAGS = +LIBOBJS = +LIBS = +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = +MAKEINFO = ${SHELL} /home/dhruba/local/snappy-1.0.5/missing --run makeinfo +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = o +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = snappy +PACKAGE_BUGREPORT = +PACKAGE_NAME = snappy +PACKAGE_STRING = snappy 1.0.5 +PACKAGE_TARNAME = snappy +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = 1.0.5 +PATH_SEPARATOR = : +PKG_CONFIG = /usr/bin/pkg-config +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = +SHELL = /bin/sh +SNAPPY_LTVERSION = 2:3:1 +SNAPPY_MAJOR = 1 +SNAPPY_MINOR = 0 +SNAPPY_PATCHLEVEL = 5 +STRIP = +UNITTEST_LIBS = -llzo2 -lz +VERSION = 1.0.5 +abs_builddir = /home/dhruba/local/snappy-1.0.5 +abs_srcdir = /home/dhruba/local/snappy-1.0.5 +abs_top_builddir = /home/dhruba/local/snappy-1.0.5 +abs_top_srcdir = /home/dhruba/local/snappy-1.0.5 +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = g++ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_cv_have_stddef_h = 1 +ac_cv_have_stdint_h = 1 +am__include = include +am__leading_dot = . +am__quote = +am__tar = ${AMTAR} chof - "$$tardir" +am__untar = ${AMTAR} xf - +bindir = ${exec_prefix}/bin +build = @build@ +build_alias = +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = . +datadir = ${prefix}/share +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = ${prefix} +gflags_CFLAGS = +gflags_LIBS = +host = @host@ +host_alias = +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = ${prefix}/include +infodir = ${prefix}/info +install_sh = /home/dhruba/local/snappy-1.0.5/install-sh +libdir = ${exec_prefix}/lib +libexecdir = ${exec_prefix}/libexec +localedir = @localedir@ +localstatedir = ${prefix}/var +lt_ECHO = @lt_ECHO@ +mandir = ${prefix}/man +mkdir_p = mkdir -p -- +oldincludedir = /usr/include +pdfdir = @pdfdir@ +prefix = /usr/local +program_transform_name = s,x,x, +psdir = @psdir@ +sbindir = ${exec_prefix}/sbin +sharedstatedir = ${prefix}/com +srcdir = . +sysconfdir = ${prefix}/etc +target_alias = +top_build_prefix = @top_build_prefix@ +top_builddir = +top_srcdir = . +ACLOCAL_AMFLAGS = -I m4 + +# Library. +lib_LTLIBRARIES = libsnappy.la +libsnappy_la_SOURCES = snappy.cc snappy-sinksource.cc snappy-stubs-internal.cc snappy-c.cc +libsnappy_la_LDFLAGS = -version-info $(SNAPPY_LTVERSION) +include_HEADERS = snappy.h snappy-sinksource.h snappy-stubs-public.h snappy-c.h +noinst_HEADERS = snappy-internal.h snappy-stubs-internal.h snappy-test.h + +# Unit tests and benchmarks. +snappy_unittest_CPPFLAGS = $(gflags_CFLAGS) $(GTEST_CPPFLAGS) +snappy_unittest_SOURCES = snappy_unittest.cc snappy-test.cc +snappy_unittest_LDFLAGS = $(GTEST_LDFLAGS) +snappy_unittest_LDADD = libsnappy.la $(UNITTEST_LIBS) $(gflags_LIBS) $(GTEST_LIBS) +EXTRA_DIST = autogen.sh testdata/alice29.txt testdata/asyoulik.txt testdata/baddata1.snappy testdata/baddata2.snappy testdata/baddata3.snappy testdata/cp.html testdata/fields.c testdata/geo.protodata testdata/grammar.lsp testdata/house.jpg testdata/html testdata/html_x_4 testdata/kennedy.xls testdata/kppkn.gtb testdata/lcet10.txt testdata/mapreduce-osdi-1.pdf testdata/plrabn12.txt testdata/ptt5 testdata/sum testdata/urls.10K testdata/xargs.1 +dist_doc_DATA = ChangeLog COPYING INSTALL NEWS README format_description.txt framing_format.txt +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +am--refresh: + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +snappy-stubs-public.h: $(top_builddir)/config.status $(srcdir)/snappy-stubs-public.h.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libsnappy.la: $(libsnappy_la_OBJECTS) $(libsnappy_la_DEPENDENCIES) + $(libsnappy_la_LINK) -rpath $(libdir) $(libsnappy_la_OBJECTS) $(libsnappy_la_LIBADD) $(LIBS) + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +snappy_unittest$(EXEEXT): $(snappy_unittest_OBJECTS) $(snappy_unittest_DEPENDENCIES) + @rm -f snappy_unittest$(EXEEXT) + $(snappy_unittest_LINK) $(snappy_unittest_OBJECTS) $(snappy_unittest_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +include ./$(DEPDIR)/snappy-c.Plo +include ./$(DEPDIR)/snappy-sinksource.Plo +include ./$(DEPDIR)/snappy-stubs-internal.Plo +include ./$(DEPDIR)/snappy.Plo +include ./$(DEPDIR)/snappy_unittest-snappy-test.Po +include ./$(DEPDIR)/snappy_unittest-snappy_unittest.Po + +.cc.o: + $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< + $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXXCOMPILE) -c -o $@ $< + +.cc.obj: + $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` + $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: + $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< + $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +# source='$<' object='$@' libtool=yes \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(LTCXXCOMPILE) -c -o $@ $< + +snappy_unittest-snappy_unittest.o: snappy_unittest.cc + $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT snappy_unittest-snappy_unittest.o -MD -MP -MF $(DEPDIR)/snappy_unittest-snappy_unittest.Tpo -c -o snappy_unittest-snappy_unittest.o `test -f 'snappy_unittest.cc' || echo '$(srcdir)/'`snappy_unittest.cc + $(am__mv) $(DEPDIR)/snappy_unittest-snappy_unittest.Tpo $(DEPDIR)/snappy_unittest-snappy_unittest.Po +# source='snappy_unittest.cc' object='snappy_unittest-snappy_unittest.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o snappy_unittest-snappy_unittest.o `test -f 'snappy_unittest.cc' || echo '$(srcdir)/'`snappy_unittest.cc + +snappy_unittest-snappy_unittest.obj: snappy_unittest.cc + $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT snappy_unittest-snappy_unittest.obj -MD -MP -MF $(DEPDIR)/snappy_unittest-snappy_unittest.Tpo -c -o snappy_unittest-snappy_unittest.obj `if test -f 'snappy_unittest.cc'; then $(CYGPATH_W) 'snappy_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/snappy_unittest.cc'; fi` + $(am__mv) $(DEPDIR)/snappy_unittest-snappy_unittest.Tpo $(DEPDIR)/snappy_unittest-snappy_unittest.Po +# source='snappy_unittest.cc' object='snappy_unittest-snappy_unittest.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o snappy_unittest-snappy_unittest.obj `if test -f 'snappy_unittest.cc'; then $(CYGPATH_W) 'snappy_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/snappy_unittest.cc'; fi` + +snappy_unittest-snappy-test.o: snappy-test.cc + $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT snappy_unittest-snappy-test.o -MD -MP -MF $(DEPDIR)/snappy_unittest-snappy-test.Tpo -c -o snappy_unittest-snappy-test.o `test -f 'snappy-test.cc' || echo '$(srcdir)/'`snappy-test.cc + $(am__mv) $(DEPDIR)/snappy_unittest-snappy-test.Tpo $(DEPDIR)/snappy_unittest-snappy-test.Po +# source='snappy-test.cc' object='snappy_unittest-snappy-test.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o snappy_unittest-snappy-test.o `test -f 'snappy-test.cc' || echo '$(srcdir)/'`snappy-test.cc + +snappy_unittest-snappy-test.obj: snappy-test.cc + $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT snappy_unittest-snappy-test.obj -MD -MP -MF $(DEPDIR)/snappy_unittest-snappy-test.Tpo -c -o snappy_unittest-snappy-test.obj `if test -f 'snappy-test.cc'; then $(CYGPATH_W) 'snappy-test.cc'; else $(CYGPATH_W) '$(srcdir)/snappy-test.cc'; fi` + $(am__mv) $(DEPDIR)/snappy_unittest-snappy-test.Tpo $(DEPDIR)/snappy_unittest-snappy-test.Po +# source='snappy-test.cc' object='snappy_unittest-snappy-test.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(snappy_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o snappy_unittest-snappy-test.obj `if test -f 'snappy-test.cc'; then $(CYGPATH_W) 'snappy-test.cc'; else $(CYGPATH_W) '$(srcdir)/snappy-test.cc'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt +install-dist_docDATA: $(dist_doc_DATA) + @$(NORMAL_INSTALL) + test -z "$(docdir)" || $(MKDIR_P) "$(DESTDIR)$(docdir)" + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ + done + +uninstall-dist_docDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(docdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(docdir)" && rm -f $$files +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(includedir)" && rm -f $$files + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + echo "$$grn$$dashes"; \ + else \ + echo "$$red$$dashes"; \ + fi; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes$$std"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-lzma: distdir + tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma + $(am__remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lzma*) \ + lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @$(am__cd) '$(distuninstallcheck_dir)' \ + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) $(HEADERS) \ + config.h +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_docDATA install-includeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_docDATA uninstall-includeHEADERS \ + uninstall-libLTLIBRARIES + +.MAKE: all check-am install-am install-strip + +.PHONY: CTAGS GTAGS all all-am am--refresh check check-TESTS check-am \ + clean clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstPROGRAMS ctags dist dist-all dist-bzip2 dist-gzip \ + dist-lzma dist-shar dist-tarZ dist-xz dist-zip distcheck \ + distclean distclean-compile distclean-generic distclean-hdr \ + distclean-libtool distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_docDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am \ + install-includeHEADERS install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-dist_docDATA \ + uninstall-includeHEADERS uninstall-libLTLIBRARIES + + +libtool: $(LIBTOOL_DEPS) + $(SHELL) ./config.status --recheck + +# 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/snappy/snappy-1.0.5/NEWS b/snappy/snappy-1.0.5/NEWS new file mode 100644 index 00000000..60bbd17d --- /dev/null +++ b/snappy/snappy-1.0.5/NEWS @@ -0,0 +1,89 @@ +Snappy v1.0.5, February 24th 2012: + + * More speed improvements. Exactly how big will depend on + the architecture: + + - 3–10% faster decompression for the base case (x86-64). + + - ARMv7 and higher can now use unaligned accesses, + and will see about 30% faster decompression and + 20–40% faster compression. + + - 32-bit platforms (ARM and 32-bit x86) will see 2–5% + faster compression. + + These are all cumulative (e.g., ARM gets all three speedups). + + * Fixed an issue where the unit test would crash on system + with less than 256 MB address space available, + e.g. some embedded platforms. + + * Added a framing format description, for use over e.g. HTTP, + or for a command-line compressor. We do not have any + implementations of this at the current point, but there seems + to be enough of a general interest in the topic. + Also make the format description slightly clearer. + + * Remove some compile-time warnings in -Wall + (mostly signed/unsigned comparisons), for easier embedding + into projects that use -Wall -Werror. + + +Snappy v1.0.4, September 15th 2011: + + * Speeded up the decompressor somewhat; typically about 2–8% + for Core i7, in 64-bit mode (comparable for Opteron). + Somewhat more for some tests, almost no gain for others. + + * Make Snappy compile on certain platforms it didn't before + (Solaris with SunPro C++, HP-UX, AIX). + + * Correct some minor errors in the format description. + + +Snappy v1.0.3, June 2nd 2011: + + * Speeded up the decompressor somewhat; about 3-6% for Core 2, + 6-13% for Core i7, and 5-12% for Opteron (all in 64-bit mode). + + * Added compressed format documentation. This text is new, + but an earlier version from Zeev Tarantov was used as reference. + + * Only link snappy_unittest against -lz and other autodetected + libraries, not libsnappy.so (which doesn't need any such dependency). + + * Fixed some display issues in the microbenchmarks, one of which would + frequently make the test crash on GNU/Hurd. + + +Snappy v1.0.2, April 29th 2011: + + * Relicense to a BSD-type license. + + * Added C bindings, contributed by Martin Gieseking. + + * More Win32 fixes, in particular for MSVC. + + * Replace geo.protodata with a newer version. + + * Fix timing inaccuracies in the unit test when comparing Snappy + to other algorithms. + + +Snappy v1.0.1, March 25th 2011: + +This is a maintenance release, mostly containing minor fixes. +There is no new functionality. The most important fixes include: + + * The COPYING file and all licensing headers now correctly state that + Snappy is licensed under the Apache 2.0 license. + + * snappy_unittest should now compile natively under Windows, + as well as on embedded systems with no mmap(). + + * Various autotools nits have been fixed. + + +Snappy v1.0, March 17th 2011: + + * Initial version. diff --git a/snappy/snappy-1.0.5/README b/snappy/snappy-1.0.5/README new file mode 100644 index 00000000..3bc8888f --- /dev/null +++ b/snappy/snappy-1.0.5/README @@ -0,0 +1,135 @@ +Snappy, a fast compressor/decompressor. + + +Introduction +============ + +Snappy is a compression/decompression library. It does not aim for maximum +compression, or compatibility with any other compression library; instead, +it aims for very high speeds and reasonable compression. For instance, +compared to the fastest mode of zlib, Snappy is an order of magnitude faster +for most inputs, but the resulting compressed files are anywhere from 20% to +100% bigger. (For more information, see "Performance", below.) + +Snappy has the following properties: + + * Fast: Compression speeds at 250 MB/sec and beyond, with no assembler code. + See "Performance" below. + * Stable: Over the last few years, Snappy has compressed and decompressed + petabytes of data in Google's production environment. The Snappy bitstream + format is stable and will not change between versions. + * Robust: The Snappy decompressor is designed not to crash in the face of + corrupted or malicious input. + * Free and open source software: Snappy is licensed under a BSD-type license. + For more information, see the included COPYING file. + +Snappy has previously been called "Zippy" in some Google presentations +and the like. + + +Performance +=========== + +Snappy is intended to be fast. On a single core of a Core i7 processor +in 64-bit mode, it compresses at about 250 MB/sec or more and decompresses at +about 500 MB/sec or more. (These numbers are for the slowest inputs in our +benchmark suite; others are much faster.) In our tests, Snappy usually +is faster than algorithms in the same class (e.g. LZO, LZF, FastLZ, QuickLZ, +etc.) while achieving comparable compression ratios. + +Typical compression ratios (based on the benchmark suite) are about 1.5-1.7x +for plain text, about 2-4x for HTML, and of course 1.0x for JPEGs, PNGs and +other already-compressed data. Similar numbers for zlib in its fastest mode +are 2.6-2.8x, 3-7x and 1.0x, respectively. More sophisticated algorithms are +capable of achieving yet higher compression rates, although usually at the +expense of speed. Of course, compression ratio will vary significantly with +the input. + +Although Snappy should be fairly portable, it is primarily optimized +for 64-bit x86-compatible processors, and may run slower in other environments. +In particular: + + - Snappy uses 64-bit operations in several places to process more data at + once than would otherwise be possible. + - Snappy assumes unaligned 32- and 64-bit loads and stores are cheap. + On some platforms, these must be emulated with single-byte loads + and stores, which is much slower. + - Snappy assumes little-endian throughout, and needs to byte-swap data in + several places if running on a big-endian platform. + +Experience has shown that even heavily tuned code can be improved. +Performance optimizations, whether for 64-bit x86 or other platforms, +are of course most welcome; see "Contact", below. + + +Usage +===== + +Note that Snappy, both the implementation and the main interface, +is written in C++. However, several third-party bindings to other languages +are available; see the Google Code page at http://code.google.com/p/snappy/ +for more information. Also, if you want to use Snappy from C code, you can +use the included C bindings in snappy-c.h. + +To use Snappy from your own C++ program, include the file "snappy.h" from +your calling file, and link against the compiled library. + +There are many ways to call Snappy, but the simplest possible is + + snappy::Compress(input.data(), input.size(), &output); + +and similarly + + snappy::Uncompress(input.data(), input.size(), &output); + +where "input" and "output" are both instances of std::string. + +There are other interfaces that are more flexible in various ways, including +support for custom (non-array) input sources. See the header file for more +information. + + +Tests and benchmarks +==================== + +When you compile Snappy, snappy_unittest is compiled in addition to the +library itself. You do not need it to use the compressor from your own library, +but it contains several useful components for Snappy development. + +First of all, it contains unit tests, verifying correctness on your machine in +various scenarios. If you want to change or optimize Snappy, please run the +tests to verify you have not broken anything. Note that if you have the +Google Test library installed, unit test behavior (especially failures) will be +significantly more user-friendly. You can find Google Test at + + http://code.google.com/p/googletest/ + +You probably also want the gflags library for handling of command-line flags; +you can find it at + + http://code.google.com/p/google-gflags/ + +In addition to the unit tests, snappy contains microbenchmarks used to +tune compression and decompression performance. These are automatically run +before the unit tests, but you can disable them using the flag +--run_microbenchmarks=false if you have gflags installed (otherwise you will +need to edit the source). + +Finally, snappy can benchmark Snappy against a few other compression libraries +(zlib, LZO, LZF, FastLZ and QuickLZ), if they were detected at configure time. +To benchmark using a given file, give the compression algorithm you want to test +Snappy against (e.g. --zlib) and then a list of one or more file names on the +command line. The testdata/ directory contains the files used by the +microbenchmark, which should provide a reasonably balanced starting point for +benchmarking. (Note that baddata[1-3].snappy are not intended as benchmarks; they +are used to verify correctness in the presence of corrupted data in the unit +test.) + + +Contact +======= + +Snappy is distributed through Google Code. For the latest version, a bug tracker, +and other information, see + + http://code.google.com/p/snappy/ diff --git a/snappy/snappy-1.0.5/aclocal.m4 b/snappy/snappy-1.0.5/aclocal.m4 new file mode 100644 index 00000000..28283870 --- /dev/null +++ b/snappy/snappy-1.0.5/aclocal.m4 @@ -0,0 +1,1009 @@ +# generated automatically by aclocal 1.9.6 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# +# Copyright © 2004 Scott James Remnant . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# PKG_PROG_PKG_CONFIG([MIN-VERSION]) +# ---------------------------------- +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi + +fi[]dnl +])# PKG_PROG_PKG_CONFIG + +# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# +# Check to see whether a particular set of modules exists. Similar +# to PKG_CHECK_MODULES(), but does not set variables or print errors. +# +# +# Similar to PKG_CHECK_MODULES, make sure that the first instance of +# this or PKG_CHECK_MODULES is called, or make sure to call +# PKG_CHECK_EXISTS manually +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_ifval([$2], [$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + + +# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +# --------------------------------------------- +m4_define([_PKG_CONFIG], +[if test -n "$PKG_CONFIG"; then + if test -n "$$1"; then + pkg_cv_[]$1="$$1" + else + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], + [pkg_failed=yes]) + fi +else + pkg_failed=untried +fi[]dnl +])# _PKG_CONFIG + +# _PKG_SHORT_ERRORS_SUPPORTED +# ----------------------------- +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])# _PKG_SHORT_ERRORS_SUPPORTED + + +# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# +# +# Note that if there is a possibility the first call to +# PKG_CHECK_MODULES might not happen, you should be sure to include an +# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +# +# +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + ifelse([$4], , [AC_MSG_ERROR(dnl +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT +])], + [AC_MSG_RESULT([no]) + $4]) +elif test $pkg_failed = untried; then + ifelse([$4], , [AC_MSG_FAILURE(dnl +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])], + [$4]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + ifelse([$3], , :, [$3]) +fi[]dnl +])# PKG_CHECK_MODULES + +# Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"]) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION so it can be traced. +# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], + [AM_AUTOMAKE_VERSION([1.9.6])]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 7 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ(2.52)dnl + ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE]) +AC_SUBST([$1_FALSE]) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 8 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH]) +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +#serial 3 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 12 + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.58])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +# test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AM_PROG_INSTALL_SH +AM_PROG_INSTALL_STRIP +AC_REQUIRE([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +]) +]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $1 | $1:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +install_sh=${install_sh-"$am_aux_dir/install-sh"} +AC_SUBST(install_sh)]) + +# Copyright (C) 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 3 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo done +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 4 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_MKDIR_P +# --------------- +# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise. +# +# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories +# created by `make install' are always world readable, even if the +# installer happens to have an overly restrictive umask (e.g. 077). +# This was a mistake. There are at least two reasons why we must not +# use `-m 0755': +# - it causes special bits like SGID to be ignored, +# - it may be too restrictive (some setups expect 775 directories). +# +# Do not use -m 0755 and let people choose whatever they expect by +# setting umask. +# +# We cannot accept any implementation of `mkdir' that recognizes `-p'. +# Some implementations (such as Solaris 8's) are not thread-safe: if a +# parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c' +# concurrently, both version can detect that a/ is missing, but only +# one can create it and the other will error out. Consequently we +# restrict ourselves to GNU make (using the --version option ensures +# this.) +AC_DEFUN([AM_PROG_MKDIR_P], +[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + # We used to keeping the `.' as first argument, in order to + # allow $(mkdir_p) to be used without argument. As in + # $(mkdir_p) $(somedir) + # where $(somedir) is conditionally defined. However this is wrong + # for two reasons: + # 1. if the package is installed by a user who cannot write `.' + # make install will fail, + # 2. the above comment should most certainly read + # $(mkdir_p) $(DESTDIR)$(somedir) + # so it does not work when $(somedir) is undefined and + # $(DESTDIR) is not. + # To support the latter case, we have to write + # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), + # so the `.' trick is pointless. + mkdir_p='mkdir -p --' +else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + for d in ./-p ./--version; + do + test -d $d && rmdir $d + done + # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. + if test -f "$ac_aux_dir/mkinstalldirs"; then + mkdir_p='$(mkinstalldirs)' + else + mkdir_p='$(install_sh) -d' + fi +fi +AC_SUBST([mkdir_p])]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 3 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# ------------------------------ +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ---------------------------------- +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 4 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of `v7', `ustar', or `pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. +AM_MISSING_PROG([AMTAR], [tar]) +m4_if([$1], [v7], + [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of `-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([m4/gtest.m4]) diff --git a/snappy/snappy-1.0.5/autogen.sh b/snappy/snappy-1.0.5/autogen.sh new file mode 100755 index 00000000..9d0ebe93 --- /dev/null +++ b/snappy/snappy-1.0.5/autogen.sh @@ -0,0 +1,7 @@ +#! /bin/sh -e +rm -rf autom4te.cache +aclocal -I m4 +autoheader +libtoolize --copy +automake --add-missing --copy +autoconf diff --git a/snappy/snappy-1.0.5/autom4te.cache/output.0 b/snappy/snappy-1.0.5/autom4te.cache/output.0 new file mode 100644 index 00000000..4b2d725f --- /dev/null +++ b/snappy/snappy-1.0.5/autom4te.cache/output.0 @@ -0,0 +1,5872 @@ +@%:@! /bin/sh +@%:@ Guess values for system-dependent variables and create Makefiles. +@%:@ Generated by GNU Autoconf 2.59 for snappy 1.0.5. +@%:@ +@%:@ Copyright (C) 2003 Free Software Foundation, Inc. +@%:@ This configure script is free software; the Free Software Foundation +@%:@ gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# 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'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME='snappy' +PACKAGE_TARNAME='snappy' +PACKAGE_VERSION='1.0.5' +PACKAGE_STRING='snappy 1.0.5' +PACKAGE_BUGREPORT='' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif +#if HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar LIBTOOL_DEPS CXX CXXFLAGS LDFLAGS CPPFLAGS ac_ct_CXX EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CXXCPP EGREP GTEST_CONFIG GTEST_CPPFLAGS GTEST_CXXFLAGS GTEST_LDFLAGS GTEST_LIBS GTEST_VERSION HAVE_GTEST HAVE_GTEST_TRUE HAVE_GTEST_FALSE PKG_CONFIG ac_pt_PKG_CONFIG gflags_CFLAGS gflags_LIBS UNITTEST_LIBS ac_cv_have_stdint_h ac_cv_have_stddef_h SNAPPY_MAJOR SNAPPY_MINOR SNAPPY_PATCHLEVEL SNAPPY_LTVERSION LIB@&t@OBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -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 && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -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 && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -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 && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + 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 && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CXX_set=${CXX+set} +ac_env_CXX_value=$CXX +ac_cv_env_CXX_set=${CXX+set} +ac_cv_env_CXX_value=$CXX +ac_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_env_CXXFLAGS_value=$CXXFLAGS +ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_cv_env_CXXFLAGS_value=$CXXFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CXXCPP_set=${CXXCPP+set} +ac_env_CXXCPP_value=$CXXCPP +ac_cv_env_CXXCPP_set=${CXXCPP+set} +ac_cv_env_CXXCPP_value=$CXXCPP +ac_env_GTEST_CONFIG_set=${GTEST_CONFIG+set} +ac_env_GTEST_CONFIG_value=$GTEST_CONFIG +ac_cv_env_GTEST_CONFIG_set=${GTEST_CONFIG+set} +ac_cv_env_GTEST_CONFIG_value=$GTEST_CONFIG +ac_env_GTEST_CPPFLAGS_set=${GTEST_CPPFLAGS+set} +ac_env_GTEST_CPPFLAGS_value=$GTEST_CPPFLAGS +ac_cv_env_GTEST_CPPFLAGS_set=${GTEST_CPPFLAGS+set} +ac_cv_env_GTEST_CPPFLAGS_value=$GTEST_CPPFLAGS +ac_env_GTEST_CXXFLAGS_set=${GTEST_CXXFLAGS+set} +ac_env_GTEST_CXXFLAGS_value=$GTEST_CXXFLAGS +ac_cv_env_GTEST_CXXFLAGS_set=${GTEST_CXXFLAGS+set} +ac_cv_env_GTEST_CXXFLAGS_value=$GTEST_CXXFLAGS +ac_env_GTEST_LDFLAGS_set=${GTEST_LDFLAGS+set} +ac_env_GTEST_LDFLAGS_value=$GTEST_LDFLAGS +ac_cv_env_GTEST_LDFLAGS_set=${GTEST_LDFLAGS+set} +ac_cv_env_GTEST_LDFLAGS_value=$GTEST_LDFLAGS +ac_env_GTEST_LIBS_set=${GTEST_LIBS+set} +ac_env_GTEST_LIBS_value=$GTEST_LIBS +ac_cv_env_GTEST_LIBS_set=${GTEST_LIBS+set} +ac_cv_env_GTEST_LIBS_value=$GTEST_LIBS +ac_env_GTEST_VERSION_set=${GTEST_VERSION+set} +ac_env_GTEST_VERSION_value=$GTEST_VERSION +ac_cv_env_GTEST_VERSION_set=${GTEST_VERSION+set} +ac_cv_env_GTEST_VERSION_value=$GTEST_VERSION +ac_env_PKG_CONFIG_set=${PKG_CONFIG+set} +ac_env_PKG_CONFIG_value=$PKG_CONFIG +ac_cv_env_PKG_CONFIG_set=${PKG_CONFIG+set} +ac_cv_env_PKG_CONFIG_value=$PKG_CONFIG +ac_env_gflags_CFLAGS_set=${gflags_CFLAGS+set} +ac_env_gflags_CFLAGS_value=$gflags_CFLAGS +ac_cv_env_gflags_CFLAGS_set=${gflags_CFLAGS+set} +ac_cv_env_gflags_CFLAGS_value=$gflags_CFLAGS +ac_env_gflags_LIBS_set=${gflags_LIBS+set} +ac_env_gflags_LIBS_value=$gflags_LIBS +ac_cv_env_gflags_LIBS_set=${gflags_LIBS+set} +ac_cv_env_gflags_LIBS_value=$gflags_LIBS + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures snappy 1.0.5 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of snappy 1.0.5:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + --enable-gtest Enable tests using the Google C++ Testing Framework. + (Default is enabled.) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-gflags use Google Flags package to enhance the unit test + @<:@default=check@:>@ + +Some influential environment variables: + CXX C++ compiler command + CXXFLAGS C++ compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + CXXCPP C++ preprocessor + GTEST_CONFIG + The exact path of Google Test's 'gtest-config' script. + GTEST_CPPFLAGS + C-like preprocessor flags for Google Test. + GTEST_CXXFLAGS + C++ compile flags for Google Test. + GTEST_LDFLAGS + Linker path and option flags for Google Test. + GTEST_LIBS Library linking flags for Google Test. + GTEST_VERSION + The version of Google Test available. + PKG_CONFIG path to pkg-config utility + gflags_CFLAGS + C compiler flags for gflags, overriding pkg-config + gflags_LIBS linker flags for gflags, overriding pkg-config + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF +snappy configure 1.0.5 +generated by GNU Autoconf 2.59 + +Copyright (C) 2003 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by snappy $as_me 1.0.5, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +@%:@@%:@ --------- @%:@@%:@ +@%:@@%:@ Platform. @%:@@%:@ +@%:@@%:@ --------- @%:@@%:@ + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +@%:@@%:@ ----------- @%:@@%:@ +@%:@@%:@ Core tests. @%:@@%:@ +@%:@@%:@ ----------- @%:@@%:@ + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +@%:@@%:@ ---------------- @%:@@%:@ +@%:@@%:@ Cache variables. @%:@@%:@ +@%:@@%:@ ---------------- @%:@@%:@ +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +@%:@@%:@ ----------------- @%:@@%:@ +@%:@@%:@ Output variables. @%:@@%:@ +@%:@@%:@ ----------------- @%:@@%:@ +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +@%:@@%:@ ------------- @%:@@%:@ +@%:@@%:@ Output files. @%:@@%:@ +@%:@@%:@ ------------- @%:@@%:@ +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +@%:@@%:@ ----------- @%:@@%:@ +@%:@@%:@ confdefs.h. @%:@@%:@ +@%:@@%:@ ----------- @%:@@%:@ +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + + + + + + + + +case m4 in + [\\/]* | ?:[\\/]* ) ac_macro_dir=m4 ;; + *) ac_macro_dir=$srcdir/m4 ;; +esac +if test -d "$ac_macro_dir"; then : +else + { { echo "$as_me:$LINENO: error: cannot find macro directory \`m4'" >&5 +echo "$as_me: error: cannot find macro directory \`m4'" >&2;} + { (exit 1); exit 1; }; } +fi + + +# These are flags passed to automake (though they look like gcc flags!) +am__api_version="1.9" +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$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. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo "$as_me:$LINENO: checking whether build environment is sane" >&5 +echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6 +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&5 +echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&2;} + { (exit 1); exit 1; }; } + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! +Check your system clock" >&5 +echo "$as_me: error: newly created file is older than distributed files! +Check your system clock" >&2;} + { (exit 1); exit 1; }; } +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +test "$program_prefix" != NONE && + program_transform_name="s,^,$program_prefix,;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$,$program_suffix,;$program_transform_name" +# Double any \ or $. echo might interpret backslashes. +# By default was `s,x,x', remove it if useless. +cat <<\_ACEOF >conftest.sed +s/[\\$]/&&/g;s/;s,x,x,$// +_ACEOF +program_transform_name=`echo $program_transform_name | sed -f conftest.sed` +rm conftest.sed + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 +echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + # We used to keeping the `.' as first argument, in order to + # allow $(mkdir_p) to be used without argument. As in + # $(mkdir_p) $(somedir) + # where $(somedir) is conditionally defined. However this is wrong + # for two reasons: + # 1. if the package is installed by a user who cannot write `.' + # make install will fail, + # 2. the above comment should most certainly read + # $(mkdir_p) $(DESTDIR)$(somedir) + # so it does not work when $(somedir) is undefined and + # $(DESTDIR) is not. + # To support the latter case, we have to write + # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), + # so the `.' trick is pointless. + mkdir_p='mkdir -p --' +else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + for d in ./-p ./--version; + do + test -d $d && rmdir $d + done + # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. + if test -f "$ac_aux_dir/mkinstalldirs"; then + mkdir_p='$(mkinstalldirs)' + else + mkdir_p='$(install_sh) -d' + fi +fi + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_AWK+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$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 + fi +done +done + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + echo "$as_me:$LINENO: result: $AWK" >&5 +echo "${ECHO_T}$AWK" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$AWK" && break +done + +echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="$(MAKE)"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 +echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} + { (exit 1); exit 1; }; } +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='snappy' + VERSION='1.0.5' + + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +@%:@define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +install_sh=${install_sh-"$am_aux_dir/install-sh"} + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$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 + fi +done +done + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$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 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + STRIP=$ac_ct_STRIP +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. + +AMTAR=${AMTAR-"${am_missing_run}tar"} + +am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' + + + + + + +LT_INIT + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC + 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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$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 + fi +done +done + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$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 + fi +done +done + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CXX" && break +done +test -n "$ac_ct_CXX" || ac_ct_CXX="g++" + + CXX=$ac_ct_CXX +fi + + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C++ compiler default output file name" >&5 +echo $ECHO_N "checking for C++ compiler default output file name... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C++ compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C++ compiler works" >&5 +echo $ECHO_N "checking whether the C++ compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C++ compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C++ compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +CXXFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cxx_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +@%:@include +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +DEPDIR="${am__leading_dot}deps" + + ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo done +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 +echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6 +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi + + +echo "$as_me:$LINENO: result: $_am_result" >&5 +echo "${ECHO_T}$_am_result" >&6 +rm -f confinc confmf + +# Check whether --enable-dependency-tracking or --disable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then + enableval="$enable_dependency_tracking" + +fi; +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi + + +if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + + +depcc="$CXX" am_compiler_list= + +echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 +if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 +echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6 +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + + +if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 +echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6 +if test "${ac_cv_c_bigendian+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # See if sys/param.h defines the BYTE_ORDER macro. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + # It does; now see whether it defined to BIG_ENDIAN or not. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_c_bigendian=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +# It does not; compile a test program. +if test "$cross_compiling" = yes; then + # try to guess the endianness by grepping values into an object file + ac_cv_c_bigendian=unknown + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; +short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; +void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } +short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; +short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; +void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } +int +main () +{ + _ascii (); _ebcdic (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then + ac_cv_c_bigendian=yes +fi +if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +int +main () +{ + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long l; + char c[sizeof (long)]; + } u; + u.l = 1; + exit (u.c[sizeof (long) - 1] == 1); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_bigendian=yes +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 +echo "${ECHO_T}$ac_cv_c_bigendian" >&6 +case $ac_cv_c_bigendian in + yes) + +cat >>confdefs.h <<\_ACEOF +@%:@define WORDS_BIGENDIAN 1 +_ACEOF + ;; + no) + ;; + *) + { { echo "$as_me:$LINENO: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&5 +echo "$as_me: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 +echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6 +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +@%:@ifdef __STDC__ +@%:@ include +@%:@else +@%:@ include +@%:@endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 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); } >/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 + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +@%:@include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 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); } >/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 + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +echo "$as_me:$LINENO: result: $CXXCPP" >&5 +echo "${ECHO_T}$CXXCPP" >&6 +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +@%:@ifdef __STDC__ +@%:@ include +@%:@else +@%:@ include +@%:@endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 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); } >/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 + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +@%:@include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 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); } >/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 + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +@%:@define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +@%:@include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +@%:@define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + + + + + +for ac_header in stdint.h stddef.h sys/mman.h sys/resource.h windows.h byteswap.h sys/byteswap.h sys/endian.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +@%:@include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +@%:@include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 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); } >/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 + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +@%:@@%:@ --------------------------------- @%:@@%:@ +@%:@@%:@ Report this to the snappy lists. @%:@@%:@ +@%:@@%:@ --------------------------------- @%:@@%:@ +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +@%:@define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +# Don't use AC_FUNC_MMAP, as it checks for mappings of already-mapped memory, +# which we don't need (and does not exist on Windows). +echo "$as_me:$LINENO: checking for mmap" >&5 +echo $ECHO_N "checking for mmap... $ECHO_C" >&6 +if test "${ac_cv_func_mmap+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define mmap to an innocuous variant, in case declares mmap. + For example, HP-UX 11i declares gettimeofday. */ +#define mmap innocuous_mmap + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char mmap (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef mmap + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char mmap (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_mmap) || defined (__stub___mmap) +choke me +#else +char (*f) () = mmap; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != mmap; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_mmap=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_mmap=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_mmap" >&5 +echo "${ECHO_T}$ac_cv_func_mmap" >&6 + + + +# Check whether --enable-gtest or --disable-gtest was given. +if test "${enable_gtest+set}" = set; then + enableval="$enable_gtest" + +else + enable_gtest= +fi; + + + + + + +HAVE_GTEST="no" +if test "x${enable_gtest}" != "xno"; then + echo "$as_me:$LINENO: checking for 'gtest-config'" >&5 +echo $ECHO_N "checking for 'gtest-config'... $ECHO_C" >&6 + if test "x${enable_gtest}" = "xyes"; then + if test -x "${enable_gtest}/scripts/gtest-config"; then + GTEST_CONFIG="${enable_gtest}/scripts/gtest-config" +else + GTEST_CONFIG="${enable_gtest}/bin/gtest-config" +fi + + if test -x "${GTEST_CONFIG}"; then + : +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + { { echo "$as_me:$LINENO: error: Unable to locate either a built or installed Google Test. +The specific location '${enable_gtest}' was provided for a built or installed +Google Test, but no 'gtest-config' script could be found at this location." >&5 +echo "$as_me: error: Unable to locate either a built or installed Google Test. +The specific location '${enable_gtest}' was provided for a built or installed +Google Test, but no 'gtest-config' script could be found at this location." >&2;} + { (exit 1); exit 1; }; } + +fi + +else + # Extract the first word of "gtest-config", so it can be a program name with args. +set dummy gtest-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_GTEST_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GTEST_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_GTEST_CONFIG="$GTEST_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GTEST_CONFIG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +GTEST_CONFIG=$ac_cv_path_GTEST_CONFIG + +if test -n "$GTEST_CONFIG"; then + echo "$as_me:$LINENO: result: $GTEST_CONFIG" >&5 +echo "${ECHO_T}$GTEST_CONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi + + if test -x "${GTEST_CONFIG}"; then + echo "$as_me:$LINENO: result: ${GTEST_CONFIG}" >&5 +echo "${ECHO_T}${GTEST_CONFIG}" >&6 + _gtest_min_version="--min-version=0" + echo "$as_me:$LINENO: checking for Google Test" >&5 +echo $ECHO_N "checking for Google Test... $ECHO_C" >&6 + if ${GTEST_CONFIG} ${_gtest_min_version}; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + HAVE_GTEST='yes' +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + if test "x${HAVE_GTEST}" = "xyes"; then + GTEST_CPPFLAGS=`${GTEST_CONFIG} --cppflags` + GTEST_CXXFLAGS=`${GTEST_CONFIG} --cxxflags` + GTEST_LDFLAGS=`${GTEST_CONFIG} --ldflags` + GTEST_LIBS=`${GTEST_CONFIG} --libs` + GTEST_VERSION=`${GTEST_CONFIG} --version` + +cat >>confdefs.h <<\_ACEOF +@%:@define HAVE_GTEST 1 +_ACEOF + +else + if test "x${enable_gtest}" = "xyes"; then + { { echo "$as_me:$LINENO: error: Google Test was enabled, but no viable version could be found." >&5 +echo "$as_me: error: Google Test was enabled, but no viable version could be found." >&2;} + { (exit 1); exit 1; }; } + +fi + +fi + +fi + + + + +if test "x$HAVE_GTEST" = "xyes"; then + HAVE_GTEST_TRUE= + HAVE_GTEST_FALSE='#' +else + HAVE_GTEST_TRUE='#' + HAVE_GTEST_FALSE= +fi + +if test "x$HAVE_GTEST" = "xyes"; then + true +else + true # Ignore; we can live without it. +fi + + + + +# Check whether --with-gflags or --without-gflags was given. +if test "${with_gflags+set}" = set; then + withval="$with_gflags" + +else + with_gflags=check +fi; + +if test "x$with_gflags" != "xno"; then + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_PKG_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG + +if test -n "$PKG_CONFIG"; then + echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5 +echo "${ECHO_T}$PKG_CONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG + +if test -n "$ac_pt_PKG_CONFIG"; then + echo "$as_me:$LINENO: result: $ac_pt_PKG_CONFIG" >&5 +echo "${ECHO_T}$ac_pt_PKG_CONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + PKG_CONFIG=$ac_pt_PKG_CONFIG +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + echo "$as_me:$LINENO: checking pkg-config is at least version $_pkg_min_version" >&5 +echo $ECHO_N "checking pkg-config is at least version $_pkg_min_version... $ECHO_C" >&6 + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + PKG_CONFIG="" + fi + +fi + +pkg_failed=no +echo "$as_me:$LINENO: checking for gflags" >&5 +echo $ECHO_N "checking for gflags... $ECHO_C" >&6 + +if test -n "$PKG_CONFIG"; then + if test -n "$gflags_CFLAGS"; then + pkg_cv_gflags_CFLAGS="$gflags_CFLAGS" + else + if test -n "$PKG_CONFIG" && \ + { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"libgflags\"") >&5 + ($PKG_CONFIG --exists --print-errors "libgflags") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + pkg_cv_gflags_CFLAGS=`$PKG_CONFIG --cflags "libgflags" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi +if test -n "$PKG_CONFIG"; then + if test -n "$gflags_LIBS"; then + pkg_cv_gflags_LIBS="$gflags_LIBS" + else + if test -n "$PKG_CONFIG" && \ + { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"libgflags\"") >&5 + ($PKG_CONFIG --exists --print-errors "libgflags") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + pkg_cv_gflags_LIBS=`$PKG_CONFIG --libs "libgflags" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + gflags_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "libgflags"` + else + gflags_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "libgflags"` + fi + # Put the nasty error message in config.log where it belongs + echo "$gflags_PKG_ERRORS" >&5 + + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + if test "x$with_gflags" != "xcheck"; then + { { echo "$as_me:$LINENO: error: --with-gflags was given, but test for gflags failed +See \`config.log' for more details." >&5 +echo "$as_me: error: --with-gflags was given, but test for gflags failed +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi +elif test $pkg_failed = untried; then + if test "x$with_gflags" != "xcheck"; then + { { echo "$as_me:$LINENO: error: --with-gflags was given, but test for gflags failed +See \`config.log' for more details." >&5 +echo "$as_me: error: --with-gflags was given, but test for gflags failed +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi +else + gflags_CFLAGS=$pkg_cv_gflags_CFLAGS + gflags_LIBS=$pkg_cv_gflags_LIBS + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +cat >>confdefs.h <<\_ACEOF +@%:@define HAVE_GFLAGS 1 +_ACEOF + +fi +fi + +# See if we have __builtin_expect. +# TODO: Use AC_CACHE. +echo "$as_me:$LINENO: checking if the compiler supports __builtin_expect" >&5 +echo $ECHO_N "checking if the compiler supports __builtin_expect... $ECHO_C" >&6 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + return __builtin_expect(1, 1) ? 1 : 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + snappy_have_builtin_expect=yes + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + snappy_have_builtin_expect=no + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +if test x$snappy_have_builtin_expect = xyes ; then + +cat >>confdefs.h <<\_ACEOF +@%:@define HAVE_BUILTIN_EXPECT 1 +_ACEOF + +fi + +# See if we have working count-trailing-zeros intrinsics. +# TODO: Use AC_CACHE. +echo "$as_me:$LINENO: checking if the compiler supports __builtin_ctzll" >&5 +echo $ECHO_N "checking if the compiler supports __builtin_ctzll... $ECHO_C" >&6 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + return (__builtin_ctzll(0x100000000LL) == 32) ? 1 : 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + snappy_have_builtin_ctz=yes + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + snappy_have_builtin_ctz=no + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +if test x$snappy_have_builtin_ctz = xyes ; then + +cat >>confdefs.h <<\_ACEOF +@%:@define HAVE_BUILTIN_CTZ 1 +_ACEOF + +fi + +# Other compression libraries; the unit test can use these for comparison +# if they are available. If they are not found, just ignore. +UNITTEST_LIBS="" + + + + + echo "$as_me:$LINENO: checking for zlibVersion in -lz" >&5 +echo $ECHO_N "checking for zlibVersion in -lz... $ECHO_C" >&6 +if test "${ac_cv_lib_z_zlibVersion+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $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 gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char zlibVersion (); +int +main () +{ +zlibVersion (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_z_zlibVersion=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_z_zlibVersion=no +fi +rm -f 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_z_zlibVersion" >&5 +echo "${ECHO_T}$ac_cv_lib_z_zlibVersion" >&6 +if test $ac_cv_lib_z_zlibVersion = yes; then + + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_LIBZ 1 +_ACEOF + + UNITTEST_LIBS="-lz $UNITTEST_LIBS" + +else + true + +fi + + + + + + echo "$as_me:$LINENO: checking for lzo1x_1_15_compress in -llzo2" >&5 +echo $ECHO_N "checking for lzo1x_1_15_compress in -llzo2... $ECHO_C" >&6 +if test "${ac_cv_lib_lzo2_lzo1x_1_15_compress+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llzo2 $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 gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char lzo1x_1_15_compress (); +int +main () +{ +lzo1x_1_15_compress (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_lzo2_lzo1x_1_15_compress=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_lzo2_lzo1x_1_15_compress=no +fi +rm -f 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_lzo2_lzo1x_1_15_compress" >&5 +echo "${ECHO_T}$ac_cv_lib_lzo2_lzo1x_1_15_compress" >&6 +if test $ac_cv_lib_lzo2_lzo1x_1_15_compress = yes; then + + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_LIBLZO2 1 +_ACEOF + + UNITTEST_LIBS="-llzo2 $UNITTEST_LIBS" + +else + true + +fi + + + + + + echo "$as_me:$LINENO: checking for lzf_compress in -llzf" >&5 +echo $ECHO_N "checking for lzf_compress in -llzf... $ECHO_C" >&6 +if test "${ac_cv_lib_lzf_lzf_compress+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llzf $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 gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char lzf_compress (); +int +main () +{ +lzf_compress (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_lzf_lzf_compress=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_lzf_lzf_compress=no +fi +rm -f 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_lzf_lzf_compress" >&5 +echo "${ECHO_T}$ac_cv_lib_lzf_lzf_compress" >&6 +if test $ac_cv_lib_lzf_lzf_compress = yes; then + + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_LIBLZF 1 +_ACEOF + + UNITTEST_LIBS="-llzf $UNITTEST_LIBS" + +else + true + +fi + + + + + + echo "$as_me:$LINENO: checking for fastlz_compress in -lfastlz" >&5 +echo $ECHO_N "checking for fastlz_compress in -lfastlz... $ECHO_C" >&6 +if test "${ac_cv_lib_fastlz_fastlz_compress+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lfastlz $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 gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char fastlz_compress (); +int +main () +{ +fastlz_compress (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_fastlz_fastlz_compress=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_fastlz_fastlz_compress=no +fi +rm -f 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_fastlz_fastlz_compress" >&5 +echo "${ECHO_T}$ac_cv_lib_fastlz_fastlz_compress" >&6 +if test $ac_cv_lib_fastlz_fastlz_compress = yes; then + + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_LIBFASTLZ 1 +_ACEOF + + UNITTEST_LIBS="-lfastlz $UNITTEST_LIBS" + +else + true + +fi + + + + + + echo "$as_me:$LINENO: checking for qlz_compress in -lquicklz" >&5 +echo $ECHO_N "checking for qlz_compress in -lquicklz... $ECHO_C" >&6 +if test "${ac_cv_lib_quicklz_qlz_compress+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lquicklz $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 gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char qlz_compress (); +int +main () +{ +qlz_compress (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_quicklz_qlz_compress=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_quicklz_qlz_compress=no +fi +rm -f 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_quicklz_qlz_compress" >&5 +echo "${ECHO_T}$ac_cv_lib_quicklz_qlz_compress" >&6 +if test $ac_cv_lib_quicklz_qlz_compress = yes; then + + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_LIBQUICKLZ 1 +_ACEOF + + UNITTEST_LIBS="-lquicklz $UNITTEST_LIBS" + +else + true + +fi + + + + +# These are used by snappy-stubs-public.h.in. +if test "$ac_cv_header_stdint_h" = "yes"; then + ac_cv_have_stdint_h=1 + +else + ac_cv_have_stdint_h=0 + +fi +if test "$ac_cv_header_stddef_h" = "yes"; then + ac_cv_have_stddef_h=1 + +else + ac_cv_have_stddef_h=0 + +fi + +# Export the version to snappy-stubs-public.h. +SNAPPY_MAJOR="1" +SNAPPY_MINOR="0" +SNAPPY_PATCHLEVEL="5" + + + + +SNAPPY_LTVERSION=2:3:1 + + + ac_config_headers="$ac_config_headers config.h" + + ac_config_files="$ac_config_files Makefile snappy-stubs-public.h" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIB@&t@OBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIB@&t@OBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${HAVE_GTEST_TRUE}" && test -z "${HAVE_GTEST_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"HAVE_GTEST\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"HAVE_GTEST\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# 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'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../@%:@@%:@ /;s/...$/ @%:@@%:@/;p;x;p;x' <<_ASBOX +@%:@@%:@ Running $as_me. @%:@@%:@ +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by snappy $as_me 1.0.5, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, 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 + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +snappy config.status 1.0.5 +configured by $0, generated by GNU Autoconf 2.59, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# +# INIT-COMMANDS section. +# + +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + +_ACEOF + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "snappy-stubs-public.h" ) CONFIG_FILES="$CONFIG_FILES snappy-stubs-public.h" ;; + "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@CYGPATH_W@,$CYGPATH_W,;t t +s,@PACKAGE@,$PACKAGE,;t t +s,@VERSION@,$VERSION,;t t +s,@ACLOCAL@,$ACLOCAL,;t t +s,@AUTOCONF@,$AUTOCONF,;t t +s,@AUTOMAKE@,$AUTOMAKE,;t t +s,@AUTOHEADER@,$AUTOHEADER,;t t +s,@MAKEINFO@,$MAKEINFO,;t t +s,@install_sh@,$install_sh,;t t +s,@STRIP@,$STRIP,;t t +s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t +s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t +s,@mkdir_p@,$mkdir_p,;t t +s,@AWK@,$AWK,;t t +s,@SET_MAKE@,$SET_MAKE,;t t +s,@am__leading_dot@,$am__leading_dot,;t t +s,@AMTAR@,$AMTAR,;t t +s,@am__tar@,$am__tar,;t t +s,@am__untar@,$am__untar,;t t +s,@LIBTOOL_DEPS@,$LIBTOOL_DEPS,;t t +s,@CXX@,$CXX,;t t +s,@CXXFLAGS@,$CXXFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CXX@,$ac_ct_CXX,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@DEPDIR@,$DEPDIR,;t t +s,@am__include@,$am__include,;t t +s,@am__quote@,$am__quote,;t t +s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t +s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t +s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t +s,@CXXDEPMODE@,$CXXDEPMODE,;t t +s,@am__fastdepCXX_TRUE@,$am__fastdepCXX_TRUE,;t t +s,@am__fastdepCXX_FALSE@,$am__fastdepCXX_FALSE,;t t +s,@CXXCPP@,$CXXCPP,;t t +s,@EGREP@,$EGREP,;t t +s,@GTEST_CONFIG@,$GTEST_CONFIG,;t t +s,@GTEST_CPPFLAGS@,$GTEST_CPPFLAGS,;t t +s,@GTEST_CXXFLAGS@,$GTEST_CXXFLAGS,;t t +s,@GTEST_LDFLAGS@,$GTEST_LDFLAGS,;t t +s,@GTEST_LIBS@,$GTEST_LIBS,;t t +s,@GTEST_VERSION@,$GTEST_VERSION,;t t +s,@HAVE_GTEST@,$HAVE_GTEST,;t t +s,@HAVE_GTEST_TRUE@,$HAVE_GTEST_TRUE,;t t +s,@HAVE_GTEST_FALSE@,$HAVE_GTEST_FALSE,;t t +s,@PKG_CONFIG@,$PKG_CONFIG,;t t +s,@ac_pt_PKG_CONFIG@,$ac_pt_PKG_CONFIG,;t t +s,@gflags_CFLAGS@,$gflags_CFLAGS,;t t +s,@gflags_LIBS@,$gflags_LIBS,;t t +s,@UNITTEST_LIBS@,$UNITTEST_LIBS,;t t +s,@ac_cv_have_stdint_h@,$ac_cv_have_stdint_h,;t t +s,@ac_cv_have_stddef_h@,$ac_cv_have_stddef_h,;t t +s,@SNAPPY_MAJOR@,$SNAPPY_MAJOR,;t t +s,@SNAPPY_MINOR@,$SNAPPY_MINOR,;t t +s,@SNAPPY_PATCHLEVEL@,$SNAPPY_PATCHLEVEL,;t t +s,@SNAPPY_LTVERSION@,$SNAPPY_LTVERSION,;t t +s,@LIB@&t@OBJS@,$LIB@&t@OBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_HEADER section. +# + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' +ac_dC=' ' +ac_dD=',;t' +# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='$,\1#\2define\3' +ac_uC=' ' +ac_uD=',;t' + +for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + # Do quote $f, to prevent DOS paths from being IFS'd. + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + # Remove the trailing spaces. + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + +_ACEOF + +# Transform confdefs.h into two sed scripts, `conftest.defines' and +# `conftest.undefs', that substitutes the proper values into +# config.h.in to produce config.h. The first handles `#define' +# templates, and the second `#undef' templates. +# And first: Protect against being on the right side of a sed subst in +# config.status. Protect against being in an unquoted here document +# in config.status. +rm -f conftest.defines conftest.undefs +# Using a here document instead of a string reduces the quoting nightmare. +# Putting comments in sed scripts is not portable. +# +# `end' is used to avoid that the second main sed command (meant for +# 0-ary CPP macros) applies to n-ary macro definitions. +# See the Autoconf documentation for `clear'. +cat >confdef2sed.sed <<\_ACEOF +s/[\\&,]/\\&/g +s,[\\$`],\\&,g +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp +t end +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +: end +_ACEOF +# If some macros were called several times there might be several times +# the same #defines, which is useless. Nevertheless, we may not want to +# sort them, since we want the *last* AC-DEFINE to be honored. +uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines +sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs +rm -f confdef2sed.sed + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >>conftest.undefs <<\_ACEOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +_ACEOF + +# Break up conftest.defines because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS +echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS +echo ' :' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.defines >/dev/null +do + # Write a limited-size here document to $tmp/defines.sed. + echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#define' lines. + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/defines.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines +echo ' fi # grep' >>$CONFIG_STATUS +echo >>$CONFIG_STATUS + +# Break up conftest.undefs because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #undef templates' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.undefs >/dev/null +do + # Write a limited-size here document to $tmp/undefs.sed. + echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#undef' + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/undefs.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail + rm -f conftest.undefs + mv conftest.tail conftest.undefs +done +rm -f conftest.undefs + +cat >>$CONFIG_STATUS <<\_ACEOF + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + echo "/* Generated by configure. */" >$tmp/config.h + else + echo "/* $ac_file. Generated by configure. */" >$tmp/config.h + fi + cat $tmp/in >>$tmp/config.h + rm -f $tmp/in + if test x"$ac_file" != x-; then + if diff $ac_file $tmp/config.h >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + rm -f $ac_file + mv $tmp/config.h $ac_file + fi + else + cat $tmp/config.h + rm -f $tmp/config.h + fi +# Compute $ac_file's index in $config_headers. +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $ac_file | $ac_file:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $ac_file" >`(dirname $ac_file) 2>/dev/null || +$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X$ac_file : 'X\(//\)[^/]' \| \ + X$ac_file : 'X\(//\)$' \| \ + X$ac_file : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X$ac_file | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'`/stamp-h$_am_stamp_count +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_COMMANDS section. +# +for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue + ac_dest=`echo "$ac_file" | sed 's,:.*,,'` + ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_dir=`(dirname "$ac_dest") 2>/dev/null || +$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_dest" : 'X\(//\)[^/]' \| \ + X"$ac_dest" : 'X\(//\)$' \| \ + X"$ac_dest" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_dest" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 +echo "$as_me: executing $ac_dest commands" >&6;} + case $ac_dest in + depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + dirpart=`(dirname "$mf") 2>/dev/null || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`(dirname "$file") 2>/dev/null || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p $dirpart/$fdir + else + as_dir=$dirpart/$fdir + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5 +echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;} + { (exit 1); exit 1; }; }; } + + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done + ;; + esac +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + diff --git a/snappy/snappy-1.0.5/autom4te.cache/output.1 b/snappy/snappy-1.0.5/autom4te.cache/output.1 new file mode 100644 index 00000000..4b2d725f --- /dev/null +++ b/snappy/snappy-1.0.5/autom4te.cache/output.1 @@ -0,0 +1,5872 @@ +@%:@! /bin/sh +@%:@ Guess values for system-dependent variables and create Makefiles. +@%:@ Generated by GNU Autoconf 2.59 for snappy 1.0.5. +@%:@ +@%:@ Copyright (C) 2003 Free Software Foundation, Inc. +@%:@ This configure script is free software; the Free Software Foundation +@%:@ gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# 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'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME='snappy' +PACKAGE_TARNAME='snappy' +PACKAGE_VERSION='1.0.5' +PACKAGE_STRING='snappy 1.0.5' +PACKAGE_BUGREPORT='' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif +#if HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar LIBTOOL_DEPS CXX CXXFLAGS LDFLAGS CPPFLAGS ac_ct_CXX EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CXXCPP EGREP GTEST_CONFIG GTEST_CPPFLAGS GTEST_CXXFLAGS GTEST_LDFLAGS GTEST_LIBS GTEST_VERSION HAVE_GTEST HAVE_GTEST_TRUE HAVE_GTEST_FALSE PKG_CONFIG ac_pt_PKG_CONFIG gflags_CFLAGS gflags_LIBS UNITTEST_LIBS ac_cv_have_stdint_h ac_cv_have_stddef_h SNAPPY_MAJOR SNAPPY_MINOR SNAPPY_PATCHLEVEL SNAPPY_LTVERSION LIB@&t@OBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -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 && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -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 && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -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 && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + 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 && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CXX_set=${CXX+set} +ac_env_CXX_value=$CXX +ac_cv_env_CXX_set=${CXX+set} +ac_cv_env_CXX_value=$CXX +ac_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_env_CXXFLAGS_value=$CXXFLAGS +ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_cv_env_CXXFLAGS_value=$CXXFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CXXCPP_set=${CXXCPP+set} +ac_env_CXXCPP_value=$CXXCPP +ac_cv_env_CXXCPP_set=${CXXCPP+set} +ac_cv_env_CXXCPP_value=$CXXCPP +ac_env_GTEST_CONFIG_set=${GTEST_CONFIG+set} +ac_env_GTEST_CONFIG_value=$GTEST_CONFIG +ac_cv_env_GTEST_CONFIG_set=${GTEST_CONFIG+set} +ac_cv_env_GTEST_CONFIG_value=$GTEST_CONFIG +ac_env_GTEST_CPPFLAGS_set=${GTEST_CPPFLAGS+set} +ac_env_GTEST_CPPFLAGS_value=$GTEST_CPPFLAGS +ac_cv_env_GTEST_CPPFLAGS_set=${GTEST_CPPFLAGS+set} +ac_cv_env_GTEST_CPPFLAGS_value=$GTEST_CPPFLAGS +ac_env_GTEST_CXXFLAGS_set=${GTEST_CXXFLAGS+set} +ac_env_GTEST_CXXFLAGS_value=$GTEST_CXXFLAGS +ac_cv_env_GTEST_CXXFLAGS_set=${GTEST_CXXFLAGS+set} +ac_cv_env_GTEST_CXXFLAGS_value=$GTEST_CXXFLAGS +ac_env_GTEST_LDFLAGS_set=${GTEST_LDFLAGS+set} +ac_env_GTEST_LDFLAGS_value=$GTEST_LDFLAGS +ac_cv_env_GTEST_LDFLAGS_set=${GTEST_LDFLAGS+set} +ac_cv_env_GTEST_LDFLAGS_value=$GTEST_LDFLAGS +ac_env_GTEST_LIBS_set=${GTEST_LIBS+set} +ac_env_GTEST_LIBS_value=$GTEST_LIBS +ac_cv_env_GTEST_LIBS_set=${GTEST_LIBS+set} +ac_cv_env_GTEST_LIBS_value=$GTEST_LIBS +ac_env_GTEST_VERSION_set=${GTEST_VERSION+set} +ac_env_GTEST_VERSION_value=$GTEST_VERSION +ac_cv_env_GTEST_VERSION_set=${GTEST_VERSION+set} +ac_cv_env_GTEST_VERSION_value=$GTEST_VERSION +ac_env_PKG_CONFIG_set=${PKG_CONFIG+set} +ac_env_PKG_CONFIG_value=$PKG_CONFIG +ac_cv_env_PKG_CONFIG_set=${PKG_CONFIG+set} +ac_cv_env_PKG_CONFIG_value=$PKG_CONFIG +ac_env_gflags_CFLAGS_set=${gflags_CFLAGS+set} +ac_env_gflags_CFLAGS_value=$gflags_CFLAGS +ac_cv_env_gflags_CFLAGS_set=${gflags_CFLAGS+set} +ac_cv_env_gflags_CFLAGS_value=$gflags_CFLAGS +ac_env_gflags_LIBS_set=${gflags_LIBS+set} +ac_env_gflags_LIBS_value=$gflags_LIBS +ac_cv_env_gflags_LIBS_set=${gflags_LIBS+set} +ac_cv_env_gflags_LIBS_value=$gflags_LIBS + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures snappy 1.0.5 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of snappy 1.0.5:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + --enable-gtest Enable tests using the Google C++ Testing Framework. + (Default is enabled.) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-gflags use Google Flags package to enhance the unit test + @<:@default=check@:>@ + +Some influential environment variables: + CXX C++ compiler command + CXXFLAGS C++ compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + CXXCPP C++ preprocessor + GTEST_CONFIG + The exact path of Google Test's 'gtest-config' script. + GTEST_CPPFLAGS + C-like preprocessor flags for Google Test. + GTEST_CXXFLAGS + C++ compile flags for Google Test. + GTEST_LDFLAGS + Linker path and option flags for Google Test. + GTEST_LIBS Library linking flags for Google Test. + GTEST_VERSION + The version of Google Test available. + PKG_CONFIG path to pkg-config utility + gflags_CFLAGS + C compiler flags for gflags, overriding pkg-config + gflags_LIBS linker flags for gflags, overriding pkg-config + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF +snappy configure 1.0.5 +generated by GNU Autoconf 2.59 + +Copyright (C) 2003 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by snappy $as_me 1.0.5, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +@%:@@%:@ --------- @%:@@%:@ +@%:@@%:@ Platform. @%:@@%:@ +@%:@@%:@ --------- @%:@@%:@ + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +@%:@@%:@ ----------- @%:@@%:@ +@%:@@%:@ Core tests. @%:@@%:@ +@%:@@%:@ ----------- @%:@@%:@ + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +@%:@@%:@ ---------------- @%:@@%:@ +@%:@@%:@ Cache variables. @%:@@%:@ +@%:@@%:@ ---------------- @%:@@%:@ +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +@%:@@%:@ ----------------- @%:@@%:@ +@%:@@%:@ Output variables. @%:@@%:@ +@%:@@%:@ ----------------- @%:@@%:@ +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +@%:@@%:@ ------------- @%:@@%:@ +@%:@@%:@ Output files. @%:@@%:@ +@%:@@%:@ ------------- @%:@@%:@ +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +@%:@@%:@ ----------- @%:@@%:@ +@%:@@%:@ confdefs.h. @%:@@%:@ +@%:@@%:@ ----------- @%:@@%:@ +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + + + + + + + + +case m4 in + [\\/]* | ?:[\\/]* ) ac_macro_dir=m4 ;; + *) ac_macro_dir=$srcdir/m4 ;; +esac +if test -d "$ac_macro_dir"; then : +else + { { echo "$as_me:$LINENO: error: cannot find macro directory \`m4'" >&5 +echo "$as_me: error: cannot find macro directory \`m4'" >&2;} + { (exit 1); exit 1; }; } +fi + + +# These are flags passed to automake (though they look like gcc flags!) +am__api_version="1.9" +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$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. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo "$as_me:$LINENO: checking whether build environment is sane" >&5 +echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6 +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&5 +echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&2;} + { (exit 1); exit 1; }; } + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! +Check your system clock" >&5 +echo "$as_me: error: newly created file is older than distributed files! +Check your system clock" >&2;} + { (exit 1); exit 1; }; } +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +test "$program_prefix" != NONE && + program_transform_name="s,^,$program_prefix,;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$,$program_suffix,;$program_transform_name" +# Double any \ or $. echo might interpret backslashes. +# By default was `s,x,x', remove it if useless. +cat <<\_ACEOF >conftest.sed +s/[\\$]/&&/g;s/;s,x,x,$// +_ACEOF +program_transform_name=`echo $program_transform_name | sed -f conftest.sed` +rm conftest.sed + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 +echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + # We used to keeping the `.' as first argument, in order to + # allow $(mkdir_p) to be used without argument. As in + # $(mkdir_p) $(somedir) + # where $(somedir) is conditionally defined. However this is wrong + # for two reasons: + # 1. if the package is installed by a user who cannot write `.' + # make install will fail, + # 2. the above comment should most certainly read + # $(mkdir_p) $(DESTDIR)$(somedir) + # so it does not work when $(somedir) is undefined and + # $(DESTDIR) is not. + # To support the latter case, we have to write + # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), + # so the `.' trick is pointless. + mkdir_p='mkdir -p --' +else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + for d in ./-p ./--version; + do + test -d $d && rmdir $d + done + # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. + if test -f "$ac_aux_dir/mkinstalldirs"; then + mkdir_p='$(mkinstalldirs)' + else + mkdir_p='$(install_sh) -d' + fi +fi + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_AWK+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$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 + fi +done +done + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + echo "$as_me:$LINENO: result: $AWK" >&5 +echo "${ECHO_T}$AWK" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$AWK" && break +done + +echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="$(MAKE)"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 +echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} + { (exit 1); exit 1; }; } +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='snappy' + VERSION='1.0.5' + + +cat >>confdefs.h <<_ACEOF +@%:@define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +@%:@define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +install_sh=${install_sh-"$am_aux_dir/install-sh"} + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$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 + fi +done +done + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$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 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + STRIP=$ac_ct_STRIP +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. + +AMTAR=${AMTAR-"${am_missing_run}tar"} + +am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' + + + + + + +LT_INIT + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC + 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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$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 + fi +done +done + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$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 + fi +done +done + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CXX" && break +done +test -n "$ac_ct_CXX" || ac_ct_CXX="g++" + + CXX=$ac_ct_CXX +fi + + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C++ compiler default output file name" >&5 +echo $ECHO_N "checking for C++ compiler default output file name... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C++ compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C++ compiler works" >&5 +echo $ECHO_N "checking whether the C++ compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C++ compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C++ compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +CXXFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cxx_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +@%:@include +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +DEPDIR="${am__leading_dot}deps" + + ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo done +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 +echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6 +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi + + +echo "$as_me:$LINENO: result: $_am_result" >&5 +echo "${ECHO_T}$_am_result" >&6 +rm -f confinc confmf + +# Check whether --enable-dependency-tracking or --disable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then + enableval="$enable_dependency_tracking" + +fi; +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi + + +if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + + +depcc="$CXX" am_compiler_list= + +echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 +if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 +echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6 +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + + +if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 +echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6 +if test "${ac_cv_c_bigendian+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # See if sys/param.h defines the BYTE_ORDER macro. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + # It does; now see whether it defined to BIG_ENDIAN or not. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_c_bigendian=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +# It does not; compile a test program. +if test "$cross_compiling" = yes; then + # try to guess the endianness by grepping values into an object file + ac_cv_c_bigendian=unknown + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; +short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; +void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } +short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; +short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; +void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } +int +main () +{ + _ascii (); _ebcdic (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then + ac_cv_c_bigendian=yes +fi +if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +int +main () +{ + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long l; + char c[sizeof (long)]; + } u; + u.l = 1; + exit (u.c[sizeof (long) - 1] == 1); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_bigendian=yes +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 +echo "${ECHO_T}$ac_cv_c_bigendian" >&6 +case $ac_cv_c_bigendian in + yes) + +cat >>confdefs.h <<\_ACEOF +@%:@define WORDS_BIGENDIAN 1 +_ACEOF + ;; + no) + ;; + *) + { { echo "$as_me:$LINENO: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&5 +echo "$as_me: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 +echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6 +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +@%:@ifdef __STDC__ +@%:@ include +@%:@else +@%:@ include +@%:@endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 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); } >/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 + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +@%:@include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 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); } >/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 + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +echo "$as_me:$LINENO: result: $CXXCPP" >&5 +echo "${ECHO_T}$CXXCPP" >&6 +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +@%:@ifdef __STDC__ +@%:@ include +@%:@else +@%:@ include +@%:@endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 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); } >/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 + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +@%:@include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 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); } >/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 + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +@%:@define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +@%:@include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +@%:@define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + + + + + +for ac_header in stdint.h stddef.h sys/mman.h sys/resource.h windows.h byteswap.h sys/byteswap.h sys/endian.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +@%:@include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +@%:@include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 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); } >/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 + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +@%:@@%:@ --------------------------------- @%:@@%:@ +@%:@@%:@ Report this to the snappy lists. @%:@@%:@ +@%:@@%:@ --------------------------------- @%:@@%:@ +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +@%:@define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +# Don't use AC_FUNC_MMAP, as it checks for mappings of already-mapped memory, +# which we don't need (and does not exist on Windows). +echo "$as_me:$LINENO: checking for mmap" >&5 +echo $ECHO_N "checking for mmap... $ECHO_C" >&6 +if test "${ac_cv_func_mmap+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define mmap to an innocuous variant, in case declares mmap. + For example, HP-UX 11i declares gettimeofday. */ +#define mmap innocuous_mmap + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char mmap (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef mmap + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char mmap (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_mmap) || defined (__stub___mmap) +choke me +#else +char (*f) () = mmap; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != mmap; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_mmap=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_mmap=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_mmap" >&5 +echo "${ECHO_T}$ac_cv_func_mmap" >&6 + + + +# Check whether --enable-gtest or --disable-gtest was given. +if test "${enable_gtest+set}" = set; then + enableval="$enable_gtest" + +else + enable_gtest= +fi; + + + + + + +HAVE_GTEST="no" +if test "x${enable_gtest}" != "xno"; then + echo "$as_me:$LINENO: checking for 'gtest-config'" >&5 +echo $ECHO_N "checking for 'gtest-config'... $ECHO_C" >&6 + if test "x${enable_gtest}" = "xyes"; then + if test -x "${enable_gtest}/scripts/gtest-config"; then + GTEST_CONFIG="${enable_gtest}/scripts/gtest-config" +else + GTEST_CONFIG="${enable_gtest}/bin/gtest-config" +fi + + if test -x "${GTEST_CONFIG}"; then + : +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + { { echo "$as_me:$LINENO: error: Unable to locate either a built or installed Google Test. +The specific location '${enable_gtest}' was provided for a built or installed +Google Test, but no 'gtest-config' script could be found at this location." >&5 +echo "$as_me: error: Unable to locate either a built or installed Google Test. +The specific location '${enable_gtest}' was provided for a built or installed +Google Test, but no 'gtest-config' script could be found at this location." >&2;} + { (exit 1); exit 1; }; } + +fi + +else + # Extract the first word of "gtest-config", so it can be a program name with args. +set dummy gtest-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_GTEST_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GTEST_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_GTEST_CONFIG="$GTEST_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GTEST_CONFIG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +GTEST_CONFIG=$ac_cv_path_GTEST_CONFIG + +if test -n "$GTEST_CONFIG"; then + echo "$as_me:$LINENO: result: $GTEST_CONFIG" >&5 +echo "${ECHO_T}$GTEST_CONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi + + if test -x "${GTEST_CONFIG}"; then + echo "$as_me:$LINENO: result: ${GTEST_CONFIG}" >&5 +echo "${ECHO_T}${GTEST_CONFIG}" >&6 + _gtest_min_version="--min-version=0" + echo "$as_me:$LINENO: checking for Google Test" >&5 +echo $ECHO_N "checking for Google Test... $ECHO_C" >&6 + if ${GTEST_CONFIG} ${_gtest_min_version}; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + HAVE_GTEST='yes' +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + if test "x${HAVE_GTEST}" = "xyes"; then + GTEST_CPPFLAGS=`${GTEST_CONFIG} --cppflags` + GTEST_CXXFLAGS=`${GTEST_CONFIG} --cxxflags` + GTEST_LDFLAGS=`${GTEST_CONFIG} --ldflags` + GTEST_LIBS=`${GTEST_CONFIG} --libs` + GTEST_VERSION=`${GTEST_CONFIG} --version` + +cat >>confdefs.h <<\_ACEOF +@%:@define HAVE_GTEST 1 +_ACEOF + +else + if test "x${enable_gtest}" = "xyes"; then + { { echo "$as_me:$LINENO: error: Google Test was enabled, but no viable version could be found." >&5 +echo "$as_me: error: Google Test was enabled, but no viable version could be found." >&2;} + { (exit 1); exit 1; }; } + +fi + +fi + +fi + + + + +if test "x$HAVE_GTEST" = "xyes"; then + HAVE_GTEST_TRUE= + HAVE_GTEST_FALSE='#' +else + HAVE_GTEST_TRUE='#' + HAVE_GTEST_FALSE= +fi + +if test "x$HAVE_GTEST" = "xyes"; then + true +else + true # Ignore; we can live without it. +fi + + + + +# Check whether --with-gflags or --without-gflags was given. +if test "${with_gflags+set}" = set; then + withval="$with_gflags" + +else + with_gflags=check +fi; + +if test "x$with_gflags" != "xno"; then + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_PKG_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG + +if test -n "$PKG_CONFIG"; then + echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5 +echo "${ECHO_T}$PKG_CONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG + +if test -n "$ac_pt_PKG_CONFIG"; then + echo "$as_me:$LINENO: result: $ac_pt_PKG_CONFIG" >&5 +echo "${ECHO_T}$ac_pt_PKG_CONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + PKG_CONFIG=$ac_pt_PKG_CONFIG +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + echo "$as_me:$LINENO: checking pkg-config is at least version $_pkg_min_version" >&5 +echo $ECHO_N "checking pkg-config is at least version $_pkg_min_version... $ECHO_C" >&6 + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + PKG_CONFIG="" + fi + +fi + +pkg_failed=no +echo "$as_me:$LINENO: checking for gflags" >&5 +echo $ECHO_N "checking for gflags... $ECHO_C" >&6 + +if test -n "$PKG_CONFIG"; then + if test -n "$gflags_CFLAGS"; then + pkg_cv_gflags_CFLAGS="$gflags_CFLAGS" + else + if test -n "$PKG_CONFIG" && \ + { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"libgflags\"") >&5 + ($PKG_CONFIG --exists --print-errors "libgflags") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + pkg_cv_gflags_CFLAGS=`$PKG_CONFIG --cflags "libgflags" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi +if test -n "$PKG_CONFIG"; then + if test -n "$gflags_LIBS"; then + pkg_cv_gflags_LIBS="$gflags_LIBS" + else + if test -n "$PKG_CONFIG" && \ + { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"libgflags\"") >&5 + ($PKG_CONFIG --exists --print-errors "libgflags") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + pkg_cv_gflags_LIBS=`$PKG_CONFIG --libs "libgflags" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + gflags_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "libgflags"` + else + gflags_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "libgflags"` + fi + # Put the nasty error message in config.log where it belongs + echo "$gflags_PKG_ERRORS" >&5 + + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + if test "x$with_gflags" != "xcheck"; then + { { echo "$as_me:$LINENO: error: --with-gflags was given, but test for gflags failed +See \`config.log' for more details." >&5 +echo "$as_me: error: --with-gflags was given, but test for gflags failed +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi +elif test $pkg_failed = untried; then + if test "x$with_gflags" != "xcheck"; then + { { echo "$as_me:$LINENO: error: --with-gflags was given, but test for gflags failed +See \`config.log' for more details." >&5 +echo "$as_me: error: --with-gflags was given, but test for gflags failed +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi +else + gflags_CFLAGS=$pkg_cv_gflags_CFLAGS + gflags_LIBS=$pkg_cv_gflags_LIBS + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +cat >>confdefs.h <<\_ACEOF +@%:@define HAVE_GFLAGS 1 +_ACEOF + +fi +fi + +# See if we have __builtin_expect. +# TODO: Use AC_CACHE. +echo "$as_me:$LINENO: checking if the compiler supports __builtin_expect" >&5 +echo $ECHO_N "checking if the compiler supports __builtin_expect... $ECHO_C" >&6 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + return __builtin_expect(1, 1) ? 1 : 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + snappy_have_builtin_expect=yes + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + snappy_have_builtin_expect=no + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +if test x$snappy_have_builtin_expect = xyes ; then + +cat >>confdefs.h <<\_ACEOF +@%:@define HAVE_BUILTIN_EXPECT 1 +_ACEOF + +fi + +# See if we have working count-trailing-zeros intrinsics. +# TODO: Use AC_CACHE. +echo "$as_me:$LINENO: checking if the compiler supports __builtin_ctzll" >&5 +echo $ECHO_N "checking if the compiler supports __builtin_ctzll... $ECHO_C" >&6 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + return (__builtin_ctzll(0x100000000LL) == 32) ? 1 : 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + snappy_have_builtin_ctz=yes + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + snappy_have_builtin_ctz=no + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +if test x$snappy_have_builtin_ctz = xyes ; then + +cat >>confdefs.h <<\_ACEOF +@%:@define HAVE_BUILTIN_CTZ 1 +_ACEOF + +fi + +# Other compression libraries; the unit test can use these for comparison +# if they are available. If they are not found, just ignore. +UNITTEST_LIBS="" + + + + + echo "$as_me:$LINENO: checking for zlibVersion in -lz" >&5 +echo $ECHO_N "checking for zlibVersion in -lz... $ECHO_C" >&6 +if test "${ac_cv_lib_z_zlibVersion+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $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 gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char zlibVersion (); +int +main () +{ +zlibVersion (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_z_zlibVersion=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_z_zlibVersion=no +fi +rm -f 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_z_zlibVersion" >&5 +echo "${ECHO_T}$ac_cv_lib_z_zlibVersion" >&6 +if test $ac_cv_lib_z_zlibVersion = yes; then + + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_LIBZ 1 +_ACEOF + + UNITTEST_LIBS="-lz $UNITTEST_LIBS" + +else + true + +fi + + + + + + echo "$as_me:$LINENO: checking for lzo1x_1_15_compress in -llzo2" >&5 +echo $ECHO_N "checking for lzo1x_1_15_compress in -llzo2... $ECHO_C" >&6 +if test "${ac_cv_lib_lzo2_lzo1x_1_15_compress+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llzo2 $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 gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char lzo1x_1_15_compress (); +int +main () +{ +lzo1x_1_15_compress (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_lzo2_lzo1x_1_15_compress=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_lzo2_lzo1x_1_15_compress=no +fi +rm -f 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_lzo2_lzo1x_1_15_compress" >&5 +echo "${ECHO_T}$ac_cv_lib_lzo2_lzo1x_1_15_compress" >&6 +if test $ac_cv_lib_lzo2_lzo1x_1_15_compress = yes; then + + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_LIBLZO2 1 +_ACEOF + + UNITTEST_LIBS="-llzo2 $UNITTEST_LIBS" + +else + true + +fi + + + + + + echo "$as_me:$LINENO: checking for lzf_compress in -llzf" >&5 +echo $ECHO_N "checking for lzf_compress in -llzf... $ECHO_C" >&6 +if test "${ac_cv_lib_lzf_lzf_compress+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llzf $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 gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char lzf_compress (); +int +main () +{ +lzf_compress (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_lzf_lzf_compress=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_lzf_lzf_compress=no +fi +rm -f 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_lzf_lzf_compress" >&5 +echo "${ECHO_T}$ac_cv_lib_lzf_lzf_compress" >&6 +if test $ac_cv_lib_lzf_lzf_compress = yes; then + + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_LIBLZF 1 +_ACEOF + + UNITTEST_LIBS="-llzf $UNITTEST_LIBS" + +else + true + +fi + + + + + + echo "$as_me:$LINENO: checking for fastlz_compress in -lfastlz" >&5 +echo $ECHO_N "checking for fastlz_compress in -lfastlz... $ECHO_C" >&6 +if test "${ac_cv_lib_fastlz_fastlz_compress+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lfastlz $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 gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char fastlz_compress (); +int +main () +{ +fastlz_compress (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_fastlz_fastlz_compress=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_fastlz_fastlz_compress=no +fi +rm -f 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_fastlz_fastlz_compress" >&5 +echo "${ECHO_T}$ac_cv_lib_fastlz_fastlz_compress" >&6 +if test $ac_cv_lib_fastlz_fastlz_compress = yes; then + + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_LIBFASTLZ 1 +_ACEOF + + UNITTEST_LIBS="-lfastlz $UNITTEST_LIBS" + +else + true + +fi + + + + + + echo "$as_me:$LINENO: checking for qlz_compress in -lquicklz" >&5 +echo $ECHO_N "checking for qlz_compress in -lquicklz... $ECHO_C" >&6 +if test "${ac_cv_lib_quicklz_qlz_compress+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lquicklz $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 gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char qlz_compress (); +int +main () +{ +qlz_compress (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_quicklz_qlz_compress=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_quicklz_qlz_compress=no +fi +rm -f 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_quicklz_qlz_compress" >&5 +echo "${ECHO_T}$ac_cv_lib_quicklz_qlz_compress" >&6 +if test $ac_cv_lib_quicklz_qlz_compress = yes; then + + cat >>confdefs.h <<_ACEOF +@%:@define HAVE_LIBQUICKLZ 1 +_ACEOF + + UNITTEST_LIBS="-lquicklz $UNITTEST_LIBS" + +else + true + +fi + + + + +# These are used by snappy-stubs-public.h.in. +if test "$ac_cv_header_stdint_h" = "yes"; then + ac_cv_have_stdint_h=1 + +else + ac_cv_have_stdint_h=0 + +fi +if test "$ac_cv_header_stddef_h" = "yes"; then + ac_cv_have_stddef_h=1 + +else + ac_cv_have_stddef_h=0 + +fi + +# Export the version to snappy-stubs-public.h. +SNAPPY_MAJOR="1" +SNAPPY_MINOR="0" +SNAPPY_PATCHLEVEL="5" + + + + +SNAPPY_LTVERSION=2:3:1 + + + ac_config_headers="$ac_config_headers config.h" + + ac_config_files="$ac_config_files Makefile snappy-stubs-public.h" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIB@&t@OBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIB@&t@OBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${HAVE_GTEST_TRUE}" && test -z "${HAVE_GTEST_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"HAVE_GTEST\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"HAVE_GTEST\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# 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'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../@%:@@%:@ /;s/...$/ @%:@@%:@/;p;x;p;x' <<_ASBOX +@%:@@%:@ Running $as_me. @%:@@%:@ +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by snappy $as_me 1.0.5, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, 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 + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +snappy config.status 1.0.5 +configured by $0, generated by GNU Autoconf 2.59, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# +# INIT-COMMANDS section. +# + +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + +_ACEOF + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "snappy-stubs-public.h" ) CONFIG_FILES="$CONFIG_FILES snappy-stubs-public.h" ;; + "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@CYGPATH_W@,$CYGPATH_W,;t t +s,@PACKAGE@,$PACKAGE,;t t +s,@VERSION@,$VERSION,;t t +s,@ACLOCAL@,$ACLOCAL,;t t +s,@AUTOCONF@,$AUTOCONF,;t t +s,@AUTOMAKE@,$AUTOMAKE,;t t +s,@AUTOHEADER@,$AUTOHEADER,;t t +s,@MAKEINFO@,$MAKEINFO,;t t +s,@install_sh@,$install_sh,;t t +s,@STRIP@,$STRIP,;t t +s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t +s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t +s,@mkdir_p@,$mkdir_p,;t t +s,@AWK@,$AWK,;t t +s,@SET_MAKE@,$SET_MAKE,;t t +s,@am__leading_dot@,$am__leading_dot,;t t +s,@AMTAR@,$AMTAR,;t t +s,@am__tar@,$am__tar,;t t +s,@am__untar@,$am__untar,;t t +s,@LIBTOOL_DEPS@,$LIBTOOL_DEPS,;t t +s,@CXX@,$CXX,;t t +s,@CXXFLAGS@,$CXXFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CXX@,$ac_ct_CXX,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@DEPDIR@,$DEPDIR,;t t +s,@am__include@,$am__include,;t t +s,@am__quote@,$am__quote,;t t +s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t +s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t +s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t +s,@CXXDEPMODE@,$CXXDEPMODE,;t t +s,@am__fastdepCXX_TRUE@,$am__fastdepCXX_TRUE,;t t +s,@am__fastdepCXX_FALSE@,$am__fastdepCXX_FALSE,;t t +s,@CXXCPP@,$CXXCPP,;t t +s,@EGREP@,$EGREP,;t t +s,@GTEST_CONFIG@,$GTEST_CONFIG,;t t +s,@GTEST_CPPFLAGS@,$GTEST_CPPFLAGS,;t t +s,@GTEST_CXXFLAGS@,$GTEST_CXXFLAGS,;t t +s,@GTEST_LDFLAGS@,$GTEST_LDFLAGS,;t t +s,@GTEST_LIBS@,$GTEST_LIBS,;t t +s,@GTEST_VERSION@,$GTEST_VERSION,;t t +s,@HAVE_GTEST@,$HAVE_GTEST,;t t +s,@HAVE_GTEST_TRUE@,$HAVE_GTEST_TRUE,;t t +s,@HAVE_GTEST_FALSE@,$HAVE_GTEST_FALSE,;t t +s,@PKG_CONFIG@,$PKG_CONFIG,;t t +s,@ac_pt_PKG_CONFIG@,$ac_pt_PKG_CONFIG,;t t +s,@gflags_CFLAGS@,$gflags_CFLAGS,;t t +s,@gflags_LIBS@,$gflags_LIBS,;t t +s,@UNITTEST_LIBS@,$UNITTEST_LIBS,;t t +s,@ac_cv_have_stdint_h@,$ac_cv_have_stdint_h,;t t +s,@ac_cv_have_stddef_h@,$ac_cv_have_stddef_h,;t t +s,@SNAPPY_MAJOR@,$SNAPPY_MAJOR,;t t +s,@SNAPPY_MINOR@,$SNAPPY_MINOR,;t t +s,@SNAPPY_PATCHLEVEL@,$SNAPPY_PATCHLEVEL,;t t +s,@SNAPPY_LTVERSION@,$SNAPPY_LTVERSION,;t t +s,@LIB@&t@OBJS@,$LIB@&t@OBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_HEADER section. +# + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' +ac_dC=' ' +ac_dD=',;t' +# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='$,\1#\2define\3' +ac_uC=' ' +ac_uD=',;t' + +for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + # Do quote $f, to prevent DOS paths from being IFS'd. + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + # Remove the trailing spaces. + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + +_ACEOF + +# Transform confdefs.h into two sed scripts, `conftest.defines' and +# `conftest.undefs', that substitutes the proper values into +# config.h.in to produce config.h. The first handles `#define' +# templates, and the second `#undef' templates. +# And first: Protect against being on the right side of a sed subst in +# config.status. Protect against being in an unquoted here document +# in config.status. +rm -f conftest.defines conftest.undefs +# Using a here document instead of a string reduces the quoting nightmare. +# Putting comments in sed scripts is not portable. +# +# `end' is used to avoid that the second main sed command (meant for +# 0-ary CPP macros) applies to n-ary macro definitions. +# See the Autoconf documentation for `clear'. +cat >confdef2sed.sed <<\_ACEOF +s/[\\&,]/\\&/g +s,[\\$`],\\&,g +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp +t end +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +: end +_ACEOF +# If some macros were called several times there might be several times +# the same #defines, which is useless. Nevertheless, we may not want to +# sort them, since we want the *last* AC-DEFINE to be honored. +uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines +sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs +rm -f confdef2sed.sed + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >>conftest.undefs <<\_ACEOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +_ACEOF + +# Break up conftest.defines because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS +echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS +echo ' :' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.defines >/dev/null +do + # Write a limited-size here document to $tmp/defines.sed. + echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#define' lines. + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/defines.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines +echo ' fi # grep' >>$CONFIG_STATUS +echo >>$CONFIG_STATUS + +# Break up conftest.undefs because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #undef templates' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.undefs >/dev/null +do + # Write a limited-size here document to $tmp/undefs.sed. + echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#undef' + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/undefs.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail + rm -f conftest.undefs + mv conftest.tail conftest.undefs +done +rm -f conftest.undefs + +cat >>$CONFIG_STATUS <<\_ACEOF + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + echo "/* Generated by configure. */" >$tmp/config.h + else + echo "/* $ac_file. Generated by configure. */" >$tmp/config.h + fi + cat $tmp/in >>$tmp/config.h + rm -f $tmp/in + if test x"$ac_file" != x-; then + if diff $ac_file $tmp/config.h >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + rm -f $ac_file + mv $tmp/config.h $ac_file + fi + else + cat $tmp/config.h + rm -f $tmp/config.h + fi +# Compute $ac_file's index in $config_headers. +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $ac_file | $ac_file:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $ac_file" >`(dirname $ac_file) 2>/dev/null || +$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X$ac_file : 'X\(//\)[^/]' \| \ + X$ac_file : 'X\(//\)$' \| \ + X$ac_file : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X$ac_file | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'`/stamp-h$_am_stamp_count +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_COMMANDS section. +# +for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue + ac_dest=`echo "$ac_file" | sed 's,:.*,,'` + ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_dir=`(dirname "$ac_dest") 2>/dev/null || +$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_dest" : 'X\(//\)[^/]' \| \ + X"$ac_dest" : 'X\(//\)$' \| \ + X"$ac_dest" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_dest" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 +echo "$as_me: executing $ac_dest commands" >&6;} + case $ac_dest in + depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + dirpart=`(dirname "$mf") 2>/dev/null || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`(dirname "$file") 2>/dev/null || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p $dirpart/$fdir + else + as_dir=$dirpart/$fdir + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5 +echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;} + { (exit 1); exit 1; }; }; } + + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done + ;; + esac +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + diff --git a/snappy/snappy-1.0.5/autom4te.cache/requests b/snappy/snappy-1.0.5/autom4te.cache/requests new file mode 100644 index 00000000..69c4b844 --- /dev/null +++ b/snappy/snappy-1.0.5/autom4te.cache/requests @@ -0,0 +1,278 @@ +# This file was generated. +# It contains the lists of macros which have been traced. +# It can be safely removed. + +@request = ( + bless( [ + '0', + 1, + [ + '/usr/share/autoconf' + ], + [ + '/usr/share/autoconf/autoconf/autoconf.m4f', + '/usr/share/aclocal/pkg.m4', + '/usr/share/aclocal-1.9/amversion.m4', + '/usr/share/aclocal-1.9/auxdir.m4', + '/usr/share/aclocal-1.9/cond.m4', + '/usr/share/aclocal-1.9/depend.m4', + '/usr/share/aclocal-1.9/depout.m4', + '/usr/share/aclocal-1.9/init.m4', + '/usr/share/aclocal-1.9/install-sh.m4', + '/usr/share/aclocal-1.9/lead-dot.m4', + '/usr/share/aclocal-1.9/make.m4', + '/usr/share/aclocal-1.9/missing.m4', + '/usr/share/aclocal-1.9/mkdirp.m4', + '/usr/share/aclocal-1.9/options.m4', + '/usr/share/aclocal-1.9/runlog.m4', + '/usr/share/aclocal-1.9/sanity.m4', + '/usr/share/aclocal-1.9/strip.m4', + '/usr/share/aclocal-1.9/tar.m4', + 'm4/gtest.m4', + 'configure.ac' + ], + { + 'm4_pattern_forbid' => 1, + 'AC_CONFIG_LIBOBJ_DIR' => 1, + 'AC_C_VOLATILE' => 1, + 'AC_TYPE_OFF_T' => 1, + 'AC_FUNC_CLOSEDIR_VOID' => 1, + 'AC_REPLACE_FNMATCH' => 1, + 'AC_DEFUN' => 1, + 'AC_PROG_LIBTOOL' => 1, + 'AM_PROG_MKDIR_P' => 1, + 'AC_FUNC_STAT' => 1, + 'AC_FUNC_WAIT3' => 1, + 'AC_HEADER_TIME' => 1, + 'AM_AUTOMAKE_VERSION' => 1, + 'AC_FUNC_LSTAT' => 1, + 'AC_STRUCT_TM' => 1, + 'AM_MISSING_HAS_RUN' => 1, + 'AC_FUNC_GETMNTENT' => 1, + 'AC_TYPE_MODE_T' => 1, + 'CHECK_EXT_COMPRESSION_LIB' => 1, + 'AC_CHECK_HEADERS' => 1, + 'AC_FUNC_STRTOD' => 1, + 'AM_MISSING_PROG' => 1, + 'AC_FUNC_STRNLEN' => 1, + 'm4_sinclude' => 1, + 'AC_PROG_CXX' => 1, + 'AC_PATH_X' => 1, + 'AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK' => 1, + 'AM_PROG_INSTALL_STRIP' => 1, + '_PKG_SHORT_ERRORS_SUPPORTED' => 1, + 'AC_PROG_AWK' => 1, + '_m4_warn' => 1, + 'AC_HEADER_STDC' => 1, + 'AC_HEADER_MAJOR' => 1, + 'AM_SANITY_CHECK' => 1, + 'PKG_CHECK_EXISTS' => 1, + '_AM_PROG_TAR' => 1, + 'AC_FUNC_ERROR_AT_LINE' => 1, + 'AC_PROG_GCC_TRADITIONAL' => 1, + 'AM_DEP_TRACK' => 1, + 'AC_LIBSOURCE' => 1, + 'AC_FUNC_MBRTOWC' => 1, + 'AC_STRUCT_ST_BLOCKS' => 1, + 'AC_TYPE_SIGNAL' => 1, + '_AM_IF_OPTION' => 1, + 'AC_TYPE_UID_T' => 1, + 'AC_PROG_MAKE_SET' => 1, + 'AC_CONFIG_AUX_DIR' => 1, + 'm4_pattern_allow' => 1, + 'sinclude' => 1, + 'AM_SET_LEADING_DOT' => 1, + 'AC_DEFINE_TRACE_LITERAL' => 1, + '_AM_DEPENDENCIES' => 1, + 'AC_FUNC_STRERROR_R' => 1, + 'AC_PROG_CC' => 1, + 'AC_DECL_SYS_SIGLIST' => 1, + 'AC_FUNC_FORK' => 1, + 'PKG_CHECK_MODULES' => 1, + 'AU_DEFUN' => 1, + 'AC_FUNC_STRCOLL' => 1, + 'AC_FUNC_VPRINTF' => 1, + 'AC_PROG_YACC' => 1, + 'AC_INIT' => 1, + 'AC_STRUCT_TIMEZONE' => 1, + 'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1, + 'AC_FUNC_CHOWN' => 1, + 'AC_FUNC_ALLOCA' => 1, + 'AC_SUBST' => 1, + '_AM_SET_OPTION' => 1, + 'AC_FUNC_GETPGRP' => 1, + 'AC_CANONICAL_HOST' => 1, + 'AC_PROG_RANLIB' => 1, + 'AM_INIT_AUTOMAKE' => 1, + 'AC_FUNC_SETPGRP' => 1, + 'AC_CONFIG_SUBDIRS' => 1, + 'AC_FUNC_MMAP' => 1, + 'AC_FUNC_REALLOC' => 1, + 'AC_TYPE_SIZE_T' => 1, + 'AC_CHECK_TYPES' => 1, + 'AC_CONFIG_LINKS' => 1, + 'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1, + 'AC_CHECK_MEMBERS' => 1, + 'AM_MAINTAINER_MODE' => 1, + 'AC_DEFUN_ONCE' => 1, + 'AC_FUNC_UTIME_NULL' => 1, + 'AC_FUNC_SELECT_ARGTYPES' => 1, + 'AC_FUNC_STRFTIME' => 1, + 'AC_HEADER_STAT' => 1, + 'AC_C_INLINE' => 1, + 'AC_PROG_CPP' => 1, + 'AC_C_CONST' => 1, + 'AC_PROG_LEX' => 1, + 'AC_TYPE_PID_T' => 1, + 'AC_CONFIG_FILES' => 1, + 'include' => 1, + 'AC_FUNC_SETVBUF_REVERSED' => 1, + 'AM_AUX_DIR_EXPAND' => 1, + 'AC_PROG_INSTALL' => 1, + 'AM_GNU_GETTEXT' => 1, + 'AC_CHECK_LIB' => 1, + 'AC_FUNC_OBSTACK' => 1, + 'AC_FUNC_MALLOC' => 1, + '_AM_SET_OPTIONS' => 1, + 'AC_FUNC_GETGROUPS' => 1, + '_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1, + 'AM_RUN_LOG' => 1, + 'AC_FUNC_GETLOADAVG' => 1, + 'AH_OUTPUT' => 1, + 'AC_FUNC_FSEEKO' => 1, + 'AM_PROG_CC_C_O' => 1, + '_AM_MANGLE_OPTION' => 1, + 'AC_FUNC_MKTIME' => 1, + 'AM_CONDITIONAL' => 1, + 'AC_CANONICAL_SYSTEM' => 1, + 'AC_CONFIG_HEADERS' => 1, + 'AM_SET_DEPDIR' => 1, + 'AC_HEADER_SYS_WAIT' => 1, + 'AC_FUNC_MEMCMP' => 1, + 'AC_PROG_LN_S' => 1, + 'PKG_PROG_PKG_CONFIG' => 1, + 'AM_PROG_INSTALL_SH' => 1, + 'm4_include' => 1, + 'GTEST_LIB_CHECK' => 1, + 'AC_HEADER_DIRENT' => 1, + 'AC_CHECK_FUNCS' => 1, + '_AC_AM_CONFIG_HEADER_HOOK' => 1, + 'AM_MAKE_INCLUDE' => 1 + } + ], 'Autom4te::Request' ), + bless( [ + '1', + 1, + [ + '/usr/share/autoconf' + ], + [ + '/usr/share/autoconf/autoconf/autoconf.m4f', + 'aclocal.m4', + 'configure.ac' + ], + { + '_LT_AC_TAGCONFIG' => 1, + 'm4_pattern_forbid' => 1, + 'AC_CANONICAL_TARGET' => 1, + 'AC_CONFIG_LIBOBJ_DIR' => 1, + 'AC_TYPE_OFF_T' => 1, + 'AC_C_VOLATILE' => 1, + 'AC_FUNC_CLOSEDIR_VOID' => 1, + 'AC_REPLACE_FNMATCH' => 1, + 'AC_PROG_LIBTOOL' => 1, + 'AC_FUNC_STAT' => 1, + 'AC_HEADER_TIME' => 1, + 'AC_FUNC_WAIT3' => 1, + 'AM_AUTOMAKE_VERSION' => 1, + 'AC_STRUCT_TM' => 1, + 'AC_FUNC_LSTAT' => 1, + 'AC_TYPE_MODE_T' => 1, + 'AC_FUNC_GETMNTENT' => 1, + 'AC_CHECK_HEADERS' => 1, + 'AC_FUNC_STRTOD' => 1, + 'AC_FUNC_STRNLEN' => 1, + 'm4_sinclude' => 1, + 'AC_PROG_CXX' => 1, + 'AC_PATH_X' => 1, + 'AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK' => 1, + 'AC_PROG_AWK' => 1, + '_m4_warn' => 1, + 'AC_HEADER_STDC' => 1, + 'AC_HEADER_MAJOR' => 1, + 'AC_FUNC_ERROR_AT_LINE' => 1, + 'AC_PROG_GCC_TRADITIONAL' => 1, + 'AC_LIBSOURCE' => 1, + 'AC_FUNC_MBRTOWC' => 1, + 'AC_STRUCT_ST_BLOCKS' => 1, + 'AC_TYPE_SIGNAL' => 1, + 'AC_CANONICAL_BUILD' => 1, + 'AC_TYPE_UID_T' => 1, + 'AC_CONFIG_AUX_DIR' => 1, + 'AC_PROG_MAKE_SET' => 1, + 'sinclude' => 1, + 'm4_pattern_allow' => 1, + 'AC_DEFINE_TRACE_LITERAL' => 1, + 'AC_FUNC_STRERROR_R' => 1, + 'AC_PROG_CC' => 1, + 'AC_DECL_SYS_SIGLIST' => 1, + 'AC_FUNC_FORK' => 1, + 'AC_FUNC_VPRINTF' => 1, + 'AC_FUNC_STRCOLL' => 1, + 'AC_PROG_YACC' => 1, + 'AC_INIT' => 1, + 'AC_STRUCT_TIMEZONE' => 1, + 'AC_FUNC_CHOWN' => 1, + 'AC_SUBST' => 1, + 'AC_FUNC_ALLOCA' => 1, + 'AC_CANONICAL_HOST' => 1, + 'AC_FUNC_GETPGRP' => 1, + 'AC_PROG_RANLIB' => 1, + 'AM_INIT_AUTOMAKE' => 1, + 'AC_FUNC_SETPGRP' => 1, + 'AC_CONFIG_SUBDIRS' => 1, + 'AC_FUNC_MMAP' => 1, + 'AC_FUNC_REALLOC' => 1, + 'AC_TYPE_SIZE_T' => 1, + 'AC_CONFIG_LINKS' => 1, + 'AC_CHECK_TYPES' => 1, + 'LT_SUPPORTED_TAG' => 1, + 'AC_CHECK_MEMBERS' => 1, + 'AM_MAINTAINER_MODE' => 1, + 'AC_FUNC_UTIME_NULL' => 1, + 'AC_FUNC_SELECT_ARGTYPES' => 1, + 'AC_FUNC_STRFTIME' => 1, + 'AC_HEADER_STAT' => 1, + 'AC_C_INLINE' => 1, + 'AC_PROG_CPP' => 1, + 'AC_TYPE_PID_T' => 1, + 'AC_C_CONST' => 1, + 'AC_PROG_LEX' => 1, + 'AM_ENABLE_MULTILIB' => 1, + 'AC_CONFIG_FILES' => 1, + 'include' => 1, + 'AC_FUNC_SETVBUF_REVERSED' => 1, + 'AC_PROG_INSTALL' => 1, + 'AM_GNU_GETTEXT' => 1, + 'AC_CHECK_LIB' => 1, + 'AC_FUNC_OBSTACK' => 1, + 'AC_FUNC_MALLOC' => 1, + 'AC_FUNC_GETGROUPS' => 1, + 'AC_FUNC_GETLOADAVG' => 1, + 'AH_OUTPUT' => 1, + 'AC_FUNC_FSEEKO' => 1, + 'AM_PROG_CC_C_O' => 1, + 'AM_CONDITIONAL' => 1, + 'AC_CANONICAL_SYSTEM' => 1, + 'AC_FUNC_MKTIME' => 1, + 'AC_CONFIG_HEADERS' => 1, + 'AC_HEADER_SYS_WAIT' => 1, + 'AC_FUNC_MEMCMP' => 1, + 'AC_PROG_LN_S' => 1, + 'm4_include' => 1, + 'AC_HEADER_DIRENT' => 1, + 'AC_CHECK_FUNCS' => 1 + } + ], 'Autom4te::Request' ) + ); + diff --git a/snappy/snappy-1.0.5/autom4te.cache/traces.0 b/snappy/snappy-1.0.5/autom4te.cache/traces.0 new file mode 100644 index 00000000..f53a76a1 --- /dev/null +++ b/snappy/snappy-1.0.5/autom4te.cache/traces.0 @@ -0,0 +1,949 @@ +m4trace:/usr/share/aclocal/pkg.m4:44: -1- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi + +fi[]dnl +]) +m4trace:/usr/share/aclocal/pkg.m4:63: -1- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_ifval([$2], [$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) +m4trace:/usr/share/aclocal/pkg.m4:91: -1- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +]) +m4trace:/usr/share/aclocal/pkg.m4:157: -1- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + ifelse([$4], , [AC_MSG_ERROR(dnl +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT +])], + [AC_MSG_RESULT([no]) + $4]) +elif test $pkg_failed = untried; then + ifelse([$4], , [AC_MSG_FAILURE(dnl +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])], + [$4]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + ifelse([$3], , :, [$3]) +fi[]dnl +]) +m4trace:/usr/share/aclocal-1.9/amversion.m4:13: -1- AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"]) +m4trace:/usr/share/aclocal-1.9/amversion.m4:20: -1- AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.9.6])]) +m4trace:/usr/share/aclocal-1.9/auxdir.m4:52: -1- AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) +m4trace:/usr/share/aclocal-1.9/cond.m4:32: -1- AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ(2.52)dnl + ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE]) +AC_SUBST([$1_FALSE]) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) +m4trace:/usr/share/aclocal-1.9/depend.m4:131: -1- AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) +m4trace:/usr/share/aclocal-1.9/depend.m4:141: -1- AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) +m4trace:/usr/share/aclocal-1.9/depend.m4:156: -1- AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH]) +]) +m4trace:/usr/share/aclocal-1.9/depout.m4:53: -1- AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done +]) +m4trace:/usr/share/aclocal-1.9/depout.m4:67: -1- AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) +m4trace:/usr/share/aclocal-1.9/init.m4:92: -1- AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.58])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +# test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AM_PROG_INSTALL_SH +AM_PROG_INSTALL_STRIP +AC_REQUIRE([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +]) +]) +m4trace:/usr/share/aclocal-1.9/init.m4:113: -1- AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $1 | $1:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) +m4trace:/usr/share/aclocal-1.9/install-sh.m4:14: -1- AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +install_sh=${install_sh-"$am_aux_dir/install-sh"} +AC_SUBST(install_sh)]) +m4trace:/usr/share/aclocal-1.9/lead-dot.m4:21: -1- AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) +m4trace:/usr/share/aclocal-1.9/make.m4:51: -1- AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo done +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) +m4trace:/usr/share/aclocal-1.9/missing.m4:17: -1- AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) +m4trace:/usr/share/aclocal-1.9/missing.m4:34: -1- AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) +m4trace:/usr/share/aclocal-1.9/mkdirp.m4:63: -1- AC_DEFUN([AM_PROG_MKDIR_P], [if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + # We used to keeping the `.' as first argument, in order to + # allow $(mkdir_p) to be used without argument. As in + # $(mkdir_p) $(somedir) + # where $(somedir) is conditionally defined. However this is wrong + # for two reasons: + # 1. if the package is installed by a user who cannot write `.' + # make install will fail, + # 2. the above comment should most certainly read + # $(mkdir_p) $(DESTDIR)$(somedir) + # so it does not work when $(somedir) is undefined and + # $(DESTDIR) is not. + # To support the latter case, we have to write + # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), + # so the `.' trick is pointless. + mkdir_p='mkdir -p --' +else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + for d in ./-p ./--version; + do + test -d $d && rmdir $d + done + # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. + if test -f "$ac_aux_dir/mkinstalldirs"; then + mkdir_p='$(mkinstalldirs)' + else + mkdir_p='$(install_sh) -d' + fi +fi +AC_SUBST([mkdir_p])]) +m4trace:/usr/share/aclocal-1.9/options.m4:14: -1- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) +m4trace:/usr/share/aclocal-1.9/options.m4:20: -1- AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), 1)]) +m4trace:/usr/share/aclocal-1.9/options.m4:26: -1- AC_DEFUN([_AM_SET_OPTIONS], [AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) +m4trace:/usr/share/aclocal-1.9/options.m4:32: -1- AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) +m4trace:/usr/share/aclocal-1.9/runlog.m4:17: -1- AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) +m4trace:/usr/share/aclocal-1.9/sanity.m4:51: -1- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) +m4trace:/usr/share/aclocal-1.9/strip.m4:28: -1- AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) +m4trace:/usr/share/aclocal-1.9/tar.m4:95: -1- AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. +AM_MISSING_PROG([AMTAR], [tar]) +m4_if([$1], [v7], + [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of `-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) +m4trace:m4/gtest.m4:74: -1- AC_DEFUN([GTEST_LIB_CHECK], [ +dnl Provide a flag to enable or disable Google Test usage. +AC_ARG_ENABLE([gtest], + [AS_HELP_STRING([--enable-gtest], + [Enable tests using the Google C++ Testing Framework. + (Default is enabled.)])], + [], + [enable_gtest=]) +AC_ARG_VAR([GTEST_CONFIG], + [The exact path of Google Test's 'gtest-config' script.]) +AC_ARG_VAR([GTEST_CPPFLAGS], + [C-like preprocessor flags for Google Test.]) +AC_ARG_VAR([GTEST_CXXFLAGS], + [C++ compile flags for Google Test.]) +AC_ARG_VAR([GTEST_LDFLAGS], + [Linker path and option flags for Google Test.]) +AC_ARG_VAR([GTEST_LIBS], + [Library linking flags for Google Test.]) +AC_ARG_VAR([GTEST_VERSION], + [The version of Google Test available.]) +HAVE_GTEST="no" +AS_IF([test "x${enable_gtest}" != "xno"], + [AC_MSG_CHECKING([for 'gtest-config']) + AS_IF([test "x${enable_gtest}" = "xyes"], + [AS_IF([test -x "${enable_gtest}/scripts/gtest-config"], + [GTEST_CONFIG="${enable_gtest}/scripts/gtest-config"], + [GTEST_CONFIG="${enable_gtest}/bin/gtest-config"]) + AS_IF([test -x "${GTEST_CONFIG}"], [], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([dnl +Unable to locate either a built or installed Google Test. +The specific location '${enable_gtest}' was provided for a built or installed +Google Test, but no 'gtest-config' script could be found at this location.]) + ])], + [AC_PATH_PROG([GTEST_CONFIG], [gtest-config])]) + AS_IF([test -x "${GTEST_CONFIG}"], + [AC_MSG_RESULT([${GTEST_CONFIG}]) + m4_ifval([$1], + [_gtest_min_version="--min-version=$1" + AC_MSG_CHECKING([for Google Test at least version >= $1])], + [_gtest_min_version="--min-version=0" + AC_MSG_CHECKING([for Google Test])]) + AS_IF([${GTEST_CONFIG} ${_gtest_min_version}], + [AC_MSG_RESULT([yes]) + HAVE_GTEST='yes'], + [AC_MSG_RESULT([no])])], + [AC_MSG_RESULT([no])]) + AS_IF([test "x${HAVE_GTEST}" = "xyes"], + [GTEST_CPPFLAGS=`${GTEST_CONFIG} --cppflags` + GTEST_CXXFLAGS=`${GTEST_CONFIG} --cxxflags` + GTEST_LDFLAGS=`${GTEST_CONFIG} --ldflags` + GTEST_LIBS=`${GTEST_CONFIG} --libs` + GTEST_VERSION=`${GTEST_CONFIG} --version` + AC_DEFINE([HAVE_GTEST],[1],[Defined when Google Test is available.])], + [AS_IF([test "x${enable_gtest}" = "xyes"], + [AC_MSG_ERROR([dnl +Google Test was enabled, but no viable version could be found.]) + ])])]) +AC_SUBST([HAVE_GTEST]) +AM_CONDITIONAL([HAVE_GTEST],[test "x$HAVE_GTEST" = "xyes"]) +AS_IF([test "x$HAVE_GTEST" = "xyes"], + [m4_ifval([$2], [$2])], + [m4_ifval([$3], [$3])]) +]) +m4trace:configure.ac:10: -1- AC_INIT([snappy], [snappy_major.snappy_minor.snappy_patchlevel]) +m4trace:configure.ac:10: -1- m4_pattern_forbid([^_?A[CHUM]_]) +m4trace:configure.ac:10: -1- m4_pattern_forbid([_AC_]) +m4trace:configure.ac:10: -1- m4_pattern_forbid([^LIBOBJS$], [do not use LIBOBJS directly, use AC_LIBOBJ (see section `AC_LIBOBJ vs LIBOBJS']) +m4trace:configure.ac:10: -1- m4_pattern_allow([^AS_FLAGS$]) +m4trace:configure.ac:10: -1- m4_pattern_forbid([^_?m4_]) +m4trace:configure.ac:10: -1- m4_pattern_forbid([^dnl$]) +m4trace:configure.ac:10: -1- m4_pattern_forbid([^_?AS_]) +m4trace:configure.ac:10: -1- AC_SUBST([SHELL], [${CONFIG_SHELL-/bin/sh}]) +m4trace:configure.ac:10: -1- AC_SUBST([PATH_SEPARATOR]) +m4trace:configure.ac:10: -1- AC_SUBST([PACKAGE_NAME], [m4_ifdef([AC_PACKAGE_NAME], ['AC_PACKAGE_NAME'])]) +m4trace:configure.ac:10: -1- AC_SUBST([PACKAGE_TARNAME], [m4_ifdef([AC_PACKAGE_TARNAME], ['AC_PACKAGE_TARNAME'])]) +m4trace:configure.ac:10: -1- AC_SUBST([PACKAGE_VERSION], [m4_ifdef([AC_PACKAGE_VERSION], ['AC_PACKAGE_VERSION'])]) +m4trace:configure.ac:10: -1- AC_SUBST([PACKAGE_STRING], [m4_ifdef([AC_PACKAGE_STRING], ['AC_PACKAGE_STRING'])]) +m4trace:configure.ac:10: -1- AC_SUBST([PACKAGE_BUGREPORT], [m4_ifdef([AC_PACKAGE_BUGREPORT], ['AC_PACKAGE_BUGREPORT'])]) +m4trace:configure.ac:10: -1- AC_SUBST([exec_prefix], [NONE]) +m4trace:configure.ac:10: -1- AC_SUBST([prefix], [NONE]) +m4trace:configure.ac:10: -1- AC_SUBST([program_transform_name], [s,x,x,]) +m4trace:configure.ac:10: -1- AC_SUBST([bindir], ['${exec_prefix}/bin']) +m4trace:configure.ac:10: -1- AC_SUBST([sbindir], ['${exec_prefix}/sbin']) +m4trace:configure.ac:10: -1- AC_SUBST([libexecdir], ['${exec_prefix}/libexec']) +m4trace:configure.ac:10: -1- AC_SUBST([datadir], ['${prefix}/share']) +m4trace:configure.ac:10: -1- AC_SUBST([sysconfdir], ['${prefix}/etc']) +m4trace:configure.ac:10: -1- AC_SUBST([sharedstatedir], ['${prefix}/com']) +m4trace:configure.ac:10: -1- AC_SUBST([localstatedir], ['${prefix}/var']) +m4trace:configure.ac:10: -1- AC_SUBST([libdir], ['${exec_prefix}/lib']) +m4trace:configure.ac:10: -1- AC_SUBST([includedir], ['${prefix}/include']) +m4trace:configure.ac:10: -1- AC_SUBST([oldincludedir], ['/usr/include']) +m4trace:configure.ac:10: -1- AC_SUBST([infodir], ['${prefix}/info']) +m4trace:configure.ac:10: -1- AC_SUBST([mandir], ['${prefix}/man']) +m4trace:configure.ac:10: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_NAME]) +m4trace:configure.ac:10: -1- AH_OUTPUT([PACKAGE_NAME], [/* Define to the full name of this package. */ +#undef PACKAGE_NAME]) +m4trace:configure.ac:10: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_TARNAME]) +m4trace:configure.ac:10: -1- AH_OUTPUT([PACKAGE_TARNAME], [/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME]) +m4trace:configure.ac:10: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_VERSION]) +m4trace:configure.ac:10: -1- AH_OUTPUT([PACKAGE_VERSION], [/* Define to the version of this package. */ +#undef PACKAGE_VERSION]) +m4trace:configure.ac:10: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_STRING]) +m4trace:configure.ac:10: -1- AH_OUTPUT([PACKAGE_STRING], [/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING]) +m4trace:configure.ac:10: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_BUGREPORT]) +m4trace:configure.ac:10: -1- AH_OUTPUT([PACKAGE_BUGREPORT], [/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT]) +m4trace:configure.ac:10: -1- AC_SUBST([build_alias]) +m4trace:configure.ac:10: -1- AC_SUBST([host_alias]) +m4trace:configure.ac:10: -1- AC_SUBST([target_alias]) +m4trace:configure.ac:10: -1- AC_SUBST([DEFS]) +m4trace:configure.ac:10: -1- AC_SUBST([ECHO_C]) +m4trace:configure.ac:10: -1- AC_SUBST([ECHO_N]) +m4trace:configure.ac:10: -1- AC_SUBST([ECHO_T]) +m4trace:configure.ac:10: -1- AC_SUBST([LIBS]) +m4trace:configure.ac:14: -1- AM_INIT_AUTOMAKE([-Wall -Werror]) +m4trace:configure.ac:14: -1- m4_pattern_allow([^AM_[A-Z]+FLAGS$]) +m4trace:configure.ac:14: -1- AM_SET_CURRENT_AUTOMAKE_VERSION +m4trace:configure.ac:14: -1- AM_AUTOMAKE_VERSION([1.9.6]) +m4trace:configure.ac:14: -1- AC_PROG_INSTALL +m4trace:configure.ac:14: -1- AC_SUBST([INSTALL_PROGRAM]) +m4trace:configure.ac:14: -1- AC_SUBST([INSTALL_SCRIPT]) +m4trace:configure.ac:14: -1- AC_SUBST([INSTALL_DATA]) +m4trace:configure.ac:14: -1- AC_SUBST([CYGPATH_W]) +m4trace:configure.ac:14: -1- _AM_SET_OPTIONS([-Wall -Werror]) +m4trace:configure.ac:14: -1- _AM_SET_OPTION([-Wall]) +m4trace:configure.ac:14: -2- _AM_MANGLE_OPTION([-Wall]) +m4trace:configure.ac:14: -1- _AM_SET_OPTION([-Werror]) +m4trace:configure.ac:14: -2- _AM_MANGLE_OPTION([-Werror]) +m4trace:configure.ac:14: -1- AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME']) +m4trace:configure.ac:14: -1- AC_SUBST([VERSION], ['AC_PACKAGE_VERSION']) +m4trace:configure.ac:14: -1- _AM_IF_OPTION([no-define], [], [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])]) +m4trace:configure.ac:14: -2- _AM_MANGLE_OPTION([no-define]) +m4trace:configure.ac:14: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE]) +m4trace:configure.ac:14: -1- AH_OUTPUT([PACKAGE], [/* Name of package */ +#undef PACKAGE]) +m4trace:configure.ac:14: -1- AC_DEFINE_TRACE_LITERAL([VERSION]) +m4trace:configure.ac:14: -1- AH_OUTPUT([VERSION], [/* Version number of package */ +#undef VERSION]) +m4trace:configure.ac:14: -1- AM_SANITY_CHECK +m4trace:configure.ac:14: -1- AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +m4trace:configure.ac:14: -1- AM_MISSING_HAS_RUN +m4trace:configure.ac:14: -1- AM_AUX_DIR_EXPAND +m4trace:configure.ac:14: -1- AC_SUBST([ACLOCAL]) +m4trace:configure.ac:14: -1- AM_MISSING_PROG([AUTOCONF], [autoconf]) +m4trace:configure.ac:14: -1- AC_SUBST([AUTOCONF]) +m4trace:configure.ac:14: -1- AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +m4trace:configure.ac:14: -1- AC_SUBST([AUTOMAKE]) +m4trace:configure.ac:14: -1- AM_MISSING_PROG([AUTOHEADER], [autoheader]) +m4trace:configure.ac:14: -1- AC_SUBST([AUTOHEADER]) +m4trace:configure.ac:14: -1- AM_MISSING_PROG([MAKEINFO], [makeinfo]) +m4trace:configure.ac:14: -1- AC_SUBST([MAKEINFO]) +m4trace:configure.ac:14: -1- AM_PROG_INSTALL_SH +m4trace:configure.ac:14: -1- AC_SUBST([install_sh]) +m4trace:configure.ac:14: -1- AM_PROG_INSTALL_STRIP +m4trace:configure.ac:14: -1- AC_SUBST([STRIP]) +m4trace:configure.ac:14: -1- AC_SUBST([ac_ct_STRIP]) +m4trace:configure.ac:14: -1- AC_SUBST([INSTALL_STRIP_PROGRAM]) +m4trace:configure.ac:14: -1- AM_PROG_MKDIR_P +m4trace:configure.ac:14: -1- AC_SUBST([mkdir_p]) +m4trace:configure.ac:14: -1- AC_PROG_AWK +m4trace:configure.ac:14: -1- AC_SUBST([AWK]) +m4trace:configure.ac:14: -1- AC_PROG_MAKE_SET +m4trace:configure.ac:14: -1- AC_SUBST([SET_MAKE]) +m4trace:configure.ac:14: -1- AM_SET_LEADING_DOT +m4trace:configure.ac:14: -1- AC_SUBST([am__leading_dot]) +m4trace:configure.ac:14: -1- _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +m4trace:configure.ac:14: -2- _AM_MANGLE_OPTION([tar-ustar]) +m4trace:configure.ac:14: -1- _AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])]) +m4trace:configure.ac:14: -2- _AM_MANGLE_OPTION([tar-pax]) +m4trace:configure.ac:14: -1- _AM_PROG_TAR([v7]) +m4trace:configure.ac:14: -1- AM_MISSING_PROG([AMTAR], [tar]) +m4trace:configure.ac:14: -1- AC_SUBST([AMTAR]) +m4trace:configure.ac:14: -1- AC_SUBST([am__tar]) +m4trace:configure.ac:14: -1- AC_SUBST([am__untar]) +m4trace:configure.ac:14: -1- _AM_IF_OPTION([no-dependencies], [], [AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +]) +m4trace:configure.ac:14: -2- _AM_MANGLE_OPTION([no-dependencies]) +m4trace:configure.ac:17: -1- AC_SUBST([LIBTOOL_DEPS]) +m4trace:configure.ac:18: -1- AC_PROG_CXX +m4trace:configure.ac:18: -1- AC_SUBST([CXX]) +m4trace:configure.ac:18: -1- AC_SUBST([CXXFLAGS]) +m4trace:configure.ac:18: -1- AC_SUBST([LDFLAGS]) +m4trace:configure.ac:18: -1- AC_SUBST([CPPFLAGS]) +m4trace:configure.ac:18: -1- AC_SUBST([CXX]) +m4trace:configure.ac:18: -1- AC_SUBST([ac_ct_CXX]) +m4trace:configure.ac:18: -1- AC_SUBST([EXEEXT], [$ac_cv_exeext]) +m4trace:configure.ac:18: -1- AC_SUBST([OBJEXT], [$ac_cv_objext]) +m4trace:configure.ac:18: -1- _AM_DEPENDENCIES([CXX]) +m4trace:configure.ac:18: -1- AM_SET_DEPDIR +m4trace:configure.ac:18: -1- AC_SUBST([DEPDIR], ["${am__leading_dot}deps"]) +m4trace:configure.ac:18: -1- AM_OUTPUT_DEPENDENCY_COMMANDS +m4trace:configure.ac:18: -1- AM_MAKE_INCLUDE +m4trace:configure.ac:18: -1- AC_SUBST([am__include]) +m4trace:configure.ac:18: -1- AC_SUBST([am__quote]) +m4trace:configure.ac:18: -1- AM_DEP_TRACK +m4trace:configure.ac:18: -1- AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +m4trace:configure.ac:18: -1- AC_SUBST([AMDEP_TRUE]) +m4trace:configure.ac:18: -1- AC_SUBST([AMDEP_FALSE]) +m4trace:configure.ac:18: -1- AC_SUBST([AMDEPBACKSLASH]) +m4trace:configure.ac:18: -1- AC_SUBST([CXXDEPMODE], [depmode=$am_cv_CXX_dependencies_compiler_type]) +m4trace:configure.ac:18: -1- AM_CONDITIONAL([am__fastdepCXX], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3]) +m4trace:configure.ac:18: -1- AC_SUBST([am__fastdepCXX_TRUE]) +m4trace:configure.ac:18: -1- AC_SUBST([am__fastdepCXX_FALSE]) +m4trace:configure.ac:20: -1- AC_DEFINE_TRACE_LITERAL([WORDS_BIGENDIAN]) +m4trace:configure.ac:20: -1- AH_OUTPUT([WORDS_BIGENDIAN], [/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN]) +m4trace:configure.ac:21: -1- AC_CHECK_HEADERS([stdint.h stddef.h sys/mman.h sys/resource.h windows.h byteswap.h sys/byteswap.h sys/endian.h]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STDINT_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STDDEF_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_STDDEF_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_SYS_MMAN_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MMAN_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_SYS_RESOURCE_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_WINDOWS_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_WINDOWS_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_BYTESWAP_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_BYTESWAP_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_SYS_BYTESWAP_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_BYTESWAP_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_SYS_ENDIAN_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_ENDIAN_H]) +m4trace:configure.ac:21: -1- AC_HEADER_STDC +m4trace:configure.ac:21: -1- AC_SUBST([CXXCPP]) +m4trace:configure.ac:21: -1- AC_SUBST([CPPFLAGS]) +m4trace:configure.ac:21: -1- AC_SUBST([CXXCPP]) +m4trace:configure.ac:21: -1- AC_SUBST([EGREP]) +m4trace:configure.ac:21: -1- AC_DEFINE_TRACE_LITERAL([STDC_HEADERS]) +m4trace:configure.ac:21: -1- AH_OUTPUT([STDC_HEADERS], [/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS]) +m4trace:configure.ac:21: -1- AC_CHECK_HEADERS([sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h], [], [], [$ac_includes_default]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_SYS_TYPES_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_SYS_STAT_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STRING_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_MEMORY_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STRINGS_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_INTTYPES_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STDINT_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H]) +m4trace:configure.ac:27: -1- GTEST_LIB_CHECK([], [true], [true # Ignore; we can live without it.]) +m4trace:configure.ac:27: -1- AC_SUBST([GTEST_CONFIG]) +m4trace:configure.ac:27: -1- AC_SUBST([GTEST_CPPFLAGS]) +m4trace:configure.ac:27: -1- AC_SUBST([GTEST_CXXFLAGS]) +m4trace:configure.ac:27: -1- AC_SUBST([GTEST_LDFLAGS]) +m4trace:configure.ac:27: -1- AC_SUBST([GTEST_LIBS]) +m4trace:configure.ac:27: -1- AC_SUBST([GTEST_VERSION]) +m4trace:configure.ac:27: -1- AC_SUBST([GTEST_CONFIG], [$ac_cv_path_GTEST_CONFIG]) +m4trace:configure.ac:27: -1- AC_DEFINE_TRACE_LITERAL([HAVE_GTEST]) +m4trace:configure.ac:27: -1- AH_OUTPUT([HAVE_GTEST], [/* Defined when Google Test is available. */ +#undef HAVE_GTEST]) +m4trace:configure.ac:27: -1- AC_SUBST([HAVE_GTEST]) +m4trace:configure.ac:27: -1- AM_CONDITIONAL([HAVE_GTEST], [test "x$HAVE_GTEST" = "xyes"]) +m4trace:configure.ac:27: -1- AC_SUBST([HAVE_GTEST_TRUE]) +m4trace:configure.ac:27: -1- AC_SUBST([HAVE_GTEST_FALSE]) +m4trace:configure.ac:43: -1- PKG_CHECK_MODULES([gflags], [libgflags], [AC_DEFINE([HAVE_GFLAGS], [1], [Use the gflags package for command-line parsing.])], [if test "x$with_gflags" != "xcheck"; then + AC_MSG_FAILURE([--with-gflags was given, but test for gflags failed]) + fi]) +m4trace:configure.ac:43: -1- PKG_PROG_PKG_CONFIG +m4trace:configure.ac:43: -1- m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4trace:configure.ac:43: -1- m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) +m4trace:configure.ac:43: -1- AC_SUBST([PKG_CONFIG]) +m4trace:configure.ac:43: -1- AC_SUBST([PKG_CONFIG], [$ac_cv_path_PKG_CONFIG]) +m4trace:configure.ac:43: -1- AC_SUBST([ac_pt_PKG_CONFIG], [$ac_cv_path_ac_pt_PKG_CONFIG]) +m4trace:configure.ac:43: -1- AC_SUBST([gflags_CFLAGS]) +m4trace:configure.ac:43: -1- AC_SUBST([gflags_LIBS]) +m4trace:configure.ac:43: -1- PKG_CHECK_EXISTS([libgflags], [pkg_cv_[]gflags_CFLAGS=`$PKG_CONFIG --[]cflags "libgflags" 2>/dev/null`], [pkg_failed=yes]) +m4trace:configure.ac:43: -1- PKG_CHECK_EXISTS([libgflags], [pkg_cv_[]gflags_LIBS=`$PKG_CONFIG --[]libs "libgflags" 2>/dev/null`], [pkg_failed=yes]) +m4trace:configure.ac:43: -1- _PKG_SHORT_ERRORS_SUPPORTED +m4trace:configure.ac:43: -1- AC_DEFINE_TRACE_LITERAL([HAVE_GFLAGS]) +m4trace:configure.ac:43: -1- AH_OUTPUT([HAVE_GFLAGS], [/* Use the gflags package for command-line parsing. */ +#undef HAVE_GFLAGS]) +m4trace:configure.ac:58: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete. +You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from... +configure.ac:58: the top level]) +m4trace:configure.ac:60: -1- AC_DEFINE_TRACE_LITERAL([HAVE_BUILTIN_EXPECT]) +m4trace:configure.ac:60: -1- AH_OUTPUT([HAVE_BUILTIN_EXPECT], [/* Define to 1 if the compiler supports __builtin_expect. */ +#undef HAVE_BUILTIN_EXPECT]) +m4trace:configure.ac:75: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete. +You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from... +configure.ac:75: the top level]) +m4trace:configure.ac:77: -1- AC_DEFINE_TRACE_LITERAL([HAVE_BUILTIN_CTZ]) +m4trace:configure.ac:77: -1- AH_OUTPUT([HAVE_BUILTIN_CTZ], [/* Define to 1 if the compiler supports __builtin_ctz and friends. */ +#undef HAVE_BUILTIN_CTZ]) +m4trace:configure.ac:94: -1- AC_DEFUN([CHECK_EXT_COMPRESSION_LIB], [ + AH_CHECK_LIB([$1]) + AC_CHECK_LIB( + [$1], + [$2], + [ + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIB$1)) + UNITTEST_LIBS="-l$1 $UNITTEST_LIBS" + ], + [true] + ) +]) +m4trace:configure.ac:95: -1- CHECK_EXT_COMPRESSION_LIB([z], [zlibVersion]) +m4trace:configure.ac:95: -1- AH_OUTPUT([HAVE_LIBZ], [/* Define to 1 if you have the `z\' library (-lz). */ +#undef HAVE_LIBZ]) +m4trace:configure.ac:95: -1- AC_CHECK_LIB([z], [zlibVersion], [ + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIBz)) + UNITTEST_LIBS="-lz $UNITTEST_LIBS" + ], [true + ]) +m4trace:configure.ac:95: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBZ]) +m4trace:configure.ac:96: -1- CHECK_EXT_COMPRESSION_LIB([lzo2], [lzo1x_1_15_compress]) +m4trace:configure.ac:96: -1- AH_OUTPUT([HAVE_LIBLZO2], [/* Define to 1 if you have the `lzo2\' library (-llzo2). */ +#undef HAVE_LIBLZO2]) +m4trace:configure.ac:96: -1- AC_CHECK_LIB([lzo2], [lzo1x_1_15_compress], [ + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIBlzo2)) + UNITTEST_LIBS="-llzo2 $UNITTEST_LIBS" + ], [true + ]) +m4trace:configure.ac:96: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBLZO2]) +m4trace:configure.ac:97: -1- CHECK_EXT_COMPRESSION_LIB([lzf], [lzf_compress]) +m4trace:configure.ac:97: -1- AH_OUTPUT([HAVE_LIBLZF], [/* Define to 1 if you have the `lzf\' library (-llzf). */ +#undef HAVE_LIBLZF]) +m4trace:configure.ac:97: -1- AC_CHECK_LIB([lzf], [lzf_compress], [ + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIBlzf)) + UNITTEST_LIBS="-llzf $UNITTEST_LIBS" + ], [true + ]) +m4trace:configure.ac:97: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBLZF]) +m4trace:configure.ac:98: -1- CHECK_EXT_COMPRESSION_LIB([fastlz], [fastlz_compress]) +m4trace:configure.ac:98: -1- AH_OUTPUT([HAVE_LIBFASTLZ], [/* Define to 1 if you have the `fastlz\' library (-lfastlz). */ +#undef HAVE_LIBFASTLZ]) +m4trace:configure.ac:98: -1- AC_CHECK_LIB([fastlz], [fastlz_compress], [ + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIBfastlz)) + UNITTEST_LIBS="-lfastlz $UNITTEST_LIBS" + ], [true + ]) +m4trace:configure.ac:98: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBFASTLZ]) +m4trace:configure.ac:99: -1- CHECK_EXT_COMPRESSION_LIB([quicklz], [qlz_compress]) +m4trace:configure.ac:99: -1- AH_OUTPUT([HAVE_LIBQUICKLZ], [/* Define to 1 if you have the `quicklz\' library (-lquicklz). */ +#undef HAVE_LIBQUICKLZ]) +m4trace:configure.ac:99: -1- AC_CHECK_LIB([quicklz], [qlz_compress], [ + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIBquicklz)) + UNITTEST_LIBS="-lquicklz $UNITTEST_LIBS" + ], [true + ]) +m4trace:configure.ac:99: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBQUICKLZ]) +m4trace:configure.ac:100: -1- AC_SUBST([UNITTEST_LIBS]) +m4trace:configure.ac:104: -1- AC_SUBST([ac_cv_have_stdint_h], [1]) +m4trace:configure.ac:106: -1- AC_SUBST([ac_cv_have_stdint_h], [0]) +m4trace:configure.ac:109: -1- AC_SUBST([ac_cv_have_stddef_h], [1]) +m4trace:configure.ac:111: -1- AC_SUBST([ac_cv_have_stddef_h], [0]) +m4trace:configure.ac:119: -1- AC_SUBST([SNAPPY_MAJOR]) +m4trace:configure.ac:120: -1- AC_SUBST([SNAPPY_MINOR]) +m4trace:configure.ac:121: -1- AC_SUBST([SNAPPY_PATCHLEVEL]) +m4trace:configure.ac:122: -1- AC_SUBST([SNAPPY_LTVERSION], [2:3:1]) +m4trace:configure.ac:124: -1- AC_CONFIG_HEADERS([config.h]) +m4trace:configure.ac:125: -1- AC_CONFIG_FILES([Makefile snappy-stubs-public.h]) +m4trace:configure.ac:126: -1- AC_SUBST([LIB@&t@OBJS], [$ac_libobjs]) +m4trace:configure.ac:126: -1- AC_SUBST([LTLIBOBJS], [$ac_ltlibobjs]) +m4trace:configure.ac:126: -1- _AC_AM_CONFIG_HEADER_HOOK([$ac_file]) +m4trace:configure.ac:126: -1- _AM_OUTPUT_DEPENDENCY_COMMANDS diff --git a/snappy/snappy-1.0.5/autom4te.cache/traces.1 b/snappy/snappy-1.0.5/autom4te.cache/traces.1 new file mode 100644 index 00000000..bbf44970 --- /dev/null +++ b/snappy/snappy-1.0.5/autom4te.cache/traces.1 @@ -0,0 +1,249 @@ +m4trace:aclocal.m4:1009: -1- m4_include([m4/gtest.m4]) +m4trace:configure.ac:10: -1- AC_INIT([snappy], [snappy_major.snappy_minor.snappy_patchlevel]) +m4trace:configure.ac:10: -1- m4_pattern_forbid([^_?A[CHUM]_]) +m4trace:configure.ac:10: -1- m4_pattern_forbid([_AC_]) +m4trace:configure.ac:10: -1- m4_pattern_forbid([^LIBOBJS$], [do not use LIBOBJS directly, use AC_LIBOBJ (see section `AC_LIBOBJ vs LIBOBJS']) +m4trace:configure.ac:10: -1- m4_pattern_allow([^AS_FLAGS$]) +m4trace:configure.ac:10: -1- m4_pattern_forbid([^_?m4_]) +m4trace:configure.ac:10: -1- m4_pattern_forbid([^dnl$]) +m4trace:configure.ac:10: -1- m4_pattern_forbid([^_?AS_]) +m4trace:configure.ac:10: -1- AC_SUBST([SHELL], [${CONFIG_SHELL-/bin/sh}]) +m4trace:configure.ac:10: -1- AC_SUBST([PATH_SEPARATOR]) +m4trace:configure.ac:10: -1- AC_SUBST([PACKAGE_NAME], [m4_ifdef([AC_PACKAGE_NAME], ['AC_PACKAGE_NAME'])]) +m4trace:configure.ac:10: -1- AC_SUBST([PACKAGE_TARNAME], [m4_ifdef([AC_PACKAGE_TARNAME], ['AC_PACKAGE_TARNAME'])]) +m4trace:configure.ac:10: -1- AC_SUBST([PACKAGE_VERSION], [m4_ifdef([AC_PACKAGE_VERSION], ['AC_PACKAGE_VERSION'])]) +m4trace:configure.ac:10: -1- AC_SUBST([PACKAGE_STRING], [m4_ifdef([AC_PACKAGE_STRING], ['AC_PACKAGE_STRING'])]) +m4trace:configure.ac:10: -1- AC_SUBST([PACKAGE_BUGREPORT], [m4_ifdef([AC_PACKAGE_BUGREPORT], ['AC_PACKAGE_BUGREPORT'])]) +m4trace:configure.ac:10: -1- AC_SUBST([exec_prefix], [NONE]) +m4trace:configure.ac:10: -1- AC_SUBST([prefix], [NONE]) +m4trace:configure.ac:10: -1- AC_SUBST([program_transform_name], [s,x,x,]) +m4trace:configure.ac:10: -1- AC_SUBST([bindir], ['${exec_prefix}/bin']) +m4trace:configure.ac:10: -1- AC_SUBST([sbindir], ['${exec_prefix}/sbin']) +m4trace:configure.ac:10: -1- AC_SUBST([libexecdir], ['${exec_prefix}/libexec']) +m4trace:configure.ac:10: -1- AC_SUBST([datadir], ['${prefix}/share']) +m4trace:configure.ac:10: -1- AC_SUBST([sysconfdir], ['${prefix}/etc']) +m4trace:configure.ac:10: -1- AC_SUBST([sharedstatedir], ['${prefix}/com']) +m4trace:configure.ac:10: -1- AC_SUBST([localstatedir], ['${prefix}/var']) +m4trace:configure.ac:10: -1- AC_SUBST([libdir], ['${exec_prefix}/lib']) +m4trace:configure.ac:10: -1- AC_SUBST([includedir], ['${prefix}/include']) +m4trace:configure.ac:10: -1- AC_SUBST([oldincludedir], ['/usr/include']) +m4trace:configure.ac:10: -1- AC_SUBST([infodir], ['${prefix}/info']) +m4trace:configure.ac:10: -1- AC_SUBST([mandir], ['${prefix}/man']) +m4trace:configure.ac:10: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_NAME]) +m4trace:configure.ac:10: -1- AH_OUTPUT([PACKAGE_NAME], [/* Define to the full name of this package. */ +#undef PACKAGE_NAME]) +m4trace:configure.ac:10: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_TARNAME]) +m4trace:configure.ac:10: -1- AH_OUTPUT([PACKAGE_TARNAME], [/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME]) +m4trace:configure.ac:10: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_VERSION]) +m4trace:configure.ac:10: -1- AH_OUTPUT([PACKAGE_VERSION], [/* Define to the version of this package. */ +#undef PACKAGE_VERSION]) +m4trace:configure.ac:10: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_STRING]) +m4trace:configure.ac:10: -1- AH_OUTPUT([PACKAGE_STRING], [/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING]) +m4trace:configure.ac:10: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_BUGREPORT]) +m4trace:configure.ac:10: -1- AH_OUTPUT([PACKAGE_BUGREPORT], [/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT]) +m4trace:configure.ac:10: -1- AC_SUBST([build_alias]) +m4trace:configure.ac:10: -1- AC_SUBST([host_alias]) +m4trace:configure.ac:10: -1- AC_SUBST([target_alias]) +m4trace:configure.ac:10: -1- AC_SUBST([DEFS]) +m4trace:configure.ac:10: -1- AC_SUBST([ECHO_C]) +m4trace:configure.ac:10: -1- AC_SUBST([ECHO_N]) +m4trace:configure.ac:10: -1- AC_SUBST([ECHO_T]) +m4trace:configure.ac:10: -1- AC_SUBST([LIBS]) +m4trace:configure.ac:14: -1- AM_INIT_AUTOMAKE([-Wall -Werror]) +m4trace:configure.ac:14: -1- m4_pattern_allow([^AM_[A-Z]+FLAGS$]) +m4trace:configure.ac:14: -1- AM_AUTOMAKE_VERSION([1.9.6]) +m4trace:configure.ac:14: -1- AC_PROG_INSTALL +m4trace:configure.ac:14: -1- AC_SUBST([INSTALL_PROGRAM]) +m4trace:configure.ac:14: -1- AC_SUBST([INSTALL_SCRIPT]) +m4trace:configure.ac:14: -1- AC_SUBST([INSTALL_DATA]) +m4trace:configure.ac:14: -1- AC_SUBST([CYGPATH_W]) +m4trace:configure.ac:14: -1- AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME']) +m4trace:configure.ac:14: -1- AC_SUBST([VERSION], ['AC_PACKAGE_VERSION']) +m4trace:configure.ac:14: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE]) +m4trace:configure.ac:14: -1- AH_OUTPUT([PACKAGE], [/* Name of package */ +#undef PACKAGE]) +m4trace:configure.ac:14: -1- AC_DEFINE_TRACE_LITERAL([VERSION]) +m4trace:configure.ac:14: -1- AH_OUTPUT([VERSION], [/* Version number of package */ +#undef VERSION]) +m4trace:configure.ac:14: -1- AC_SUBST([ACLOCAL]) +m4trace:configure.ac:14: -1- AC_SUBST([AUTOCONF]) +m4trace:configure.ac:14: -1- AC_SUBST([AUTOMAKE]) +m4trace:configure.ac:14: -1- AC_SUBST([AUTOHEADER]) +m4trace:configure.ac:14: -1- AC_SUBST([MAKEINFO]) +m4trace:configure.ac:14: -1- AC_SUBST([install_sh]) +m4trace:configure.ac:14: -1- AC_SUBST([STRIP]) +m4trace:configure.ac:14: -1- AC_SUBST([ac_ct_STRIP]) +m4trace:configure.ac:14: -1- AC_SUBST([INSTALL_STRIP_PROGRAM]) +m4trace:configure.ac:14: -1- AC_SUBST([mkdir_p]) +m4trace:configure.ac:14: -1- AC_PROG_AWK +m4trace:configure.ac:14: -1- AC_SUBST([AWK]) +m4trace:configure.ac:14: -1- AC_PROG_MAKE_SET +m4trace:configure.ac:14: -1- AC_SUBST([SET_MAKE]) +m4trace:configure.ac:14: -1- AC_SUBST([am__leading_dot]) +m4trace:configure.ac:14: -1- AC_SUBST([AMTAR]) +m4trace:configure.ac:14: -1- AC_SUBST([am__tar]) +m4trace:configure.ac:14: -1- AC_SUBST([am__untar]) +m4trace:configure.ac:17: -1- AC_SUBST([LIBTOOL_DEPS]) +m4trace:configure.ac:18: -1- AC_PROG_CXX +m4trace:configure.ac:18: -1- AC_SUBST([CXX]) +m4trace:configure.ac:18: -1- AC_SUBST([CXXFLAGS]) +m4trace:configure.ac:18: -1- AC_SUBST([LDFLAGS]) +m4trace:configure.ac:18: -1- AC_SUBST([CPPFLAGS]) +m4trace:configure.ac:18: -1- AC_SUBST([CXX]) +m4trace:configure.ac:18: -1- AC_SUBST([ac_ct_CXX]) +m4trace:configure.ac:18: -1- AC_SUBST([EXEEXT], [$ac_cv_exeext]) +m4trace:configure.ac:18: -1- AC_SUBST([OBJEXT], [$ac_cv_objext]) +m4trace:configure.ac:18: -1- AC_SUBST([DEPDIR], ["${am__leading_dot}deps"]) +m4trace:configure.ac:18: -1- AC_SUBST([am__include]) +m4trace:configure.ac:18: -1- AC_SUBST([am__quote]) +m4trace:configure.ac:18: -1- AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +m4trace:configure.ac:18: -1- AC_SUBST([AMDEP_TRUE]) +m4trace:configure.ac:18: -1- AC_SUBST([AMDEP_FALSE]) +m4trace:configure.ac:18: -1- AC_SUBST([AMDEPBACKSLASH]) +m4trace:configure.ac:18: -1- AC_SUBST([CXXDEPMODE], [depmode=$am_cv_CXX_dependencies_compiler_type]) +m4trace:configure.ac:18: -1- AM_CONDITIONAL([am__fastdepCXX], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3]) +m4trace:configure.ac:18: -1- AC_SUBST([am__fastdepCXX_TRUE]) +m4trace:configure.ac:18: -1- AC_SUBST([am__fastdepCXX_FALSE]) +m4trace:configure.ac:20: -1- AC_DEFINE_TRACE_LITERAL([WORDS_BIGENDIAN]) +m4trace:configure.ac:20: -1- AH_OUTPUT([WORDS_BIGENDIAN], [/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN]) +m4trace:configure.ac:21: -1- AC_CHECK_HEADERS([stdint.h stddef.h sys/mman.h sys/resource.h windows.h byteswap.h sys/byteswap.h sys/endian.h]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STDINT_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STDDEF_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_STDDEF_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_SYS_MMAN_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MMAN_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_SYS_RESOURCE_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_WINDOWS_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_WINDOWS_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_BYTESWAP_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_BYTESWAP_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_SYS_BYTESWAP_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_BYTESWAP_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_SYS_ENDIAN_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_ENDIAN_H]) +m4trace:configure.ac:21: -1- AC_HEADER_STDC +m4trace:configure.ac:21: -1- AC_SUBST([CXXCPP]) +m4trace:configure.ac:21: -1- AC_SUBST([CPPFLAGS]) +m4trace:configure.ac:21: -1- AC_SUBST([CXXCPP]) +m4trace:configure.ac:21: -1- AC_SUBST([EGREP]) +m4trace:configure.ac:21: -1- AC_DEFINE_TRACE_LITERAL([STDC_HEADERS]) +m4trace:configure.ac:21: -1- AH_OUTPUT([STDC_HEADERS], [/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS]) +m4trace:configure.ac:21: -1- AC_CHECK_HEADERS([sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h], [], [], [$ac_includes_default]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_SYS_TYPES_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_SYS_STAT_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STRING_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_MEMORY_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STRINGS_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_INTTYPES_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STDINT_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H]) +m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H]) +m4trace:configure.ac:27: -1- AC_SUBST([GTEST_CONFIG]) +m4trace:configure.ac:27: -1- AC_SUBST([GTEST_CPPFLAGS]) +m4trace:configure.ac:27: -1- AC_SUBST([GTEST_CXXFLAGS]) +m4trace:configure.ac:27: -1- AC_SUBST([GTEST_LDFLAGS]) +m4trace:configure.ac:27: -1- AC_SUBST([GTEST_LIBS]) +m4trace:configure.ac:27: -1- AC_SUBST([GTEST_VERSION]) +m4trace:configure.ac:27: -1- AC_SUBST([GTEST_CONFIG], [$ac_cv_path_GTEST_CONFIG]) +m4trace:configure.ac:27: -1- AC_DEFINE_TRACE_LITERAL([HAVE_GTEST]) +m4trace:configure.ac:27: -1- AH_OUTPUT([HAVE_GTEST], [/* Defined when Google Test is available. */ +#undef HAVE_GTEST]) +m4trace:configure.ac:27: -1- AC_SUBST([HAVE_GTEST]) +m4trace:configure.ac:27: -1- AM_CONDITIONAL([HAVE_GTEST], [test "x$HAVE_GTEST" = "xyes"]) +m4trace:configure.ac:27: -1- AC_SUBST([HAVE_GTEST_TRUE]) +m4trace:configure.ac:27: -1- AC_SUBST([HAVE_GTEST_FALSE]) +m4trace:configure.ac:43: -1- m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4trace:configure.ac:43: -1- m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) +m4trace:configure.ac:43: -1- AC_SUBST([PKG_CONFIG]) +m4trace:configure.ac:43: -1- AC_SUBST([PKG_CONFIG], [$ac_cv_path_PKG_CONFIG]) +m4trace:configure.ac:43: -1- AC_SUBST([ac_pt_PKG_CONFIG], [$ac_cv_path_ac_pt_PKG_CONFIG]) +m4trace:configure.ac:43: -1- AC_SUBST([gflags_CFLAGS]) +m4trace:configure.ac:43: -1- AC_SUBST([gflags_LIBS]) +m4trace:configure.ac:43: -1- AC_DEFINE_TRACE_LITERAL([HAVE_GFLAGS]) +m4trace:configure.ac:43: -1- AH_OUTPUT([HAVE_GFLAGS], [/* Use the gflags package for command-line parsing. */ +#undef HAVE_GFLAGS]) +m4trace:configure.ac:58: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete. +You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from... +configure.ac:58: the top level]) +m4trace:configure.ac:60: -1- AC_DEFINE_TRACE_LITERAL([HAVE_BUILTIN_EXPECT]) +m4trace:configure.ac:60: -1- AH_OUTPUT([HAVE_BUILTIN_EXPECT], [/* Define to 1 if the compiler supports __builtin_expect. */ +#undef HAVE_BUILTIN_EXPECT]) +m4trace:configure.ac:75: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete. +You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from... +configure.ac:75: the top level]) +m4trace:configure.ac:77: -1- AC_DEFINE_TRACE_LITERAL([HAVE_BUILTIN_CTZ]) +m4trace:configure.ac:77: -1- AH_OUTPUT([HAVE_BUILTIN_CTZ], [/* Define to 1 if the compiler supports __builtin_ctz and friends. */ +#undef HAVE_BUILTIN_CTZ]) +m4trace:configure.ac:95: -1- AH_OUTPUT([HAVE_LIBZ], [/* Define to 1 if you have the `z\' library (-lz). */ +#undef HAVE_LIBZ]) +m4trace:configure.ac:95: -1- AC_CHECK_LIB([z], [zlibVersion], [ + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIBz)) + UNITTEST_LIBS="-lz $UNITTEST_LIBS" + ], [true + ]) +m4trace:configure.ac:95: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBZ]) +m4trace:configure.ac:96: -1- AH_OUTPUT([HAVE_LIBLZO2], [/* Define to 1 if you have the `lzo2\' library (-llzo2). */ +#undef HAVE_LIBLZO2]) +m4trace:configure.ac:96: -1- AC_CHECK_LIB([lzo2], [lzo1x_1_15_compress], [ + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIBlzo2)) + UNITTEST_LIBS="-llzo2 $UNITTEST_LIBS" + ], [true + ]) +m4trace:configure.ac:96: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBLZO2]) +m4trace:configure.ac:97: -1- AH_OUTPUT([HAVE_LIBLZF], [/* Define to 1 if you have the `lzf\' library (-llzf). */ +#undef HAVE_LIBLZF]) +m4trace:configure.ac:97: -1- AC_CHECK_LIB([lzf], [lzf_compress], [ + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIBlzf)) + UNITTEST_LIBS="-llzf $UNITTEST_LIBS" + ], [true + ]) +m4trace:configure.ac:97: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBLZF]) +m4trace:configure.ac:98: -1- AH_OUTPUT([HAVE_LIBFASTLZ], [/* Define to 1 if you have the `fastlz\' library (-lfastlz). */ +#undef HAVE_LIBFASTLZ]) +m4trace:configure.ac:98: -1- AC_CHECK_LIB([fastlz], [fastlz_compress], [ + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIBfastlz)) + UNITTEST_LIBS="-lfastlz $UNITTEST_LIBS" + ], [true + ]) +m4trace:configure.ac:98: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBFASTLZ]) +m4trace:configure.ac:99: -1- AH_OUTPUT([HAVE_LIBQUICKLZ], [/* Define to 1 if you have the `quicklz\' library (-lquicklz). */ +#undef HAVE_LIBQUICKLZ]) +m4trace:configure.ac:99: -1- AC_CHECK_LIB([quicklz], [qlz_compress], [ + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIBquicklz)) + UNITTEST_LIBS="-lquicklz $UNITTEST_LIBS" + ], [true + ]) +m4trace:configure.ac:99: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBQUICKLZ]) +m4trace:configure.ac:100: -1- AC_SUBST([UNITTEST_LIBS]) +m4trace:configure.ac:104: -1- AC_SUBST([ac_cv_have_stdint_h], [1]) +m4trace:configure.ac:106: -1- AC_SUBST([ac_cv_have_stdint_h], [0]) +m4trace:configure.ac:109: -1- AC_SUBST([ac_cv_have_stddef_h], [1]) +m4trace:configure.ac:111: -1- AC_SUBST([ac_cv_have_stddef_h], [0]) +m4trace:configure.ac:119: -1- AC_SUBST([SNAPPY_MAJOR]) +m4trace:configure.ac:120: -1- AC_SUBST([SNAPPY_MINOR]) +m4trace:configure.ac:121: -1- AC_SUBST([SNAPPY_PATCHLEVEL]) +m4trace:configure.ac:122: -1- AC_SUBST([SNAPPY_LTVERSION], [2:3:1]) +m4trace:configure.ac:124: -1- AC_CONFIG_HEADERS([config.h]) +m4trace:configure.ac:125: -1- AC_CONFIG_FILES([Makefile snappy-stubs-public.h]) +m4trace:configure.ac:126: -1- AC_SUBST([LIB@&t@OBJS], [$ac_libobjs]) +m4trace:configure.ac:126: -1- AC_SUBST([LTLIBOBJS], [$ac_ltlibobjs]) diff --git a/snappy/snappy-1.0.5/compile.sh b/snappy/snappy-1.0.5/compile.sh new file mode 100755 index 00000000..8f009aa9 --- /dev/null +++ b/snappy/snappy-1.0.5/compile.sh @@ -0,0 +1 @@ +make CXXFLAGS="-O2 -DNDEBUG" CXX="/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++" LIBS="/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/jemalloc/jemalloc-2.2.4/96de4f9/lib/libjemalloc_pic.a" diff --git a/snappy/snappy-1.0.5/config.guess b/snappy/snappy-1.0.5/config.guess new file mode 100755 index 00000000..e3a2116a --- /dev/null +++ b/snappy/snappy-1.0.5/config.guess @@ -0,0 +1,1533 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. + +timestamp='2009-06-10' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[456]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:[3456]*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T | authenticamd | genuineintel) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/snappy/snappy-1.0.5/config.h b/snappy/snappy-1.0.5/config.h new file mode 100644 index 00000000..895cc7fc --- /dev/null +++ b/snappy/snappy-1.0.5/config.h @@ -0,0 +1,105 @@ +/* config.h. Generated by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if the compiler supports __builtin_ctz and friends. */ +#define HAVE_BUILTIN_CTZ 1 + +/* Define to 1 if the compiler supports __builtin_expect. */ +#define HAVE_BUILTIN_EXPECT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_BYTESWAP_H 1 + +/* Use the gflags package for command-line parsing. */ +/* #undef HAVE_GFLAGS */ + +/* Defined when Google Test is available. */ +/* #undef HAVE_GTEST */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `fastlz' library (-lfastlz). */ +/* #undef HAVE_LIBFASTLZ */ + +/* Define to 1 if you have the `lzf' library (-llzf). */ +/* #undef HAVE_LIBLZF */ + +/* Define to 1 if you have the `lzo2' library (-llzo2). */ +/* #undef HAVE_LIBLZO2 */ + +/* Define to 1 if you have the `quicklz' library (-lquicklz). */ +/* #undef HAVE_LIBQUICKLZ */ + +/* Define to 1 if you have the `z' library (-lz). */ +// #define HAVE_LIBZ 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDDEF_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_BYTESWAP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_ENDIAN_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Name of package */ +#define PACKAGE "snappy" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "snappy" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "snappy 1.0.5" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "snappy" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.0.5" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.0.5" + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ diff --git a/snappy/snappy-1.0.5/config.h.in b/snappy/snappy-1.0.5/config.h.in new file mode 100644 index 00000000..d722b0ed --- /dev/null +++ b/snappy/snappy-1.0.5/config.h.in @@ -0,0 +1,104 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if the compiler supports __builtin_ctz and friends. */ +#undef HAVE_BUILTIN_CTZ + +/* Define to 1 if the compiler supports __builtin_expect. */ +#undef HAVE_BUILTIN_EXPECT + +/* Define to 1 if you have the header file. */ +#undef HAVE_BYTESWAP_H + +/* Use the gflags package for command-line parsing. */ +#undef HAVE_GFLAGS + +/* Defined when Google Test is available. */ +#undef HAVE_GTEST + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `fastlz' library (-lfastlz). */ +#undef HAVE_LIBFASTLZ + +/* Define to 1 if you have the `lzf' library (-llzf). */ +#undef HAVE_LIBLZF + +/* Define to 1 if you have the `lzo2' library (-llzo2). */ +#undef HAVE_LIBLZO2 + +/* Define to 1 if you have the `quicklz' library (-lquicklz). */ +#undef HAVE_LIBQUICKLZ + +/* Define to 1 if you have the `z' library (-lz). */ +#undef HAVE_LIBZ + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDDEF_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_BYTESWAP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_ENDIAN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MMAN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINDOWS_H + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN diff --git a/snappy/snappy-1.0.5/config.log b/snappy/snappy-1.0.5/config.log new file mode 100644 index 00000000..5399a02d --- /dev/null +++ b/snappy/snappy-1.0.5/config.log @@ -0,0 +1,1306 @@ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by snappy configure 1.0.5, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ ./configure --disable-shared --with-pic CXX=/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp --no-create --no-recursion + +## --------- ## +## Platform. ## +## --------- ## + +hostname = dev3936.snc6.facebook.com +uname -m = x86_64 +uname -r = 2.6.38.4-49_fbk20_00135_g561dc87 +uname -s = Linux +uname -v = #49 SMP Mon Nov 28 14:05:54 PST 2011 + +/usr/bin/uname -p = unknown +/bin/uname -X = unknown + +/bin/arch = x86_64 +/usr/bin/arch -k = unknown +/usr/convex/getsysinfo = unknown +hostinfo = unknown +/bin/machine = unknown +/usr/bin/oslevel = unknown +/bin/universe = unknown + +PATH: /usr/local/jdk-6u7-32//bin +PATH: /home/dhruba/maven/bin +PATH: /home/dhruba/bin/ +PATH: /home/dhruba/external/apache-ant-1.8.1/bin/ +PATH: /usr/local/java/bin/ +PATH: ~/pl/bin +PATH: ~/maven/bin +PATH: /home/dhruba/apache-ant-1.7.0/bin +PATH: /usr/kerberos/bin +PATH: /opt/local/bin +PATH: /usr/local/bin +PATH: /bin +PATH: /usr/bin +PATH: /usr/facebook/scripts +PATH: /home/engshare/devtools/facebook/bin +PATH: /home/engshare/svnroot/tfb/trunk/www/scripts/bin +PATH: /home/engshare/admin/scripts/git +PATH: /home/engshare/admin/scripts +PATH: /home/dhruba/www/scripts/bin +PATH: /home/dhruba/bin + + +## ----------- ## +## Core tests. ## +## ----------- ## + +configure:1420: checking for a BSD-compatible install +configure:1475: result: /usr/bin/install -c +configure:1486: checking whether build environment is sane +configure:1529: result: yes +configure:1594: checking for gawk +configure:1610: found /bin/gawk +configure:1620: result: gawk +configure:1630: checking whether make sets $(MAKE) +configure:1650: result: yes +configure:1915: checking for C++ compiler version +configure:1918: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp --version &5 +g++ (GCC) 4.6.2 20111027 (Red Hat 4.6.2-1) +Copyright (C) 2011 Free Software Foundation, Inc. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +configure:1921: $? = 0 +configure:1923: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -v &5 +Using built-in specs. +COLLECT_GCC=/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/bin/g++ +COLLECT_LTO_WRAPPER=/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/bin/../libexec/gcc/x86_64-redhat-linux-gnu/4.6.2/lto-wrapper +Target: x86_64-redhat-linux-gnu +Configured with: /home/engshare/third-party/src/gcc/gcc-4.6.2/gcc-4.6.2-20111027/configure --build=x86_64-redhat-linux-gnu --host=x86_64-redhat-linux-gnu --target=x86_64-redhat-linux-gnu --prefix=/home/engshare/third-party/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc --exec-prefix=/home/engshare/third-party/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc --bindir=/home/engshare/third-party/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/bin --sbindir=/home/engshare/third-party/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/sbin --sysconfdir=/home/engshare/third-party/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/etc --datadir=/home/engshare/third-party/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/share --includedir=/home/engshare/third-party/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/include --libdir=/home/engshare/third-party/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/lib --libexecdir=/home/engshare/third-party/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/libexec --localstatedir=/home/engshare/third-party/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/var --sharedstatedir=/home/engshare/third-party/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/com --mandir=/home/engshare/third-party/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/share/man --infodir=/home/engshare/third-party/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/share/info --with-gmp=/home/engshare/third-party/centos5.2-native/gmp/gmp-5.0.1/da39a3e --with-mpfr=/home/engshare/third-party/centos5.2-native/mpfr/mpfr-3.0.0/c68f0aa --with-mpc=/home/engshare/third-party/centos5.2-native/mpc/mpc-0.8.2/18cfc0e --with-ppl=/home/engshare/third-party/centos5.2-native/ppl/ppl-0.10/c68f0aa --with-cloog=/home/engshare/third-party/centos5.2-native/cloog/cloog-0.15.7/ab7be4d --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-languages=c,c++ --disable-libgcj --disable-libgfortran --enable-linker-build-id --with-gnu-as --with-gnu-ld --with-host-libstdcxx='-L/usr/lib/gcc/x86_64-redhat-linux/4.1.2 -lstdc++' +Thread model: posix +gcc version 4.6.2 20111027 (Red Hat 4.6.2-1) (GCC) +COMPILER_PATH=/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/bin/../libexec/gcc/x86_64-redhat-linux-gnu/4.6.2/:/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/bin/../libexec/gcc/:/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/bin/:/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/binutils/binutils-2.21.1/da39a3e/bin/ +LIBRARY_PATH=/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/bin/../lib/gcc/x86_64-redhat-linux-gnu/4.6.2/:/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/bin/../lib/gcc/:/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/lib/../lib64/:/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/lib64/../lib64/:/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/bin/../lib/gcc/x86_64-redhat-linux-gnu/4.6.2/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/lib/:/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/lib64/:/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/bin/../lib/gcc/x86_64-redhat-linux-gnu/4.6.2/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-nostdinc' '-I' './snappy' '-I' '/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include' '-std=gnu++0x' '-I' './thrift' '-I' './thrift/gen-cpp' '-I' './thrift/lib/cpp' '-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/bin/../libexec/gcc/x86_64-redhat-linux-gnu/4.6.2/collect2 --no-add-needed --eh-frame-hdr -m elf_x86_64 --hash-style=gnu -dynamic-linker /lib64/ld-linux-x86-64.so.2 /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/lib/../lib64/crt1.o /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/lib/../lib64/crti.o /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/bin/../lib/gcc/x86_64-redhat-linux-gnu/4.6.2/crtbegin.o -L/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/bin/../lib/gcc/x86_64-redhat-linux-gnu/4.6.2 -L/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/bin/../lib/gcc -L/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/lib/../lib64 -L/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/lib64/../lib64 -L/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/bin/../lib/gcc/x86_64-redhat-linux-gnu/4.6.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/lib -L/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/libgcc/libgcc-4.6.2/b4e37bb/lib64 -L/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/bin/../lib/gcc/x86_64-redhat-linux-gnu/4.6.2/../../.. --dynamic-linker /usr/local/fbcode/gcc-4.6.2-glibc-2.13/lib/ld-linux-x86-64.so.2 -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2/cc6c9dc/bin/../lib/gcc/x86_64-redhat-linux-gnu/4.6.2/crtend.o /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/lib/../lib64/crtn.o +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/lib/../lib64/crt1.o: In function `_start': +/home/engshare/third-party/src/glibc/glibc-2.13/glibc-2.13/csu/../sysdeps/x86_64/elf/start.S:109: undefined reference to `main' +collect2: ld returned 1 exit status +configure:1926: $? = 1 +configure:1928: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -V &5 +g++: error: unrecognized option '-V' +configure:1931: $? = 1 +configure:1954: checking for C++ compiler default output file name +configure:1957: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp conftest.cc >&5 +configure:1960: $? = 0 +configure:2006: result: a.out +configure:2011: checking whether the C++ compiler works +configure:2017: ./a.out +configure:2020: $? = 0 +configure:2037: result: yes +configure:2044: checking whether we are cross compiling +configure:2046: result: no +configure:2049: checking for suffix of executables +configure:2051: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -o conftest conftest.cc >&5 +configure:2054: $? = 0 +configure:2079: result: +configure:2085: checking for suffix of object files +configure:2106: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c conftest.cc >&5 +configure:2109: $? = 0 +configure:2131: result: o +configure:2135: checking whether we are using the GNU C++ compiler +configure:2159: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c conftest.cc >&5 +configure:2165: $? = 0 +configure:2169: test -z + || test ! -s conftest.err +configure:2172: $? = 0 +configure:2175: test -s conftest.o +configure:2178: $? = 0 +configure:2191: result: yes +configure:2197: checking whether /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp accepts -g +configure:2218: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g conftest.cc >&5 +configure:2224: $? = 0 +configure:2228: test -z + || test ! -s conftest.err +configure:2231: $? = 0 +configure:2234: test -s conftest.o +configure:2237: $? = 0 +configure:2248: result: yes +configure:2290: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:2296: $? = 0 +configure:2300: test -z + || test ! -s conftest.err +configure:2303: $? = 0 +configure:2306: test -s conftest.o +configure:2309: $? = 0 +configure:2335: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +conftest.cc: In function 'int main()': +conftest.cc:15:9: error: 'exit' was not declared in this scope +configure:2341: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "snappy" +| #define PACKAGE_TARNAME "snappy" +| #define PACKAGE_VERSION "1.0.5" +| #define PACKAGE_STRING "snappy 1.0.5" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE "snappy" +| #define VERSION "1.0.5" +| /* end confdefs.h. */ +| +| int +| main () +| { +| exit (42); +| ; +| return 0; +| } +configure:2290: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +conftest.cc:11:40: error: 'void std::exit(int)' should have been declared inside 'std' +configure:2296: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "snappy" +| #define PACKAGE_TARNAME "snappy" +| #define PACKAGE_VERSION "1.0.5" +| #define PACKAGE_STRING "snappy 1.0.5" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE "snappy" +| #define VERSION "1.0.5" +| /* end confdefs.h. */ +| extern "C" void std::exit (int) throw (); using std::exit; +| #include +| int +| main () +| { +| exit (42); +| ; +| return 0; +| } +configure:2290: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +conftest.cc:11:31: error: 'void std::exit(int)' should have been declared inside 'std' +In file included from conftest.cc:12:0: +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/glibc/glibc-2.13/5c2e919/include/stdlib.h:544:70: error: declaration of 'void std::exit(int) throw ()' has a different exception specifier +conftest.cc:11:17: error: from previous declaration 'void std::exit(int)' +configure:2296: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "snappy" +| #define PACKAGE_TARNAME "snappy" +| #define PACKAGE_VERSION "1.0.5" +| #define PACKAGE_STRING "snappy 1.0.5" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE "snappy" +| #define VERSION "1.0.5" +| /* end confdefs.h. */ +| extern "C" void std::exit (int); using std::exit; +| #include +| int +| main () +| { +| exit (42); +| ; +| return 0; +| } +configure:2290: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:2296: $? = 0 +configure:2300: test -z + || test ! -s conftest.err +configure:2303: $? = 0 +configure:2306: test -s conftest.o +configure:2309: $? = 0 +configure:2335: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:2341: $? = 0 +configure:2345: test -z + || test ! -s conftest.err +configure:2348: $? = 0 +configure:2351: test -s conftest.o +configure:2354: $? = 0 +configure:2388: checking for style of include used by make +configure:2416: result: GNU +configure:2444: checking dependency style of /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp +configure:2534: result: gcc3 +configure:2558: checking whether byte ordering is bigendian +configure:2585: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:2591: $? = 0 +configure:2595: test -z + || test ! -s conftest.err +configure:2598: $? = 0 +configure:2601: test -s conftest.o +configure:2604: $? = 0 +configure:2628: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +conftest.cc: In function 'int main()': +conftest.cc:21:6: error: 'big' was not declared in this scope +conftest.cc:21:10: error: expected ';' before 'endian' +configure:2634: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "snappy" +| #define PACKAGE_TARNAME "snappy" +| #define PACKAGE_VERSION "1.0.5" +| #define PACKAGE_STRING "snappy 1.0.5" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE "snappy" +| #define VERSION "1.0.5" +| #ifdef __cplusplus +| extern "C" void exit (int) throw (); +| #endif +| /* end confdefs.h. */ +| #include +| #include +| +| int +| main () +| { +| #if BYTE_ORDER != BIG_ENDIAN +| not big endian +| #endif +| +| ; +| return 0; +| } +configure:2769: result: no +configure:2793: checking how to run the C++ preprocessor +configure:2824: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -E conftest.cc +configure:2830: $? = 0 +configure:2862: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -E conftest.cc +conftest.cc:14:28: fatal error: ac_nonexistent.h: No such file or directory +compilation terminated. +configure:2868: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "snappy" +| #define PACKAGE_TARNAME "snappy" +| #define PACKAGE_VERSION "1.0.5" +| #define PACKAGE_STRING "snappy 1.0.5" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE "snappy" +| #define VERSION "1.0.5" +| #ifdef __cplusplus +| extern "C" void exit (int) throw (); +| #endif +| /* end confdefs.h. */ +| #include +configure:2907: result: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -E +configure:2931: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -E conftest.cc +configure:2937: $? = 0 +configure:2969: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -E conftest.cc +conftest.cc:14:28: fatal error: ac_nonexistent.h: No such file or directory +compilation terminated. +configure:2975: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "snappy" +| #define PACKAGE_TARNAME "snappy" +| #define PACKAGE_VERSION "1.0.5" +| #define PACKAGE_STRING "snappy 1.0.5" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE "snappy" +| #define VERSION "1.0.5" +| #ifdef __cplusplus +| extern "C" void exit (int) throw (); +| #endif +| /* end confdefs.h. */ +| #include +configure:3019: checking for egrep +configure:3029: result: grep -E +configure:3034: checking for ANSI C header files +configure:3059: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:3065: $? = 0 +configure:3069: test -z + || test ! -s conftest.err +configure:3072: $? = 0 +configure:3075: test -s conftest.o +configure:3078: $? = 0 +configure:3167: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -o conftest -g -O2 conftest.cc >&5 +configure:3170: $? = 0 +configure:3172: ./conftest +configure:3175: $? = 0 +configure:3190: result: yes +configure:3214: checking for sys/types.h +configure:3230: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:3236: $? = 0 +configure:3240: test -z + || test ! -s conftest.err +configure:3243: $? = 0 +configure:3246: test -s conftest.o +configure:3249: $? = 0 +configure:3260: result: yes +configure:3214: checking for sys/stat.h +configure:3230: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:3236: $? = 0 +configure:3240: test -z + || test ! -s conftest.err +configure:3243: $? = 0 +configure:3246: test -s conftest.o +configure:3249: $? = 0 +configure:3260: result: yes +configure:3214: checking for stdlib.h +configure:3230: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:3236: $? = 0 +configure:3240: test -z + || test ! -s conftest.err +configure:3243: $? = 0 +configure:3246: test -s conftest.o +configure:3249: $? = 0 +configure:3260: result: yes +configure:3214: checking for string.h +configure:3230: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:3236: $? = 0 +configure:3240: test -z + || test ! -s conftest.err +configure:3243: $? = 0 +configure:3246: test -s conftest.o +configure:3249: $? = 0 +configure:3260: result: yes +configure:3214: checking for memory.h +configure:3230: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:3236: $? = 0 +configure:3240: test -z + || test ! -s conftest.err +configure:3243: $? = 0 +configure:3246: test -s conftest.o +configure:3249: $? = 0 +configure:3260: result: yes +configure:3214: checking for strings.h +configure:3230: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:3236: $? = 0 +configure:3240: test -z + || test ! -s conftest.err +configure:3243: $? = 0 +configure:3246: test -s conftest.o +configure:3249: $? = 0 +configure:3260: result: yes +configure:3214: checking for inttypes.h +configure:3230: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:3236: $? = 0 +configure:3240: test -z + || test ! -s conftest.err +configure:3243: $? = 0 +configure:3246: test -s conftest.o +configure:3249: $? = 0 +configure:3260: result: yes +configure:3214: checking for stdint.h +configure:3230: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:3236: $? = 0 +configure:3240: test -z + || test ! -s conftest.err +configure:3243: $? = 0 +configure:3246: test -s conftest.o +configure:3249: $? = 0 +configure:3260: result: yes +configure:3214: checking for unistd.h +configure:3230: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:3236: $? = 0 +configure:3240: test -z + || test ! -s conftest.err +configure:3243: $? = 0 +configure:3246: test -s conftest.o +configure:3249: $? = 0 +configure:3260: result: yes +configure:3284: checking for stdint.h +configure:3289: result: yes +configure:3293: checking stddef.h usability +configure:3305: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:3311: $? = 0 +configure:3315: test -z + || test ! -s conftest.err +configure:3318: $? = 0 +configure:3321: test -s conftest.o +configure:3324: $? = 0 +configure:3334: result: yes +configure:3338: checking stddef.h presence +configure:3348: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -E conftest.cc +configure:3354: $? = 0 +configure:3374: result: yes +configure:3409: checking for stddef.h +configure:3416: result: yes +configure:3293: checking sys/mman.h usability +configure:3305: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:3311: $? = 0 +configure:3315: test -z + || test ! -s conftest.err +configure:3318: $? = 0 +configure:3321: test -s conftest.o +configure:3324: $? = 0 +configure:3334: result: yes +configure:3338: checking sys/mman.h presence +configure:3348: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -E conftest.cc +configure:3354: $? = 0 +configure:3374: result: yes +configure:3409: checking for sys/mman.h +configure:3416: result: yes +configure:3293: checking sys/resource.h usability +configure:3305: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:3311: $? = 0 +configure:3315: test -z + || test ! -s conftest.err +configure:3318: $? = 0 +configure:3321: test -s conftest.o +configure:3324: $? = 0 +configure:3334: result: yes +configure:3338: checking sys/resource.h presence +configure:3348: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -E conftest.cc +configure:3354: $? = 0 +configure:3374: result: yes +configure:3409: checking for sys/resource.h +configure:3416: result: yes +configure:3293: checking windows.h usability +configure:3305: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +conftest.cc:62:21: fatal error: windows.h: No such file or directory +compilation terminated. +configure:3311: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "snappy" +| #define PACKAGE_TARNAME "snappy" +| #define PACKAGE_VERSION "1.0.5" +| #define PACKAGE_STRING "snappy 1.0.5" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE "snappy" +| #define VERSION "1.0.5" +| #ifdef __cplusplus +| extern "C" void exit (int) throw (); +| #endif +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_STDDEF_H 1 +| #define HAVE_SYS_MMAN_H 1 +| #define HAVE_SYS_RESOURCE_H 1 +| /* end confdefs.h. */ +| #include +| #if HAVE_SYS_TYPES_H +| # include +| #endif +| #if HAVE_SYS_STAT_H +| # include +| #endif +| #if STDC_HEADERS +| # include +| # include +| #else +| # if HAVE_STDLIB_H +| # include +| # endif +| #endif +| #if HAVE_STRING_H +| # if !STDC_HEADERS && HAVE_MEMORY_H +| # include +| # endif +| # include +| #endif +| #if HAVE_STRINGS_H +| # include +| #endif +| #if HAVE_INTTYPES_H +| # include +| #else +| # if HAVE_STDINT_H +| # include +| # endif +| #endif +| #if HAVE_UNISTD_H +| # include +| #endif +| #include +configure:3334: result: no +configure:3338: checking windows.h presence +configure:3348: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -E conftest.cc +conftest.cc:28:21: fatal error: windows.h: No such file or directory +compilation terminated. +configure:3354: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "snappy" +| #define PACKAGE_TARNAME "snappy" +| #define PACKAGE_VERSION "1.0.5" +| #define PACKAGE_STRING "snappy 1.0.5" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE "snappy" +| #define VERSION "1.0.5" +| #ifdef __cplusplus +| extern "C" void exit (int) throw (); +| #endif +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_STDDEF_H 1 +| #define HAVE_SYS_MMAN_H 1 +| #define HAVE_SYS_RESOURCE_H 1 +| /* end confdefs.h. */ +| #include +configure:3374: result: no +configure:3409: checking for windows.h +configure:3416: result: no +configure:3293: checking byteswap.h usability +configure:3305: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:3311: $? = 0 +configure:3315: test -z + || test ! -s conftest.err +configure:3318: $? = 0 +configure:3321: test -s conftest.o +configure:3324: $? = 0 +configure:3334: result: yes +configure:3338: checking byteswap.h presence +configure:3348: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -E conftest.cc +configure:3354: $? = 0 +configure:3374: result: yes +configure:3409: checking for byteswap.h +configure:3416: result: yes +configure:3293: checking sys/byteswap.h usability +configure:3305: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +conftest.cc:63:26: fatal error: sys/byteswap.h: No such file or directory +compilation terminated. +configure:3311: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "snappy" +| #define PACKAGE_TARNAME "snappy" +| #define PACKAGE_VERSION "1.0.5" +| #define PACKAGE_STRING "snappy 1.0.5" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE "snappy" +| #define VERSION "1.0.5" +| #ifdef __cplusplus +| extern "C" void exit (int) throw (); +| #endif +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_STDDEF_H 1 +| #define HAVE_SYS_MMAN_H 1 +| #define HAVE_SYS_RESOURCE_H 1 +| #define HAVE_BYTESWAP_H 1 +| /* end confdefs.h. */ +| #include +| #if HAVE_SYS_TYPES_H +| # include +| #endif +| #if HAVE_SYS_STAT_H +| # include +| #endif +| #if STDC_HEADERS +| # include +| # include +| #else +| # if HAVE_STDLIB_H +| # include +| # endif +| #endif +| #if HAVE_STRING_H +| # if !STDC_HEADERS && HAVE_MEMORY_H +| # include +| # endif +| # include +| #endif +| #if HAVE_STRINGS_H +| # include +| #endif +| #if HAVE_INTTYPES_H +| # include +| #else +| # if HAVE_STDINT_H +| # include +| # endif +| #endif +| #if HAVE_UNISTD_H +| # include +| #endif +| #include +configure:3334: result: no +configure:3338: checking sys/byteswap.h presence +configure:3348: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -E conftest.cc +conftest.cc:29:26: fatal error: sys/byteswap.h: No such file or directory +compilation terminated. +configure:3354: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "snappy" +| #define PACKAGE_TARNAME "snappy" +| #define PACKAGE_VERSION "1.0.5" +| #define PACKAGE_STRING "snappy 1.0.5" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE "snappy" +| #define VERSION "1.0.5" +| #ifdef __cplusplus +| extern "C" void exit (int) throw (); +| #endif +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_STDDEF_H 1 +| #define HAVE_SYS_MMAN_H 1 +| #define HAVE_SYS_RESOURCE_H 1 +| #define HAVE_BYTESWAP_H 1 +| /* end confdefs.h. */ +| #include +configure:3374: result: no +configure:3409: checking for sys/byteswap.h +configure:3416: result: no +configure:3293: checking sys/endian.h usability +configure:3305: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +conftest.cc:63:24: fatal error: sys/endian.h: No such file or directory +compilation terminated. +configure:3311: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "snappy" +| #define PACKAGE_TARNAME "snappy" +| #define PACKAGE_VERSION "1.0.5" +| #define PACKAGE_STRING "snappy 1.0.5" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE "snappy" +| #define VERSION "1.0.5" +| #ifdef __cplusplus +| extern "C" void exit (int) throw (); +| #endif +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_STDDEF_H 1 +| #define HAVE_SYS_MMAN_H 1 +| #define HAVE_SYS_RESOURCE_H 1 +| #define HAVE_BYTESWAP_H 1 +| /* end confdefs.h. */ +| #include +| #if HAVE_SYS_TYPES_H +| # include +| #endif +| #if HAVE_SYS_STAT_H +| # include +| #endif +| #if STDC_HEADERS +| # include +| # include +| #else +| # if HAVE_STDLIB_H +| # include +| # endif +| #endif +| #if HAVE_STRING_H +| # if !STDC_HEADERS && HAVE_MEMORY_H +| # include +| # endif +| # include +| #endif +| #if HAVE_STRINGS_H +| # include +| #endif +| #if HAVE_INTTYPES_H +| # include +| #else +| # if HAVE_STDINT_H +| # include +| # endif +| #endif +| #if HAVE_UNISTD_H +| # include +| #endif +| #include +configure:3334: result: no +configure:3338: checking sys/endian.h presence +configure:3348: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -E conftest.cc +conftest.cc:29:24: fatal error: sys/endian.h: No such file or directory +compilation terminated. +configure:3354: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "snappy" +| #define PACKAGE_TARNAME "snappy" +| #define PACKAGE_VERSION "1.0.5" +| #define PACKAGE_STRING "snappy 1.0.5" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE "snappy" +| #define VERSION "1.0.5" +| #ifdef __cplusplus +| extern "C" void exit (int) throw (); +| #endif +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_STDDEF_H 1 +| #define HAVE_SYS_MMAN_H 1 +| #define HAVE_SYS_RESOURCE_H 1 +| #define HAVE_BYTESWAP_H 1 +| /* end confdefs.h. */ +| #include +configure:3374: result: no +configure:3409: checking for sys/endian.h +configure:3416: result: no +configure:3432: checking for mmap +configure:3489: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -o conftest -g -O2 conftest.cc >&5 +configure:3495: $? = 0 +configure:3499: test -z + || test ! -s conftest.err +configure:3502: $? = 0 +configure:3505: test -s conftest +configure:3508: $? = 0 +configure:3520: result: yes +configure:3540: checking for 'gtest-config' +configure:3567: checking for gtest-config +configure:3600: result: no +configure:3622: result: no +configure:3726: checking for pkg-config +configure:3744: found /usr/bin/pkg-config +configure:3756: result: /usr/bin/pkg-config +configure:3771: checking pkg-config is at least version 0.9.0 +configure:3774: result: yes +configure:3785: checking for gflags +configure:3793: $PKG_CONFIG --exists --print-errors "libgflags" +Package libgflags was not found in the pkg-config search path. +Perhaps you should add the directory containing `libgflags.pc' +to the PKG_CONFIG_PATH environment variable +No package 'libgflags' found +configure:3796: $? = 1 +configure:3811: $PKG_CONFIG --exists --print-errors "libgflags" +Package libgflags was not found in the pkg-config search path. +Perhaps you should add the directory containing `libgflags.pc' +to the PKG_CONFIG_PATH environment variable +No package 'libgflags' found +configure:3814: $? = 1 +No package 'libgflags' found +configure:3842: result: no +configure:3874: checking if the compiler supports __builtin_expect +configure:3895: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:3901: $? = 0 +configure:3905: test -z + || test ! -s conftest.err +configure:3908: $? = 0 +configure:3911: test -s conftest.o +configure:3914: $? = 0 +configure:3918: result: yes +configure:3942: checking if the compiler supports __builtin_ctzll +configure:3963: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -c -g -O2 conftest.cc >&5 +configure:3969: $? = 0 +configure:3973: test -z + || test ! -s conftest.err +configure:3976: $? = 0 +configure:3979: test -s conftest.o +configure:3982: $? = 0 +configure:3986: result: yes +configure:4015: checking for zlibVersion in -lz +configure:4045: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -o conftest -g -O2 conftest.cc -lz >&5 +configure:4051: $? = 0 +configure:4055: test -z + || test ! -s conftest.err +configure:4058: $? = 0 +configure:4061: test -s conftest +configure:4064: $? = 0 +configure:4077: result: yes +configure:4096: checking for lzo1x_1_15_compress in -llzo2 +configure:4126: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -o conftest -g -O2 conftest.cc -llzo2 >&5 +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/binutils/binutils-2.21.1/da39a3e/bin/ld: cannot find -llzo2 +collect2: ld returned 1 exit status +configure:4132: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "snappy" +| #define PACKAGE_TARNAME "snappy" +| #define PACKAGE_VERSION "1.0.5" +| #define PACKAGE_STRING "snappy 1.0.5" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE "snappy" +| #define VERSION "1.0.5" +| #ifdef __cplusplus +| extern "C" void exit (int) throw (); +| #endif +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_STDDEF_H 1 +| #define HAVE_SYS_MMAN_H 1 +| #define HAVE_SYS_RESOURCE_H 1 +| #define HAVE_BYTESWAP_H 1 +| #define HAVE_BUILTIN_EXPECT 1 +| #define HAVE_BUILTIN_CTZ 1 +| #define HAVE_LIBZ 1 +| /* end confdefs.h. */ +| +| /* Override any gcc2 internal prototype to avoid an error. */ +| #ifdef __cplusplus +| extern "C" +| #endif +| /* We use char because int might match the return type of a gcc2 +| builtin and then its argument prototype would still apply. */ +| char lzo1x_1_15_compress (); +| int +| main () +| { +| lzo1x_1_15_compress (); +| ; +| return 0; +| } +configure:4158: result: no +configure:4177: checking for lzf_compress in -llzf +configure:4207: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -o conftest -g -O2 conftest.cc -llzf >&5 +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/binutils/binutils-2.21.1/da39a3e/bin/ld: cannot find -llzf +collect2: ld returned 1 exit status +configure:4213: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "snappy" +| #define PACKAGE_TARNAME "snappy" +| #define PACKAGE_VERSION "1.0.5" +| #define PACKAGE_STRING "snappy 1.0.5" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE "snappy" +| #define VERSION "1.0.5" +| #ifdef __cplusplus +| extern "C" void exit (int) throw (); +| #endif +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_STDDEF_H 1 +| #define HAVE_SYS_MMAN_H 1 +| #define HAVE_SYS_RESOURCE_H 1 +| #define HAVE_BYTESWAP_H 1 +| #define HAVE_BUILTIN_EXPECT 1 +| #define HAVE_BUILTIN_CTZ 1 +| #define HAVE_LIBZ 1 +| /* end confdefs.h. */ +| +| /* Override any gcc2 internal prototype to avoid an error. */ +| #ifdef __cplusplus +| extern "C" +| #endif +| /* We use char because int might match the return type of a gcc2 +| builtin and then its argument prototype would still apply. */ +| char lzf_compress (); +| int +| main () +| { +| lzf_compress (); +| ; +| return 0; +| } +configure:4239: result: no +configure:4258: checking for fastlz_compress in -lfastlz +configure:4288: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -o conftest -g -O2 conftest.cc -lfastlz >&5 +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/binutils/binutils-2.21.1/da39a3e/bin/ld: cannot find -lfastlz +collect2: ld returned 1 exit status +configure:4294: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "snappy" +| #define PACKAGE_TARNAME "snappy" +| #define PACKAGE_VERSION "1.0.5" +| #define PACKAGE_STRING "snappy 1.0.5" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE "snappy" +| #define VERSION "1.0.5" +| #ifdef __cplusplus +| extern "C" void exit (int) throw (); +| #endif +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_STDDEF_H 1 +| #define HAVE_SYS_MMAN_H 1 +| #define HAVE_SYS_RESOURCE_H 1 +| #define HAVE_BYTESWAP_H 1 +| #define HAVE_BUILTIN_EXPECT 1 +| #define HAVE_BUILTIN_CTZ 1 +| #define HAVE_LIBZ 1 +| /* end confdefs.h. */ +| +| /* Override any gcc2 internal prototype to avoid an error. */ +| #ifdef __cplusplus +| extern "C" +| #endif +| /* We use char because int might match the return type of a gcc2 +| builtin and then its argument prototype would still apply. */ +| char fastlz_compress (); +| int +| main () +| { +| fastlz_compress (); +| ; +| return 0; +| } +configure:4320: result: no +configure:4339: checking for qlz_compress in -lquicklz +configure:4369: /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -o conftest -g -O2 conftest.cc -lquicklz >&5 +/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/binutils/binutils-2.21.1/da39a3e/bin/ld: cannot find -lquicklz +collect2: ld returned 1 exit status +configure:4375: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "snappy" +| #define PACKAGE_TARNAME "snappy" +| #define PACKAGE_VERSION "1.0.5" +| #define PACKAGE_STRING "snappy 1.0.5" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE "snappy" +| #define VERSION "1.0.5" +| #ifdef __cplusplus +| extern "C" void exit (int) throw (); +| #endif +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_STDDEF_H 1 +| #define HAVE_SYS_MMAN_H 1 +| #define HAVE_SYS_RESOURCE_H 1 +| #define HAVE_BYTESWAP_H 1 +| #define HAVE_BUILTIN_EXPECT 1 +| #define HAVE_BUILTIN_CTZ 1 +| #define HAVE_LIBZ 1 +| /* end confdefs.h. */ +| +| /* Override any gcc2 internal prototype to avoid an error. */ +| #ifdef __cplusplus +| extern "C" +| #endif +| /* We use char because int might match the return type of a gcc2 +| builtin and then its argument prototype would still apply. */ +| char qlz_compress (); +| int +| main () +| { +| qlz_compress (); +| ; +| return 0; +| } +configure:4401: result: no +configure:4566: creating ./config.status + +## ---------------- ## +## Cache variables. ## +## ---------------- ## + +ac_cv_c_bigendian=no +ac_cv_cxx_compiler_gnu=yes +ac_cv_env_CPPFLAGS_set= +ac_cv_env_CPPFLAGS_value= +ac_cv_env_CXXCPP_set= +ac_cv_env_CXXCPP_value= +ac_cv_env_CXXFLAGS_set= +ac_cv_env_CXXFLAGS_value= +ac_cv_env_CXX_set=set +ac_cv_env_CXX_value='/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp' +ac_cv_env_GTEST_CONFIG_set= +ac_cv_env_GTEST_CONFIG_value= +ac_cv_env_GTEST_CPPFLAGS_set= +ac_cv_env_GTEST_CPPFLAGS_value= +ac_cv_env_GTEST_CXXFLAGS_set= +ac_cv_env_GTEST_CXXFLAGS_value= +ac_cv_env_GTEST_LDFLAGS_set= +ac_cv_env_GTEST_LDFLAGS_value= +ac_cv_env_GTEST_LIBS_set= +ac_cv_env_GTEST_LIBS_value= +ac_cv_env_GTEST_VERSION_set= +ac_cv_env_GTEST_VERSION_value= +ac_cv_env_LDFLAGS_set= +ac_cv_env_LDFLAGS_value= +ac_cv_env_PKG_CONFIG_set= +ac_cv_env_PKG_CONFIG_value= +ac_cv_env_build_alias_set= +ac_cv_env_build_alias_value= +ac_cv_env_gflags_CFLAGS_set= +ac_cv_env_gflags_CFLAGS_value= +ac_cv_env_gflags_LIBS_set= +ac_cv_env_gflags_LIBS_value= +ac_cv_env_host_alias_set= +ac_cv_env_host_alias_value= +ac_cv_env_target_alias_set= +ac_cv_env_target_alias_value= +ac_cv_exeext= +ac_cv_func_mmap=yes +ac_cv_have_stddef_h=1 +ac_cv_have_stdint_h=1 +ac_cv_header_byteswap_h=yes +ac_cv_header_inttypes_h=yes +ac_cv_header_memory_h=yes +ac_cv_header_stdc=yes +ac_cv_header_stddef_h=yes +ac_cv_header_stdint_h=yes +ac_cv_header_stdlib_h=yes +ac_cv_header_string_h=yes +ac_cv_header_strings_h=yes +ac_cv_header_sys_byteswap_h=no +ac_cv_header_sys_endian_h=no +ac_cv_header_sys_mman_h=yes +ac_cv_header_sys_resource_h=yes +ac_cv_header_sys_stat_h=yes +ac_cv_header_sys_types_h=yes +ac_cv_header_unistd_h=yes +ac_cv_header_windows_h=no +ac_cv_lib_fastlz_fastlz_compress=no +ac_cv_lib_lzf_lzf_compress=no +ac_cv_lib_lzo2_lzo1x_1_15_compress=no +ac_cv_lib_quicklz_qlz_compress=no +ac_cv_lib_z_zlibVersion=yes +ac_cv_objext=o +ac_cv_path_ac_pt_PKG_CONFIG=/usr/bin/pkg-config +ac_cv_path_install='/usr/bin/install -c' +ac_cv_prog_AWK=gawk +ac_cv_prog_CXXCPP='/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -E' +ac_cv_prog_cxx_g=yes +ac_cv_prog_egrep='grep -E' +ac_cv_prog_make_make_set=yes +am_cv_CXX_dependencies_compiler_type=gcc3 + +## ----------------- ## +## Output variables. ## +## ----------------- ## + +ACLOCAL='${SHELL} /home/dhruba/snappy-1.0.5/missing --run aclocal-1.9' +AMDEPBACKSLASH='\' +AMDEP_FALSE='#' +AMDEP_TRUE='' +AMTAR='${SHELL} /home/dhruba/snappy-1.0.5/missing --run tar' +AUTOCONF='${SHELL} /home/dhruba/snappy-1.0.5/missing --run autoconf' +AUTOHEADER='${SHELL} /home/dhruba/snappy-1.0.5/missing --run autoheader' +AUTOMAKE='${SHELL} /home/dhruba/snappy-1.0.5/missing --run automake-1.9' +AWK='gawk' +CPPFLAGS='' +CXX='/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp' +CXXCPP='/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -E' +CXXDEPMODE='depmode=gcc3' +CXXFLAGS='-g -O2' +CYGPATH_W='echo' +DEFS='-DHAVE_CONFIG_H' +DEPDIR='.deps' +ECHO_C='' +ECHO_N='-n' +ECHO_T='' +EGREP='grep -E' +EXEEXT='' +GTEST_CONFIG='' +GTEST_CPPFLAGS='' +GTEST_CXXFLAGS='' +GTEST_LDFLAGS='' +GTEST_LIBS='' +GTEST_VERSION='' +HAVE_GTEST='no' +HAVE_GTEST_FALSE='' +HAVE_GTEST_TRUE='#' +INSTALL_DATA='${INSTALL} -m 644' +INSTALL_PROGRAM='${INSTALL}' +INSTALL_SCRIPT='${INSTALL}' +INSTALL_STRIP_PROGRAM='${SHELL} $(install_sh) -c -s' +LDFLAGS='' +LIBOBJS='' +LIBS='' +LIBTOOL_DEPS='' +LTLIBOBJS='' +MAKEINFO='${SHELL} /home/dhruba/snappy-1.0.5/missing --run makeinfo' +OBJEXT='o' +PACKAGE='snappy' +PACKAGE_BUGREPORT='' +PACKAGE_NAME='snappy' +PACKAGE_STRING='snappy 1.0.5' +PACKAGE_TARNAME='snappy' +PACKAGE_VERSION='1.0.5' +PATH_SEPARATOR=':' +PKG_CONFIG='/usr/bin/pkg-config' +SET_MAKE='' +SHELL='/bin/sh' +SNAPPY_LTVERSION='2:3:1' +SNAPPY_MAJOR='1' +SNAPPY_MINOR='0' +SNAPPY_PATCHLEVEL='5' +STRIP='' +UNITTEST_LIBS='-lz ' +VERSION='1.0.5' +ac_ct_CXX='' +ac_ct_STRIP='' +ac_cv_have_stddef_h='1' +ac_cv_have_stdint_h='1' +ac_pt_PKG_CONFIG='/usr/bin/pkg-config' +am__fastdepCXX_FALSE='#' +am__fastdepCXX_TRUE='' +am__include='include' +am__leading_dot='.' +am__quote='' +am__tar='${AMTAR} chof - "$$tardir"' +am__untar='${AMTAR} xf -' +bindir='${exec_prefix}/bin' +build_alias='' +datadir='${prefix}/share' +exec_prefix='${prefix}' +gflags_CFLAGS='' +gflags_LIBS='' +host_alias='' +includedir='${prefix}/include' +infodir='${prefix}/info' +install_sh='/home/dhruba/snappy-1.0.5/install-sh' +libdir='${exec_prefix}/lib' +libexecdir='${exec_prefix}/libexec' +localstatedir='${prefix}/var' +mandir='${prefix}/man' +mkdir_p='mkdir -p --' +oldincludedir='/usr/include' +prefix='/usr/local' +program_transform_name='s,x,x,' +sbindir='${exec_prefix}/sbin' +sharedstatedir='${prefix}/com' +sysconfdir='${prefix}/etc' +target_alias='' + +## ----------- ## +## confdefs.h. ## +## ----------- ## + +#define HAVE_BUILTIN_CTZ 1 +#define HAVE_BUILTIN_EXPECT 1 +#define HAVE_BYTESWAP_H 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_LIBZ 1 +#define HAVE_MEMORY_H 1 +#define HAVE_STDDEF_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRINGS_H 1 +#define HAVE_STRING_H 1 +#define HAVE_SYS_MMAN_H 1 +#define HAVE_SYS_RESOURCE_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_UNISTD_H 1 +#define PACKAGE "snappy" +#define PACKAGE_BUGREPORT "" +#define PACKAGE_NAME "snappy" +#define PACKAGE_STRING "snappy 1.0.5" +#define PACKAGE_TARNAME "snappy" +#define PACKAGE_VERSION "1.0.5" +#define STDC_HEADERS 1 +#define VERSION "1.0.5" +#endif +#ifdef __cplusplus +extern "C" void exit (int) throw (); + +configure: exit 0 + +## ---------------------- ## +## Running config.status. ## +## ---------------------- ## + +This file was extended by snappy config.status 1.0.5, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = + CONFIG_HEADERS = + CONFIG_LINKS = + CONFIG_COMMANDS = + $ ./config.status config.h + +on dev3936.snc6.facebook.com + +config.status:815: creating config.h +config.status:937: config.h is unchanged + +## ---------------------- ## +## Running config.status. ## +## ---------------------- ## + +This file was extended by snappy config.status 1.0.5, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = + CONFIG_HEADERS = + CONFIG_LINKS = + CONFIG_COMMANDS = + $ ./config.status snappy-stubs-public.h + +on dev3936.snc6.facebook.com + +config.status:711: creating snappy-stubs-public.h diff --git a/snappy/snappy-1.0.5/config.status b/snappy/snappy-1.0.5/config.status new file mode 100755 index 00000000..93eb95da --- /dev/null +++ b/snappy/snappy-1.0.5/config.status @@ -0,0 +1,1208 @@ +#! /bin/sh +# Generated by configure. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=${CONFIG_SHELL-/bin/sh} +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# 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'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by snappy $as_me 1.0.5, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +config_files=" Makefile snappy-stubs-public.h" +config_headers=" config.h" +config_commands=" depfiles" + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, 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 + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." +ac_cs_version="\ +snappy config.status 1.0.5 +configured by ./configure, generated by GNU Autoconf 2.59, + with options \"'--disable-shared' '--with-pic' 'CXX=/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp'\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=. +INSTALL="/usr/bin/install -c" +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +if $ac_cs_recheck; then + echo "running /bin/sh ./configure " '--disable-shared' '--with-pic' 'CXX=/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp' $ac_configure_extra_args " --no-create --no-recursion" >&6 + exec /bin/sh ./configure '--disable-shared' '--with-pic' 'CXX=/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp' $ac_configure_extra_args --no-create --no-recursion +fi + +# +# INIT-COMMANDS section. +# + +AMDEP_TRUE="" ac_aux_dir="." + +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "snappy-stubs-public.h" ) CONFIG_FILES="$CONFIG_FILES snappy-stubs-public.h" ;; + "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t$/@;t t/; /@;t t$/s/[\\&,]/\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t$/,;t t/' >$tmp/subs.sed <<\CEOF +s,@SHELL@,/bin/sh,;t t +s,@PATH_SEPARATOR@,:,;t t +s,@PACKAGE_NAME@,snappy,;t t +s,@PACKAGE_TARNAME@,snappy,;t t +s,@PACKAGE_VERSION@,1.0.5,;t t +s,@PACKAGE_STRING@,snappy 1.0.5,;t t +s,@PACKAGE_BUGREPORT@,,;t t +s,@exec_prefix@,${prefix},;t t +s,@prefix@,/usr/local,;t t +s,@program_transform_name@,s,x,x,,;t t +s,@bindir@,${exec_prefix}/bin,;t t +s,@sbindir@,${exec_prefix}/sbin,;t t +s,@libexecdir@,${exec_prefix}/libexec,;t t +s,@datadir@,${prefix}/share,;t t +s,@sysconfdir@,${prefix}/etc,;t t +s,@sharedstatedir@,${prefix}/com,;t t +s,@localstatedir@,${prefix}/var,;t t +s,@libdir@,${exec_prefix}/lib,;t t +s,@includedir@,${prefix}/include,;t t +s,@oldincludedir@,/usr/include,;t t +s,@infodir@,${prefix}/info,;t t +s,@mandir@,${prefix}/man,;t t +s,@build_alias@,,;t t +s,@host_alias@,,;t t +s,@target_alias@,,;t t +s,@DEFS@,-DHAVE_CONFIG_H,;t t +s,@ECHO_C@,,;t t +s,@ECHO_N@,-n,;t t +s,@ECHO_T@,,;t t +s,@LIBS@,,;t t +s,@INSTALL_PROGRAM@,${INSTALL},;t t +s,@INSTALL_SCRIPT@,${INSTALL},;t t +s,@INSTALL_DATA@,${INSTALL} -m 644,;t t +s,@CYGPATH_W@,echo,;t t +s,@PACKAGE@,snappy,;t t +s,@VERSION@,1.0.5,;t t +s,@ACLOCAL@,${SHELL} /home/dhruba/snappy-1.0.5/missing --run aclocal-1.9,;t t +s,@AUTOCONF@,${SHELL} /home/dhruba/snappy-1.0.5/missing --run autoconf,;t t +s,@AUTOMAKE@,${SHELL} /home/dhruba/snappy-1.0.5/missing --run automake-1.9,;t t +s,@AUTOHEADER@,${SHELL} /home/dhruba/snappy-1.0.5/missing --run autoheader,;t t +s,@MAKEINFO@,${SHELL} /home/dhruba/snappy-1.0.5/missing --run makeinfo,;t t +s,@install_sh@,/home/dhruba/snappy-1.0.5/install-sh,;t t +s,@STRIP@,,;t t +s,@ac_ct_STRIP@,,;t t +s,@INSTALL_STRIP_PROGRAM@,${SHELL} $(install_sh) -c -s,;t t +s,@mkdir_p@,mkdir -p --,;t t +s,@AWK@,gawk,;t t +s,@SET_MAKE@,,;t t +s,@am__leading_dot@,.,;t t +s,@AMTAR@,${SHELL} /home/dhruba/snappy-1.0.5/missing --run tar,;t t +s,@am__tar@,${AMTAR} chof - "$$tardir",;t t +s,@am__untar@,${AMTAR} xf -,;t t +s,@LIBTOOL_DEPS@,,;t t +s,@CXX@,/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp,;t t +s,@CXXFLAGS@,-g -O2,;t t +s,@LDFLAGS@,,;t t +s,@CPPFLAGS@,,;t t +s,@ac_ct_CXX@,,;t t +s,@EXEEXT@,,;t t +s,@OBJEXT@,o,;t t +s,@DEPDIR@,.deps,;t t +s,@am__include@,include,;t t +s,@am__quote@,,;t t +s,@AMDEP_TRUE@,,;t t +s,@AMDEP_FALSE@,#,;t t +s,@AMDEPBACKSLASH@,\,;t t +s,@CXXDEPMODE@,depmode=gcc3,;t t +s,@am__fastdepCXX_TRUE@,,;t t +s,@am__fastdepCXX_FALSE@,#,;t t +s,@CXXCPP@,/mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -I ./snappy -I /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/boost/default/eed002c/include -std=gnu++0x -I./thrift -I./thrift/gen-cpp -I./thrift/lib/cpp -E,;t t +s,@EGREP@,grep -E,;t t +s,@GTEST_CONFIG@,,;t t +s,@GTEST_CPPFLAGS@,,;t t +s,@GTEST_CXXFLAGS@,,;t t +s,@GTEST_LDFLAGS@,,;t t +s,@GTEST_LIBS@,,;t t +s,@GTEST_VERSION@,,;t t +s,@HAVE_GTEST@,no,;t t +s,@HAVE_GTEST_TRUE@,#,;t t +s,@HAVE_GTEST_FALSE@,,;t t +s,@PKG_CONFIG@,/usr/bin/pkg-config,;t t +s,@ac_pt_PKG_CONFIG@,/usr/bin/pkg-config,;t t +s,@gflags_CFLAGS@,,;t t +s,@gflags_LIBS@,,;t t +s,@UNITTEST_LIBS@,-lz ,;t t +s,@ac_cv_have_stdint_h@,1,;t t +s,@ac_cv_have_stddef_h@,1,;t t +s,@SNAPPY_MAJOR@,1,;t t +s,@SNAPPY_MINOR@,0,;t t +s,@SNAPPY_PATCHLEVEL@,5,;t t +s,@SNAPPY_LTVERSION@,2:3:1,;t t +s,@LIBOBJS@,,;t t +s,@LTLIBOBJS@,,;t t +CEOF + + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + sed "/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +} + +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done + +# +# CONFIG_HEADER section. +# + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' +ac_dC=' ' +ac_dD=',;t' +# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='$,\1#\2define\3' +ac_uC=' ' +ac_uD=',;t' + +for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + # Do quote $f, to prevent DOS paths from being IFS'd. + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + # Remove the trailing spaces. + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + + # Handle all the #define templates only if necessary. + if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then + # If there are no defines, we may have an empty if/fi + : + cat >$tmp/defines.sed <$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in + + fi # grep + + # Handle all the #undef templates + cat >$tmp/undefs.sed <$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + echo "/* Generated by configure. */" >$tmp/config.h + else + echo "/* $ac_file. Generated by configure. */" >$tmp/config.h + fi + cat $tmp/in >>$tmp/config.h + rm -f $tmp/in + if test x"$ac_file" != x-; then + if diff $ac_file $tmp/config.h >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + rm -f $ac_file + mv $tmp/config.h $ac_file + fi + else + cat $tmp/config.h + rm -f $tmp/config.h + fi +# Compute $ac_file's index in $config_headers. +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $ac_file | $ac_file:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $ac_file" >`(dirname $ac_file) 2>/dev/null || +$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X$ac_file : 'X\(//\)[^/]' \| \ + X$ac_file : 'X\(//\)$' \| \ + X$ac_file : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X$ac_file | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'`/stamp-h$_am_stamp_count +done + +# +# CONFIG_COMMANDS section. +# +for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue + ac_dest=`echo "$ac_file" | sed 's,:.*,,'` + ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_dir=`(dirname "$ac_dest") 2>/dev/null || +$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_dest" : 'X\(//\)[^/]' \| \ + X"$ac_dest" : 'X\(//\)$' \| \ + X"$ac_dest" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_dest" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 +echo "$as_me: executing $ac_dest commands" >&6;} + case $ac_dest in + depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + dirpart=`(dirname "$mf") 2>/dev/null || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`(dirname "$file") 2>/dev/null || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p $dirpart/$fdir + else + as_dir=$dirpart/$fdir + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5 +echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;} + { (exit 1); exit 1; }; }; } + + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done + ;; + esac +done + +{ (exit 0); exit 0; } diff --git a/snappy/snappy-1.0.5/config.sub b/snappy/snappy-1.0.5/config.sub new file mode 100755 index 00000000..eb0389a6 --- /dev/null +++ b/snappy/snappy-1.0.5/config.sub @@ -0,0 +1,1693 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. + +timestamp='2009-06-11' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/snappy/snappy-1.0.5/configure b/snappy/snappy-1.0.5/configure new file mode 100755 index 00000000..5fc8a4a2 --- /dev/null +++ b/snappy/snappy-1.0.5/configure @@ -0,0 +1,5872 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.59 for snappy 1.0.5. +# +# Copyright (C) 2003 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# 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'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME='snappy' +PACKAGE_TARNAME='snappy' +PACKAGE_VERSION='1.0.5' +PACKAGE_STRING='snappy 1.0.5' +PACKAGE_BUGREPORT='' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif +#if HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar LIBTOOL_DEPS CXX CXXFLAGS LDFLAGS CPPFLAGS ac_ct_CXX EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CXXCPP EGREP GTEST_CONFIG GTEST_CPPFLAGS GTEST_CXXFLAGS GTEST_LDFLAGS GTEST_LIBS GTEST_VERSION HAVE_GTEST HAVE_GTEST_TRUE HAVE_GTEST_FALSE PKG_CONFIG ac_pt_PKG_CONFIG gflags_CFLAGS gflags_LIBS UNITTEST_LIBS ac_cv_have_stdint_h ac_cv_have_stddef_h SNAPPY_MAJOR SNAPPY_MINOR SNAPPY_PATCHLEVEL SNAPPY_LTVERSION LIBOBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -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 && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -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 && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -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 && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + 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 && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CXX_set=${CXX+set} +ac_env_CXX_value=$CXX +ac_cv_env_CXX_set=${CXX+set} +ac_cv_env_CXX_value=$CXX +ac_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_env_CXXFLAGS_value=$CXXFLAGS +ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_cv_env_CXXFLAGS_value=$CXXFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CXXCPP_set=${CXXCPP+set} +ac_env_CXXCPP_value=$CXXCPP +ac_cv_env_CXXCPP_set=${CXXCPP+set} +ac_cv_env_CXXCPP_value=$CXXCPP +ac_env_GTEST_CONFIG_set=${GTEST_CONFIG+set} +ac_env_GTEST_CONFIG_value=$GTEST_CONFIG +ac_cv_env_GTEST_CONFIG_set=${GTEST_CONFIG+set} +ac_cv_env_GTEST_CONFIG_value=$GTEST_CONFIG +ac_env_GTEST_CPPFLAGS_set=${GTEST_CPPFLAGS+set} +ac_env_GTEST_CPPFLAGS_value=$GTEST_CPPFLAGS +ac_cv_env_GTEST_CPPFLAGS_set=${GTEST_CPPFLAGS+set} +ac_cv_env_GTEST_CPPFLAGS_value=$GTEST_CPPFLAGS +ac_env_GTEST_CXXFLAGS_set=${GTEST_CXXFLAGS+set} +ac_env_GTEST_CXXFLAGS_value=$GTEST_CXXFLAGS +ac_cv_env_GTEST_CXXFLAGS_set=${GTEST_CXXFLAGS+set} +ac_cv_env_GTEST_CXXFLAGS_value=$GTEST_CXXFLAGS +ac_env_GTEST_LDFLAGS_set=${GTEST_LDFLAGS+set} +ac_env_GTEST_LDFLAGS_value=$GTEST_LDFLAGS +ac_cv_env_GTEST_LDFLAGS_set=${GTEST_LDFLAGS+set} +ac_cv_env_GTEST_LDFLAGS_value=$GTEST_LDFLAGS +ac_env_GTEST_LIBS_set=${GTEST_LIBS+set} +ac_env_GTEST_LIBS_value=$GTEST_LIBS +ac_cv_env_GTEST_LIBS_set=${GTEST_LIBS+set} +ac_cv_env_GTEST_LIBS_value=$GTEST_LIBS +ac_env_GTEST_VERSION_set=${GTEST_VERSION+set} +ac_env_GTEST_VERSION_value=$GTEST_VERSION +ac_cv_env_GTEST_VERSION_set=${GTEST_VERSION+set} +ac_cv_env_GTEST_VERSION_value=$GTEST_VERSION +ac_env_PKG_CONFIG_set=${PKG_CONFIG+set} +ac_env_PKG_CONFIG_value=$PKG_CONFIG +ac_cv_env_PKG_CONFIG_set=${PKG_CONFIG+set} +ac_cv_env_PKG_CONFIG_value=$PKG_CONFIG +ac_env_gflags_CFLAGS_set=${gflags_CFLAGS+set} +ac_env_gflags_CFLAGS_value=$gflags_CFLAGS +ac_cv_env_gflags_CFLAGS_set=${gflags_CFLAGS+set} +ac_cv_env_gflags_CFLAGS_value=$gflags_CFLAGS +ac_env_gflags_LIBS_set=${gflags_LIBS+set} +ac_env_gflags_LIBS_value=$gflags_LIBS +ac_cv_env_gflags_LIBS_set=${gflags_LIBS+set} +ac_cv_env_gflags_LIBS_value=$gflags_LIBS + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures snappy 1.0.5 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of snappy 1.0.5:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + --enable-gtest Enable tests using the Google C++ Testing Framework. + (Default is enabled.) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-gflags use Google Flags package to enhance the unit test + [default=check] + +Some influential environment variables: + CXX C++ compiler command + CXXFLAGS C++ compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + CXXCPP C++ preprocessor + GTEST_CONFIG + The exact path of Google Test's 'gtest-config' script. + GTEST_CPPFLAGS + C-like preprocessor flags for Google Test. + GTEST_CXXFLAGS + C++ compile flags for Google Test. + GTEST_LDFLAGS + Linker path and option flags for Google Test. + GTEST_LIBS Library linking flags for Google Test. + GTEST_VERSION + The version of Google Test available. + PKG_CONFIG path to pkg-config utility + gflags_CFLAGS + C compiler flags for gflags, overriding pkg-config + gflags_LIBS linker flags for gflags, overriding pkg-config + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF +snappy configure 1.0.5 +generated by GNU Autoconf 2.59 + +Copyright (C) 2003 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by snappy $as_me 1.0.5, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + + + + + + + + +case m4 in + [\\/]* | ?:[\\/]* ) ac_macro_dir=m4 ;; + *) ac_macro_dir=$srcdir/m4 ;; +esac +if test -d "$ac_macro_dir"; then : +else + { { echo "$as_me:$LINENO: error: cannot find macro directory \`m4'" >&5 +echo "$as_me: error: cannot find macro directory \`m4'" >&2;} + { (exit 1); exit 1; }; } +fi + + +# These are flags passed to automake (though they look like gcc flags!) +am__api_version="1.9" +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$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. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo "$as_me:$LINENO: checking whether build environment is sane" >&5 +echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6 +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&5 +echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&2;} + { (exit 1); exit 1; }; } + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! +Check your system clock" >&5 +echo "$as_me: error: newly created file is older than distributed files! +Check your system clock" >&2;} + { (exit 1); exit 1; }; } +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +test "$program_prefix" != NONE && + program_transform_name="s,^,$program_prefix,;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$,$program_suffix,;$program_transform_name" +# Double any \ or $. echo might interpret backslashes. +# By default was `s,x,x', remove it if useless. +cat <<\_ACEOF >conftest.sed +s/[\\$]/&&/g;s/;s,x,x,$// +_ACEOF +program_transform_name=`echo $program_transform_name | sed -f conftest.sed` +rm conftest.sed + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 +echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + # We used to keeping the `.' as first argument, in order to + # allow $(mkdir_p) to be used without argument. As in + # $(mkdir_p) $(somedir) + # where $(somedir) is conditionally defined. However this is wrong + # for two reasons: + # 1. if the package is installed by a user who cannot write `.' + # make install will fail, + # 2. the above comment should most certainly read + # $(mkdir_p) $(DESTDIR)$(somedir) + # so it does not work when $(somedir) is undefined and + # $(DESTDIR) is not. + # To support the latter case, we have to write + # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), + # so the `.' trick is pointless. + mkdir_p='mkdir -p --' +else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + for d in ./-p ./--version; + do + test -d $d && rmdir $d + done + # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. + if test -f "$ac_aux_dir/mkinstalldirs"; then + mkdir_p='$(mkinstalldirs)' + else + mkdir_p='$(install_sh) -d' + fi +fi + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_AWK+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$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 + fi +done +done + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + echo "$as_me:$LINENO: result: $AWK" >&5 +echo "${ECHO_T}$AWK" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$AWK" && break +done + +echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="$(MAKE)"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 +echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} + { (exit 1); exit 1; }; } +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='snappy' + VERSION='1.0.5' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +install_sh=${install_sh-"$am_aux_dir/install-sh"} + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$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 + fi +done +done + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$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 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + STRIP=$ac_ct_STRIP +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. + +AMTAR=${AMTAR-"${am_missing_run}tar"} + +am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' + + + + + + +LT_INIT + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC + 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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$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 + fi +done +done + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$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 + fi +done +done + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CXX" && break +done +test -n "$ac_ct_CXX" || ac_ct_CXX="g++" + + CXX=$ac_ct_CXX +fi + + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C++ compiler default output file name" >&5 +echo $ECHO_N "checking for C++ compiler default output file name... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C++ compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C++ compiler works" >&5 +echo $ECHO_N "checking whether the C++ compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C++ compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C++ compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +CXXFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cxx_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +DEPDIR="${am__leading_dot}deps" + + ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo done +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 +echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6 +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi + + +echo "$as_me:$LINENO: result: $_am_result" >&5 +echo "${ECHO_T}$_am_result" >&6 +rm -f confinc confmf + +# Check whether --enable-dependency-tracking or --disable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then + enableval="$enable_dependency_tracking" + +fi; +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi + + +if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + + +depcc="$CXX" am_compiler_list= + +echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 +if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 +echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6 +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + + +if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 +echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6 +if test "${ac_cv_c_bigendian+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # See if sys/param.h defines the BYTE_ORDER macro. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + # It does; now see whether it defined to BIG_ENDIAN or not. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_c_bigendian=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +# It does not; compile a test program. +if test "$cross_compiling" = yes; then + # try to guess the endianness by grepping values into an object file + ac_cv_c_bigendian=unknown + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; +short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; +void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } +short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; +short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; +void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } +int +main () +{ + _ascii (); _ebcdic (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then + ac_cv_c_bigendian=yes +fi +if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +int +main () +{ + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long l; + char c[sizeof (long)]; + } u; + u.l = 1; + exit (u.c[sizeof (long) - 1] == 1); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_bigendian=yes +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 +echo "${ECHO_T}$ac_cv_c_bigendian" >&6 +case $ac_cv_c_bigendian in + yes) + +cat >>confdefs.h <<\_ACEOF +#define WORDS_BIGENDIAN 1 +_ACEOF + ;; + no) + ;; + *) + { { echo "$as_me:$LINENO: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&5 +echo "$as_me: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 +echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6 +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 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); } >/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 + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 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); } >/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 + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +echo "$as_me:$LINENO: result: $CXXCPP" >&5 +echo "${ECHO_T}$CXXCPP" >&6 +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 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); } >/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 + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 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); } >/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 + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + + + + + +for ac_header in stdint.h stddef.h sys/mman.h sys/resource.h windows.h byteswap.h sys/byteswap.h sys/endian.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 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); } >/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 + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the snappy lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +# Don't use AC_FUNC_MMAP, as it checks for mappings of already-mapped memory, +# which we don't need (and does not exist on Windows). +echo "$as_me:$LINENO: checking for mmap" >&5 +echo $ECHO_N "checking for mmap... $ECHO_C" >&6 +if test "${ac_cv_func_mmap+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define mmap to an innocuous variant, in case declares mmap. + For example, HP-UX 11i declares gettimeofday. */ +#define mmap innocuous_mmap + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char mmap (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef mmap + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char mmap (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_mmap) || defined (__stub___mmap) +choke me +#else +char (*f) () = mmap; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != mmap; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_mmap=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_mmap=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_mmap" >&5 +echo "${ECHO_T}$ac_cv_func_mmap" >&6 + + + +# Check whether --enable-gtest or --disable-gtest was given. +if test "${enable_gtest+set}" = set; then + enableval="$enable_gtest" + +else + enable_gtest= +fi; + + + + + + +HAVE_GTEST="no" +if test "x${enable_gtest}" != "xno"; then + echo "$as_me:$LINENO: checking for 'gtest-config'" >&5 +echo $ECHO_N "checking for 'gtest-config'... $ECHO_C" >&6 + if test "x${enable_gtest}" = "xyes"; then + if test -x "${enable_gtest}/scripts/gtest-config"; then + GTEST_CONFIG="${enable_gtest}/scripts/gtest-config" +else + GTEST_CONFIG="${enable_gtest}/bin/gtest-config" +fi + + if test -x "${GTEST_CONFIG}"; then + : +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + { { echo "$as_me:$LINENO: error: Unable to locate either a built or installed Google Test. +The specific location '${enable_gtest}' was provided for a built or installed +Google Test, but no 'gtest-config' script could be found at this location." >&5 +echo "$as_me: error: Unable to locate either a built or installed Google Test. +The specific location '${enable_gtest}' was provided for a built or installed +Google Test, but no 'gtest-config' script could be found at this location." >&2;} + { (exit 1); exit 1; }; } + +fi + +else + # Extract the first word of "gtest-config", so it can be a program name with args. +set dummy gtest-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_GTEST_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GTEST_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_GTEST_CONFIG="$GTEST_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GTEST_CONFIG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +GTEST_CONFIG=$ac_cv_path_GTEST_CONFIG + +if test -n "$GTEST_CONFIG"; then + echo "$as_me:$LINENO: result: $GTEST_CONFIG" >&5 +echo "${ECHO_T}$GTEST_CONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi + + if test -x "${GTEST_CONFIG}"; then + echo "$as_me:$LINENO: result: ${GTEST_CONFIG}" >&5 +echo "${ECHO_T}${GTEST_CONFIG}" >&6 + _gtest_min_version="--min-version=0" + echo "$as_me:$LINENO: checking for Google Test" >&5 +echo $ECHO_N "checking for Google Test... $ECHO_C" >&6 + if ${GTEST_CONFIG} ${_gtest_min_version}; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + HAVE_GTEST='yes' +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + if test "x${HAVE_GTEST}" = "xyes"; then + GTEST_CPPFLAGS=`${GTEST_CONFIG} --cppflags` + GTEST_CXXFLAGS=`${GTEST_CONFIG} --cxxflags` + GTEST_LDFLAGS=`${GTEST_CONFIG} --ldflags` + GTEST_LIBS=`${GTEST_CONFIG} --libs` + GTEST_VERSION=`${GTEST_CONFIG} --version` + +cat >>confdefs.h <<\_ACEOF +#define HAVE_GTEST 1 +_ACEOF + +else + if test "x${enable_gtest}" = "xyes"; then + { { echo "$as_me:$LINENO: error: Google Test was enabled, but no viable version could be found." >&5 +echo "$as_me: error: Google Test was enabled, but no viable version could be found." >&2;} + { (exit 1); exit 1; }; } + +fi + +fi + +fi + + + + +if test "x$HAVE_GTEST" = "xyes"; then + HAVE_GTEST_TRUE= + HAVE_GTEST_FALSE='#' +else + HAVE_GTEST_TRUE='#' + HAVE_GTEST_FALSE= +fi + +if test "x$HAVE_GTEST" = "xyes"; then + true +else + true # Ignore; we can live without it. +fi + + + + +# Check whether --with-gflags or --without-gflags was given. +if test "${with_gflags+set}" = set; then + withval="$with_gflags" + +else + with_gflags=check +fi; + +if test "x$with_gflags" != "xno"; then + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_PKG_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG + +if test -n "$PKG_CONFIG"; then + echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5 +echo "${ECHO_T}$PKG_CONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG + +if test -n "$ac_pt_PKG_CONFIG"; then + echo "$as_me:$LINENO: result: $ac_pt_PKG_CONFIG" >&5 +echo "${ECHO_T}$ac_pt_PKG_CONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + PKG_CONFIG=$ac_pt_PKG_CONFIG +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + echo "$as_me:$LINENO: checking pkg-config is at least version $_pkg_min_version" >&5 +echo $ECHO_N "checking pkg-config is at least version $_pkg_min_version... $ECHO_C" >&6 + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + PKG_CONFIG="" + fi + +fi + +pkg_failed=no +echo "$as_me:$LINENO: checking for gflags" >&5 +echo $ECHO_N "checking for gflags... $ECHO_C" >&6 + +if test -n "$PKG_CONFIG"; then + if test -n "$gflags_CFLAGS"; then + pkg_cv_gflags_CFLAGS="$gflags_CFLAGS" + else + if test -n "$PKG_CONFIG" && \ + { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"libgflags\"") >&5 + ($PKG_CONFIG --exists --print-errors "libgflags") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + pkg_cv_gflags_CFLAGS=`$PKG_CONFIG --cflags "libgflags" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi +if test -n "$PKG_CONFIG"; then + if test -n "$gflags_LIBS"; then + pkg_cv_gflags_LIBS="$gflags_LIBS" + else + if test -n "$PKG_CONFIG" && \ + { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"libgflags\"") >&5 + ($PKG_CONFIG --exists --print-errors "libgflags") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + pkg_cv_gflags_LIBS=`$PKG_CONFIG --libs "libgflags" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + gflags_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "libgflags"` + else + gflags_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "libgflags"` + fi + # Put the nasty error message in config.log where it belongs + echo "$gflags_PKG_ERRORS" >&5 + + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + if test "x$with_gflags" != "xcheck"; then + { { echo "$as_me:$LINENO: error: --with-gflags was given, but test for gflags failed +See \`config.log' for more details." >&5 +echo "$as_me: error: --with-gflags was given, but test for gflags failed +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi +elif test $pkg_failed = untried; then + if test "x$with_gflags" != "xcheck"; then + { { echo "$as_me:$LINENO: error: --with-gflags was given, but test for gflags failed +See \`config.log' for more details." >&5 +echo "$as_me: error: --with-gflags was given, but test for gflags failed +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi +else + gflags_CFLAGS=$pkg_cv_gflags_CFLAGS + gflags_LIBS=$pkg_cv_gflags_LIBS + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +cat >>confdefs.h <<\_ACEOF +#define HAVE_GFLAGS 1 +_ACEOF + +fi +fi + +# See if we have __builtin_expect. +# TODO: Use AC_CACHE. +echo "$as_me:$LINENO: checking if the compiler supports __builtin_expect" >&5 +echo $ECHO_N "checking if the compiler supports __builtin_expect... $ECHO_C" >&6 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + return __builtin_expect(1, 1) ? 1 : 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + snappy_have_builtin_expect=yes + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + snappy_have_builtin_expect=no + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +if test x$snappy_have_builtin_expect = xyes ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_BUILTIN_EXPECT 1 +_ACEOF + +fi + +# See if we have working count-trailing-zeros intrinsics. +# TODO: Use AC_CACHE. +echo "$as_me:$LINENO: checking if the compiler supports __builtin_ctzll" >&5 +echo $ECHO_N "checking if the compiler supports __builtin_ctzll... $ECHO_C" >&6 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + return (__builtin_ctzll(0x100000000LL) == 32) ? 1 : 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + snappy_have_builtin_ctz=yes + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + snappy_have_builtin_ctz=no + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +if test x$snappy_have_builtin_ctz = xyes ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_BUILTIN_CTZ 1 +_ACEOF + +fi + +# Other compression libraries; the unit test can use these for comparison +# if they are available. If they are not found, just ignore. +UNITTEST_LIBS="" + + + + + echo "$as_me:$LINENO: checking for zlibVersion in -lz" >&5 +echo $ECHO_N "checking for zlibVersion in -lz... $ECHO_C" >&6 +if test "${ac_cv_lib_z_zlibVersion+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $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 gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char zlibVersion (); +int +main () +{ +zlibVersion (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_z_zlibVersion=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_z_zlibVersion=no +fi +rm -f 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_z_zlibVersion" >&5 +echo "${ECHO_T}$ac_cv_lib_z_zlibVersion" >&6 +if test $ac_cv_lib_z_zlibVersion = yes; then + + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBZ 1 +_ACEOF + + UNITTEST_LIBS="-lz $UNITTEST_LIBS" + +else + true + +fi + + + + + + echo "$as_me:$LINENO: checking for lzo1x_1_15_compress in -llzo2" >&5 +echo $ECHO_N "checking for lzo1x_1_15_compress in -llzo2... $ECHO_C" >&6 +if test "${ac_cv_lib_lzo2_lzo1x_1_15_compress+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llzo2 $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 gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char lzo1x_1_15_compress (); +int +main () +{ +lzo1x_1_15_compress (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_lzo2_lzo1x_1_15_compress=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_lzo2_lzo1x_1_15_compress=no +fi +rm -f 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_lzo2_lzo1x_1_15_compress" >&5 +echo "${ECHO_T}$ac_cv_lib_lzo2_lzo1x_1_15_compress" >&6 +if test $ac_cv_lib_lzo2_lzo1x_1_15_compress = yes; then + + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBLZO2 1 +_ACEOF + + UNITTEST_LIBS="-llzo2 $UNITTEST_LIBS" + +else + true + +fi + + + + + + echo "$as_me:$LINENO: checking for lzf_compress in -llzf" >&5 +echo $ECHO_N "checking for lzf_compress in -llzf... $ECHO_C" >&6 +if test "${ac_cv_lib_lzf_lzf_compress+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llzf $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 gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char lzf_compress (); +int +main () +{ +lzf_compress (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_lzf_lzf_compress=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_lzf_lzf_compress=no +fi +rm -f 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_lzf_lzf_compress" >&5 +echo "${ECHO_T}$ac_cv_lib_lzf_lzf_compress" >&6 +if test $ac_cv_lib_lzf_lzf_compress = yes; then + + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBLZF 1 +_ACEOF + + UNITTEST_LIBS="-llzf $UNITTEST_LIBS" + +else + true + +fi + + + + + + echo "$as_me:$LINENO: checking for fastlz_compress in -lfastlz" >&5 +echo $ECHO_N "checking for fastlz_compress in -lfastlz... $ECHO_C" >&6 +if test "${ac_cv_lib_fastlz_fastlz_compress+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lfastlz $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 gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char fastlz_compress (); +int +main () +{ +fastlz_compress (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_fastlz_fastlz_compress=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_fastlz_fastlz_compress=no +fi +rm -f 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_fastlz_fastlz_compress" >&5 +echo "${ECHO_T}$ac_cv_lib_fastlz_fastlz_compress" >&6 +if test $ac_cv_lib_fastlz_fastlz_compress = yes; then + + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBFASTLZ 1 +_ACEOF + + UNITTEST_LIBS="-lfastlz $UNITTEST_LIBS" + +else + true + +fi + + + + + + echo "$as_me:$LINENO: checking for qlz_compress in -lquicklz" >&5 +echo $ECHO_N "checking for qlz_compress in -lquicklz... $ECHO_C" >&6 +if test "${ac_cv_lib_quicklz_qlz_compress+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lquicklz $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 gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char qlz_compress (); +int +main () +{ +qlz_compress (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_quicklz_qlz_compress=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_quicklz_qlz_compress=no +fi +rm -f 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_quicklz_qlz_compress" >&5 +echo "${ECHO_T}$ac_cv_lib_quicklz_qlz_compress" >&6 +if test $ac_cv_lib_quicklz_qlz_compress = yes; then + + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBQUICKLZ 1 +_ACEOF + + UNITTEST_LIBS="-lquicklz $UNITTEST_LIBS" + +else + true + +fi + + + + +# These are used by snappy-stubs-public.h.in. +if test "$ac_cv_header_stdint_h" = "yes"; then + ac_cv_have_stdint_h=1 + +else + ac_cv_have_stdint_h=0 + +fi +if test "$ac_cv_header_stddef_h" = "yes"; then + ac_cv_have_stddef_h=1 + +else + ac_cv_have_stddef_h=0 + +fi + +# Export the version to snappy-stubs-public.h. +SNAPPY_MAJOR="1" +SNAPPY_MINOR="0" +SNAPPY_PATCHLEVEL="5" + + + + +SNAPPY_LTVERSION=2:3:1 + + + ac_config_headers="$ac_config_headers config.h" + + ac_config_files="$ac_config_files Makefile snappy-stubs-public.h" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${HAVE_GTEST_TRUE}" && test -z "${HAVE_GTEST_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"HAVE_GTEST\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"HAVE_GTEST\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# 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'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by snappy $as_me 1.0.5, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, 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 + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +snappy config.status 1.0.5 +configured by $0, generated by GNU Autoconf 2.59, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# +# INIT-COMMANDS section. +# + +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + +_ACEOF + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "snappy-stubs-public.h" ) CONFIG_FILES="$CONFIG_FILES snappy-stubs-public.h" ;; + "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@CYGPATH_W@,$CYGPATH_W,;t t +s,@PACKAGE@,$PACKAGE,;t t +s,@VERSION@,$VERSION,;t t +s,@ACLOCAL@,$ACLOCAL,;t t +s,@AUTOCONF@,$AUTOCONF,;t t +s,@AUTOMAKE@,$AUTOMAKE,;t t +s,@AUTOHEADER@,$AUTOHEADER,;t t +s,@MAKEINFO@,$MAKEINFO,;t t +s,@install_sh@,$install_sh,;t t +s,@STRIP@,$STRIP,;t t +s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t +s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t +s,@mkdir_p@,$mkdir_p,;t t +s,@AWK@,$AWK,;t t +s,@SET_MAKE@,$SET_MAKE,;t t +s,@am__leading_dot@,$am__leading_dot,;t t +s,@AMTAR@,$AMTAR,;t t +s,@am__tar@,$am__tar,;t t +s,@am__untar@,$am__untar,;t t +s,@LIBTOOL_DEPS@,$LIBTOOL_DEPS,;t t +s,@CXX@,$CXX,;t t +s,@CXXFLAGS@,$CXXFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CXX@,$ac_ct_CXX,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@DEPDIR@,$DEPDIR,;t t +s,@am__include@,$am__include,;t t +s,@am__quote@,$am__quote,;t t +s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t +s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t +s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t +s,@CXXDEPMODE@,$CXXDEPMODE,;t t +s,@am__fastdepCXX_TRUE@,$am__fastdepCXX_TRUE,;t t +s,@am__fastdepCXX_FALSE@,$am__fastdepCXX_FALSE,;t t +s,@CXXCPP@,$CXXCPP,;t t +s,@EGREP@,$EGREP,;t t +s,@GTEST_CONFIG@,$GTEST_CONFIG,;t t +s,@GTEST_CPPFLAGS@,$GTEST_CPPFLAGS,;t t +s,@GTEST_CXXFLAGS@,$GTEST_CXXFLAGS,;t t +s,@GTEST_LDFLAGS@,$GTEST_LDFLAGS,;t t +s,@GTEST_LIBS@,$GTEST_LIBS,;t t +s,@GTEST_VERSION@,$GTEST_VERSION,;t t +s,@HAVE_GTEST@,$HAVE_GTEST,;t t +s,@HAVE_GTEST_TRUE@,$HAVE_GTEST_TRUE,;t t +s,@HAVE_GTEST_FALSE@,$HAVE_GTEST_FALSE,;t t +s,@PKG_CONFIG@,$PKG_CONFIG,;t t +s,@ac_pt_PKG_CONFIG@,$ac_pt_PKG_CONFIG,;t t +s,@gflags_CFLAGS@,$gflags_CFLAGS,;t t +s,@gflags_LIBS@,$gflags_LIBS,;t t +s,@UNITTEST_LIBS@,$UNITTEST_LIBS,;t t +s,@ac_cv_have_stdint_h@,$ac_cv_have_stdint_h,;t t +s,@ac_cv_have_stddef_h@,$ac_cv_have_stddef_h,;t t +s,@SNAPPY_MAJOR@,$SNAPPY_MAJOR,;t t +s,@SNAPPY_MINOR@,$SNAPPY_MINOR,;t t +s,@SNAPPY_PATCHLEVEL@,$SNAPPY_PATCHLEVEL,;t t +s,@SNAPPY_LTVERSION@,$SNAPPY_LTVERSION,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_HEADER section. +# + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' +ac_dC=' ' +ac_dD=',;t' +# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='$,\1#\2define\3' +ac_uC=' ' +ac_uD=',;t' + +for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + # Do quote $f, to prevent DOS paths from being IFS'd. + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + # Remove the trailing spaces. + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + +_ACEOF + +# Transform confdefs.h into two sed scripts, `conftest.defines' and +# `conftest.undefs', that substitutes the proper values into +# config.h.in to produce config.h. The first handles `#define' +# templates, and the second `#undef' templates. +# And first: Protect against being on the right side of a sed subst in +# config.status. Protect against being in an unquoted here document +# in config.status. +rm -f conftest.defines conftest.undefs +# Using a here document instead of a string reduces the quoting nightmare. +# Putting comments in sed scripts is not portable. +# +# `end' is used to avoid that the second main sed command (meant for +# 0-ary CPP macros) applies to n-ary macro definitions. +# See the Autoconf documentation for `clear'. +cat >confdef2sed.sed <<\_ACEOF +s/[\\&,]/\\&/g +s,[\\$`],\\&,g +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp +t end +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +: end +_ACEOF +# If some macros were called several times there might be several times +# the same #defines, which is useless. Nevertheless, we may not want to +# sort them, since we want the *last* AC-DEFINE to be honored. +uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines +sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs +rm -f confdef2sed.sed + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >>conftest.undefs <<\_ACEOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +_ACEOF + +# Break up conftest.defines because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS +echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS +echo ' :' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.defines >/dev/null +do + # Write a limited-size here document to $tmp/defines.sed. + echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#define' lines. + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/defines.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines +echo ' fi # grep' >>$CONFIG_STATUS +echo >>$CONFIG_STATUS + +# Break up conftest.undefs because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #undef templates' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.undefs >/dev/null +do + # Write a limited-size here document to $tmp/undefs.sed. + echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#undef' + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/undefs.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail + rm -f conftest.undefs + mv conftest.tail conftest.undefs +done +rm -f conftest.undefs + +cat >>$CONFIG_STATUS <<\_ACEOF + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + echo "/* Generated by configure. */" >$tmp/config.h + else + echo "/* $ac_file. Generated by configure. */" >$tmp/config.h + fi + cat $tmp/in >>$tmp/config.h + rm -f $tmp/in + if test x"$ac_file" != x-; then + if diff $ac_file $tmp/config.h >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + rm -f $ac_file + mv $tmp/config.h $ac_file + fi + else + cat $tmp/config.h + rm -f $tmp/config.h + fi +# Compute $ac_file's index in $config_headers. +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $ac_file | $ac_file:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $ac_file" >`(dirname $ac_file) 2>/dev/null || +$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X$ac_file : 'X\(//\)[^/]' \| \ + X$ac_file : 'X\(//\)$' \| \ + X$ac_file : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X$ac_file | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'`/stamp-h$_am_stamp_count +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_COMMANDS section. +# +for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue + ac_dest=`echo "$ac_file" | sed 's,:.*,,'` + ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_dir=`(dirname "$ac_dest") 2>/dev/null || +$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_dest" : 'X\(//\)[^/]' \| \ + X"$ac_dest" : 'X\(//\)$' \| \ + X"$ac_dest" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_dest" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 +echo "$as_me: executing $ac_dest commands" >&6;} + case $ac_dest in + depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + dirpart=`(dirname "$mf") 2>/dev/null || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`(dirname "$file") 2>/dev/null || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p $dirpart/$fdir + else + as_dir=$dirpart/$fdir + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5 +echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;} + { (exit 1); exit 1; }; }; } + + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done + ;; + esac +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + diff --git a/snappy/snappy-1.0.5/configure.ac b/snappy/snappy-1.0.5/configure.ac new file mode 100644 index 00000000..d193b0be --- /dev/null +++ b/snappy/snappy-1.0.5/configure.ac @@ -0,0 +1,126 @@ +m4_define([snappy_major], [1]) +m4_define([snappy_minor], [0]) +m4_define([snappy_patchlevel], [5]) + +# Libtool shared library interface versions (current:revision:age) +# Update this value for every release! (A:B:C will map to foo.so.(A-C).C.B) +# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html +m4_define([snappy_ltversion], [2:3:1]) + +AC_INIT([snappy], [snappy_major.snappy_minor.snappy_patchlevel]) +AC_CONFIG_MACRO_DIR([m4]) + +# These are flags passed to automake (though they look like gcc flags!) +AM_INIT_AUTOMAKE([-Wall -Werror]) + +LT_INIT +AC_SUBST([LIBTOOL_DEPS]) +AC_PROG_CXX +AC_LANG([C++]) +AC_C_BIGENDIAN +AC_CHECK_HEADERS([stdint.h stddef.h sys/mman.h sys/resource.h windows.h byteswap.h sys/byteswap.h sys/endian.h]) + +# Don't use AC_FUNC_MMAP, as it checks for mappings of already-mapped memory, +# which we don't need (and does not exist on Windows). +AC_CHECK_FUNC([mmap]) + +GTEST_LIB_CHECK([], [true], [true # Ignore; we can live without it.]) + +AC_ARG_WITH([gflags], + [AS_HELP_STRING( + [--with-gflags], + [use Google Flags package to enhance the unit test @<:@default=check@:>@])], + [], + [with_gflags=check]) + +if test "x$with_gflags" != "xno"; then + PKG_CHECK_MODULES( + [gflags], + [libgflags], + [AC_DEFINE([HAVE_GFLAGS], [1], [Use the gflags package for command-line parsing.])], + [if test "x$with_gflags" != "xcheck"; then + AC_MSG_FAILURE([--with-gflags was given, but test for gflags failed]) + fi]) +fi + +# See if we have __builtin_expect. +# TODO: Use AC_CACHE. +AC_MSG_CHECKING([if the compiler supports __builtin_expect]) + +AC_TRY_COMPILE(, [ + return __builtin_expect(1, 1) ? 1 : 0 +], [ + snappy_have_builtin_expect=yes + AC_MSG_RESULT([yes]) +], [ + snappy_have_builtin_expect=no + AC_MSG_RESULT([no]) +]) +if test x$snappy_have_builtin_expect = xyes ; then + AC_DEFINE([HAVE_BUILTIN_EXPECT], [1], [Define to 1 if the compiler supports __builtin_expect.]) +fi + +# See if we have working count-trailing-zeros intrinsics. +# TODO: Use AC_CACHE. +AC_MSG_CHECKING([if the compiler supports __builtin_ctzll]) + +AC_TRY_COMPILE(, [ + return (__builtin_ctzll(0x100000000LL) == 32) ? 1 : 0 +], [ + snappy_have_builtin_ctz=yes + AC_MSG_RESULT([yes]) +], [ + snappy_have_builtin_ctz=no + AC_MSG_RESULT([no]) +]) +if test x$snappy_have_builtin_ctz = xyes ; then + AC_DEFINE([HAVE_BUILTIN_CTZ], [1], [Define to 1 if the compiler supports __builtin_ctz and friends.]) +fi + +# Other compression libraries; the unit test can use these for comparison +# if they are available. If they are not found, just ignore. +UNITTEST_LIBS="" +AC_DEFUN([CHECK_EXT_COMPRESSION_LIB], [ + AH_CHECK_LIB([$1]) + AC_CHECK_LIB( + [$1], + [$2], + [ + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIB$1)) + UNITTEST_LIBS="-l$1 $UNITTEST_LIBS" + ], + [true] + ) +]) +CHECK_EXT_COMPRESSION_LIB([z], [zlibVersion]) +CHECK_EXT_COMPRESSION_LIB([lzo2], [lzo1x_1_15_compress]) +CHECK_EXT_COMPRESSION_LIB([lzf], [lzf_compress]) +CHECK_EXT_COMPRESSION_LIB([fastlz], [fastlz_compress]) +CHECK_EXT_COMPRESSION_LIB([quicklz], [qlz_compress]) +AC_SUBST([UNITTEST_LIBS]) + +# These are used by snappy-stubs-public.h.in. +if test "$ac_cv_header_stdint_h" = "yes"; then + AC_SUBST([ac_cv_have_stdint_h], [1]) +else + AC_SUBST([ac_cv_have_stdint_h], [0]) +fi +if test "$ac_cv_header_stddef_h" = "yes"; then + AC_SUBST([ac_cv_have_stddef_h], [1]) +else + AC_SUBST([ac_cv_have_stddef_h], [0]) +fi + +# Export the version to snappy-stubs-public.h. +SNAPPY_MAJOR="snappy_major" +SNAPPY_MINOR="snappy_minor" +SNAPPY_PATCHLEVEL="snappy_patchlevel" + +AC_SUBST([SNAPPY_MAJOR]) +AC_SUBST([SNAPPY_MINOR]) +AC_SUBST([SNAPPY_PATCHLEVEL]) +AC_SUBST([SNAPPY_LTVERSION], snappy_ltversion) + +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_FILES([Makefile snappy-stubs-public.h]) +AC_OUTPUT diff --git a/snappy/snappy-1.0.5/depcomp b/snappy/snappy-1.0.5/depcomp new file mode 100755 index 00000000..df8eea7e --- /dev/null +++ b/snappy/snappy-1.0.5/depcomp @@ -0,0 +1,630 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2009-04-28.21; # UTC + +# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free +# Software Foundation, Inc. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u="sed s,\\\\\\\\,/,g" + depmode=msvisualcpp +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> "$depfile" + echo >> "$depfile" + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" + # Add `dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mechanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/snappy/snappy-1.0.5/dhruba.txt b/snappy/snappy-1.0.5/dhruba.txt new file mode 100644 index 00000000..183b6388 --- /dev/null +++ b/snappy/snappy-1.0.5/dhruba.txt @@ -0,0 +1,12 @@ +# for fbcode compile, run leveldb/fbcode.sh + +autoconf +./configure + +# for running fbcode, edit config.h and comment out the followng two lines: +// #define HAVE_LIBLZO2 1 +// #define HAVE_LIBZ 1 +edit Makefile and change "UNITTEST_LIBS = -llzo2 -lz" to "UNITTEST_LIBS = -lz" + +make top_builddir="." LIBTOOL=libtool -e "CPPFLAGS=-DNDEBUG" clean all + diff --git a/snappy/snappy-1.0.5/format_description.txt b/snappy/snappy-1.0.5/format_description.txt new file mode 100644 index 00000000..20db66c1 --- /dev/null +++ b/snappy/snappy-1.0.5/format_description.txt @@ -0,0 +1,110 @@ +Snappy compressed format description +Last revised: 2011-10-05 + + +This is not a formal specification, but should suffice to explain most +relevant parts of how the Snappy format works. It is originally based on +text by Zeev Tarantov. + +Snappy is a LZ77-type compressor with a fixed, byte-oriented encoding. +There is no entropy encoder backend nor framing layer -- the latter is +assumed to be handled by other parts of the system. + +This document only describes the format, not how the Snappy compressor nor +decompressor actually works. The correctness of the decompressor should not +depend on implementation details of the compressor, and vice versa. + + +1. Preamble + +The stream starts with the uncompressed length (up to a maximum of 2^32 - 1), +stored as a little-endian varint. Varints consist of a series of bytes, +where the lower 7 bits are data and the upper bit is set iff there are +more bytes to be read. In other words, an uncompressed length of 64 would +be stored as 0x40, and an uncompressed length of 2097150 (0x1FFFFE) +would be stored as 0xFE 0xFF 0x7F. + + +2. The compressed stream itself + +There are two types of elements in a Snappy stream: Literals and +copies (backreferences). There is no restriction on the order of elements, +except that the stream naturally cannot start with a copy. (Having +two literals in a row is never optimal from a compression point of +view, but nevertheless fully permitted.) Each element starts with a tag byte, +and the lower two bits of this tag byte signal what type of element will +follow: + + 00: Literal + 01: Copy with 1-byte offset + 10: Copy with 2-byte offset + 11: Copy with 4-byte offset + +The interpretation of the upper six bits are element-dependent. + + +2.1. Literals (00) + +Literals are uncompressed data stored directly in the byte stream. +The literal length is stored differently depending on the length +of the literal: + + - For literals up to and including 60 bytes in length, the upper + six bits of the tag byte contain (len-1). The literal follows + immediately thereafter in the bytestream. + - For longer literals, the (len-1) value is stored after the tag byte, + little-endian. The upper six bits of the tag byte describe how + many bytes are used for the length; 60, 61, 62 or 63 for + 1-4 bytes, respectively. The literal itself follows after the + length. + + +2.2. Copies + +Copies are references back into previous decompressed data, telling +the decompressor to reuse data it has previously decoded. +They encode two values: The _offset_, saying how many bytes back +from the current position to read, and the _length_, how many bytes +to copy. Offsets of zero can be encoded, but are not legal; +similarly, it is possible to encode backreferences that would +go past the end of the block (offset > current decompressed position), +which is also nonsensical and thus not allowed. + +As in most LZ77-based compressors, the length can be larger than the offset, +yielding a form of run-length encoding (RLE). For instance, +"xababab" could be encoded as + + + +Note that since the current Snappy compressor works in 32 kB +blocks and does not do matching across blocks, it will never produce +a bitstream with offsets larger than about 32768. However, the +decompressor should not rely on this, as it may change in the future. + +There are several different kinds of copy elements, depending on +the amount of bytes to be copied (length), and how far back the +data to be copied is (offset). + + +2.2.1. Copy with 1-byte offset (01) + +These elements can encode lengths between [4..11] bytes and offsets +between [0..2047] bytes. (len-4) occupies three bits and is stored +in bits [2..4] of the tag byte. The offset occupies 11 bits, of which the +upper three are stored in the upper three bits ([5..7]) of the tag byte, +and the lower eight are stored in a byte following the tag byte. + + +2.2.2. Copy with 2-byte offset (10) + +These elements can encode lengths between [1..64] and offsets from +[0..65535]. (len-1) occupies six bits and is stored in the upper +six bits ([2..7]) of the tag byte. The offset is stored as a +little-endian 16-bit integer in the two bytes following the tag byte. + + +2.2.3. Copy with 4-byte offset (11) + +These are like the copies with 2-byte offsets (see previous subsection), +except that the offset is stored as a 32-bit integer instead of a +16-bit integer (and thus will occupy four bytes). diff --git a/snappy/snappy-1.0.5/framing_format.txt b/snappy/snappy-1.0.5/framing_format.txt new file mode 100644 index 00000000..08fda03f --- /dev/null +++ b/snappy/snappy-1.0.5/framing_format.txt @@ -0,0 +1,124 @@ +Snappy framing format description +Last revised: 2011-12-15 + +This format decribes a framing format for Snappy, allowing compressing to +files or streams that can then more easily be decompressed without having +to hold the entire stream in memory. It also provides data checksums to +help verify integrity. It does not provide metadata checksums, so it does +not protect against e.g. all forms of truncations. + +Implementation of the framing format is optional for Snappy compressors and +decompressor; it is not part of the Snappy core specification. + + +1. General structure + +The file consists solely of chunks, lying back-to-back with no padding +in between. Each chunk consists first a single byte of chunk identifier, +then a two-byte little-endian length of the chunk in bytes (from 0 to 65535, +inclusive), and then the data if any. The three bytes of chunk header is not +counted in the data length. + +The different chunk types are listed below. The first chunk must always +be the stream identifier chunk (see section 4.1, below). The stream +ends when the file ends -- there is no explicit end-of-file marker. + + +2. File type identification + +The following identifiers for this format are recommended where appropriate. +However, note that none have been registered officially, so this is only to +be taken as a guideline. We use "Snappy framed" to distinguish between this +format and raw Snappy data. + + File extension: .sz + MIME type: application/x-snappy-framed + HTTP Content-Encoding: x-snappy-framed + + +3. Checksum format + +Some chunks have data protected by a checksum (the ones that do will say so +explicitly). The checksums are always masked CRC-32Cs. + +A description of CRC-32C can be found in RFC 3720, section 12.1, with +examples in section B.4. + +Checksums are not stored directly, but masked, as checksumming data and +then its own checksum can be problematic. The masking is the same as used +in Apache Hadoop: Rotate the checksum by 15 bits, then add the constant +0xa282ead8 (using wraparound as normal for unsigned integers). This is +equivalent to the following C code: + + uint32_t mask_checksum(uint32_t x) { + return ((x >> 15) | (x << 17)) + 0xa282ead8; + } + +Note that the masking is reversible. + +The checksum is always stored as a four bytes long integer, in little-endian. + + +4. Chunk types + +The currently supported chunk types are described below. The list may +be extended in the future. + + +4.1. Stream identifier (chunk type 0xff) + +The stream identifier is always the first element in the stream. +It is exactly six bytes long and contains "sNaPpY" in ASCII. This means that +a valid Snappy framed stream always starts with the bytes + + 0xff 0x06 0x00 0x73 0x4e 0x61 0x50 0x70 0x59 + +The stream identifier chunk can come multiple times in the stream besides +the first; if such a chunk shows up, it should simply be ignored, assuming +it has the right length and contents. This allows for easy concatenation of +compressed files without the need for re-framing. + + +4.2. Compressed data (chunk type 0x00) + +Compressed data chunks contain a normal Snappy compressed bitstream; +see the compressed format specification. The compressed data is preceded by +the CRC-32C (see section 3) of the _uncompressed_ data. + +Note that the data portion of the chunk, i.e., the compressed contents, +can be at most 65531 bytes (2^16 - 1, minus the checksum). +However, we place an additional restriction that the uncompressed data +in a chunk must be no longer than 32768 bytes. This allows consumers to +easily use small fixed-size buffers. + + +4.3. Uncompressed data (chunk type 0x01) + +Uncompressed data chunks allow a compressor to send uncompressed, +raw data; this is useful if, for instance, uncompressible or +near-incompressible data is detected, and faster decompression is desired. + +As in the compressed chunks, the data is preceded by its own masked +CRC-32C (see section 3). + +An uncompressed data chunk, like compressed data chunks, should contain +no more than 32768 data bytes, so the maximum legal chunk length with the +checksum is 32772. + + +4.4. Reserved unskippable chunks (chunk types 0x02-0x7f) + +These are reserved for future expansion. A decoder that sees such a chunk +should immediately return an error, as it must assume it cannot decode the +stream correctly. + +Future versions of this specification may define meanings for these chunks. + + +4.5. Reserved skippable chunks (chunk types 0x80-0xfe) + +These are also reserved for future expansion, but unlike the chunks +described in 4.4, a decoder seeing these must skip them and continue +decoding. + +Future versions of this specification may define meanings for these chunks. diff --git a/snappy/snappy-1.0.5/install-sh b/snappy/snappy-1.0.5/install-sh new file mode 100755 index 00000000..6781b987 --- /dev/null +++ b/snappy/snappy-1.0.5/install-sh @@ -0,0 +1,520 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2009-04-28.21; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + trap '(exit $?); exit' 1 2 13 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/snappy/snappy-1.0.5/libsnappy.la b/snappy/snappy-1.0.5/libsnappy.la new file mode 100644 index 00000000..01e3cd05 --- /dev/null +++ b/snappy/snappy-1.0.5/libsnappy.la @@ -0,0 +1,41 @@ +# libsnappy.la - a libtool library file +# Generated by ltmain.sh (GNU libtool) 2.2.6b Debian-2.2.6b-2ubuntu1 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='libsnappy.so.1' + +# Names of this library. +library_names='libsnappy.so.1.0.5 libsnappy.so.1 libsnappy.so' + +# The name of the static archive. +old_library='libsnappy.a' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='' + +# Libraries that this one depends upon. +dependency_libs='' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for libsnappy. +current=1 +age=0 +revision=5 + +# Is this an already installed library? +installed=no + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/usr/local/lib' diff --git a/snappy/snappy-1.0.5/libtool b/snappy/snappy-1.0.5/libtool new file mode 100755 index 00000000..33bd9de0 --- /dev/null +++ b/snappy/snappy-1.0.5/libtool @@ -0,0 +1,9063 @@ +#! /bin/sh + +# libtool - Provide generalized library-building support services. +# Generated automatically by config.status (snappy) 1.0.5 +# Libtool was configured on host devrs306.snc6.facebook.com: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool 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. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +# The names of the tagged configurations supported by this script. +available_tags="CXX " + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=2.2.6b +macro_revision=1.3017 + +# Whether or not to build shared libraries. +build_libtool_libs=yes + +# Whether or not to build static libraries. +build_old_libs=yes + +# What type of objects to build. +pic_mode=default + +# Whether or not to optimize for fast installation. +fast_install=yes + +# The host system. +host_alias= +host=x86_64-unknown-linux-gnu +host_os=linux-gnu + +# The build system. +build_alias= +build=x86_64-unknown-linux-gnu +build_os=linux-gnu + +# A sed program that does not truncate output. +SED="/bin/sed" + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP="/bin/grep" + +# An ERE matcher. +EGREP="/bin/grep -E" + +# A literal string matcher. +FGREP="/bin/grep -F" + +# A BSD- or MS-compatible name lister. +NM="/usr/bin/nm -B" + +# Whether we need soft or hard links. +LN_S="ln -s" + +# What is the maximum length of a command? +max_cmd_len=98304 + +# Object file suffix (normally "o"). +objext=o + +# Executable file suffix (normally ""). +exeext= + +# whether the shell understands "unset". +lt_unset=unset + +# turn spaces into newlines. +SP2NL="tr \\040 \\012" + +# turn newlines into spaces. +NL2SP="tr \\015\\012 \\040\\040" + +# How to create reloadable object files. +reload_flag=" -r" +reload_cmds="\$LD\$reload_flag -o \$output\$reload_objs" + +# An object symbol dumper. +OBJDUMP="objdump" + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method="pass_all" + +# Command to use when deplibs_check_method == "file_magic". +file_magic_cmd="\$MAGIC_CMD" + +# The archiver. +AR="ar" +AR_FLAGS="cru" + +# A symbol stripping program. +STRIP="strip" + +# Commands used to install an old-style archive. +RANLIB="ranlib" +old_postinstall_cmds="chmod 644 \$oldlib~\$RANLIB \$oldlib" +old_postuninstall_cmds="" + +# A C compiler. +LTCC="gcc" + +# LTCC compiler flags. +LTCFLAGS="-g -O2" + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe="sed -n -e 's/^.*[ ]\\([ABCDGIRSTW][ABCDGIRSTW]*\\)[ ][ ]*\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 \\2 \\2/p'" + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl="sed -n -e 's/^T .* \\(.*\\)\$/extern int \\1();/p' -e 's/^[ABCDGIRSTW]* .* \\(.*\\)\$/extern char \\1;/p'" + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address="sed -n -e 's/^: \\([^ ]*\\) \$/ {\\\"\\1\\\", (void *) 0},/p' -e 's/^[ABCDGIRSTW]* \\([^ ]*\\) \\([^ ]*\\)\$/ {\"\\2\", (void *) \\&\\2},/p'" + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \\([^ ]*\\) \$/ {\\\"\\1\\\", (void *) 0},/p' -e 's/^[ABCDGIRSTW]* \\([^ ]*\\) \\(lib[^ ]*\\)\$/ {\"\\2\", (void *) \\&\\2},/p' -e 's/^[ABCDGIRSTW]* \\([^ ]*\\) \\([^ ]*\\)\$/ {\"lib\\2\", (void *) \\&\\2},/p'" + +# The name of the directory that contains temporary libtool files. +objdir=.libs + +# Shell to use when invoking shell scripts. +SHELL="/bin/sh" + +# An echo program that does not interpret backslashes. +ECHO="echo" + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=file + +# Must we lock files when doing compilation? +need_locks="no" + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL="" + +# Tool to change global to local symbols on Mac OS X. +NMEDIT="" + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO="" + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL="" + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64="" + +# Old archive suffix (normally "a"). +libext=a + +# Shared library suffix (normally ".so"). +shrext_cmds=".so" + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds="" + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink="PATH LD_LIBRARY_PATH LD_RUN_PATH GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" + +# Do we need the "lib" prefix for modules? +need_lib_prefix=no + +# Do we need a version for libraries? +need_version=no + +# Library versioning type. +version_type=linux + +# Shared library runtime path variable. +runpath_var=LD_RUN_PATH + +# Shared library path variable. +shlibpath_var=LD_LIBRARY_PATH + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=no + +# Format of library name prefix. +libname_spec="lib\$name" + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec="\${libname}\${release}\${shared_ext}\$versuffix \${libname}\${release}\${shared_ext}\$major \$libname\${shared_ext}" + +# The coded name of the library, if different from the real name. +soname_spec="\${libname}\${release}\${shared_ext}\$major" + +# Command to use after installation of a shared archive. +postinstall_cmds="" + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds="" + +# Commands used to finish a libtool library installation in a directory. +finish_cmds="PATH=\\\"\\\$PATH:/sbin\\\" ldconfig -n \$libdir" + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval="" + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=yes + +# Compile-time system search path for libraries. +sys_lib_search_path_spec="/usr/lib/gcc/x86_64-redhat-linux/4.1.2 /usr/lib64 /lib64" + +# Run-time system search path for libraries. +sys_lib_dlsearch_path_spec="/lib /usr/lib /usr/lib64/R/lib /usr/local/lib64 /usr/lib64/mysql /usr/lib/oracle/11.1/client64/lib/ /usr/local/lib /usr/lib/qt-3.3/lib /usr/lib64/qt-3.3/lib /usr/local/lib " + +# Whether dlopen is supported. +dlopen_support=unknown + +# Whether dlopen of programs is supported. +dlopen_self=unknown + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=unknown + +# Commands to strip libraries. +old_striplib="strip --strip-debug" +striplib="strip --strip-unneeded" + + +# The linker used to build libraries. +LD="/usr/bin/ld -m elf_x86_64" + +# Commands used to build an old-style archive. +old_archive_cmds="\$AR \$AR_FLAGS \$oldlib\$oldobjs~\$RANLIB \$oldlib" + +# A language specific compiler. +CC="gcc" + +# Is the compiler the GNU compiler? +with_gcc=yes + +# Compiler flag to turn off builtin functions. +no_builtin_flag=" -fno-builtin" + +# How to pass a linker flag through the compiler. +wl="-Wl," + +# Additional compiler flags for building library objects. +pic_flag=" -fPIC -DPIC" + +# Compiler flag to prevent dynamic linking. +link_static_flag="-static" + +# Does compiler simultaneously support -c and -o options? +compiler_c_o="yes" + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=no + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=no + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec="\${wl}--export-dynamic" + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec="\${wl}--whole-archive\$convenience \${wl}--no-whole-archive" + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object="no" + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds="" + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds="" + +# Commands used to build a shared archive. +archive_cmds="\$CC -shared \$libobjs \$deplibs \$compiler_flags \${wl}-soname \$wl\$soname -o \$lib" +archive_expsym_cmds="echo \\\"{ global:\\\" > \$output_objdir/\$libname.ver~ + cat \$export_symbols | sed -e \\\"s/\\\\(.*\\\\)/\\\\1;/\\\" >> \$output_objdir/\$libname.ver~ + echo \\\"local: *; };\\\" >> \$output_objdir/\$libname.ver~ + \$CC -shared \$libobjs \$deplibs \$compiler_flags \${wl}-soname \$wl\$soname \${wl}-version-script \${wl}\$output_objdir/\$libname.ver -o \$lib" + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds="" +module_expsym_cmds="" + +# Whether we are building with GNU ld or not. +with_gnu_ld="yes" + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag="" + +# Flag that enforces no undefined symbols. +no_undefined_flag="" + +# Flag to hardcode $libdir into a binary during linking. +# This must work even if $libdir does not exist +hardcode_libdir_flag_spec="\${wl}-rpath \${wl}\$libdir" + +# If ld is used when linking, flag to hardcode $libdir into a binary +# during linking. This must work even if $libdir does not exist. +hardcode_libdir_flag_spec_ld="" + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator="" + +# Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=no + +# Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting ${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=no + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=no + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=unsupported + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=no + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=no + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=no + +# Fix the shell variable $srcfile for the compiler. +fix_srcfile_path="" + +# Set to "yes" if exported symbols are required. +always_export_symbols=no + +# The commands to list exported symbols. +export_symbols_cmds="\$NM \$libobjs \$convenience | \$global_symbol_pipe | \$SED 's/.* //' | sort | uniq > \$export_symbols" + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms="_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*" + +# Symbols that must always be exported. +include_expsyms="" + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds="" + +# Specify filename containing input files. +file_list_spec="" + +# How to hardcode a shared library path into an executable. +hardcode_action=immediate + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs="" + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects="" +postdep_objects="" +predeps="" +postdeps="" + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path="" + +# ### END LIBTOOL CONFIG + +# Generated from ltmain.m4sh. + +# ltmain.sh (GNU libtool) 2.2.6b +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool 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. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, +# or obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Usage: $progname [OPTION]... [MODE-ARG]... +# +# Provide generalized library-building support services. +# +# --config show all configuration variables +# --debug enable verbose shell tracing +# -n, --dry-run display commands without modifying any files +# --features display basic configuration information and exit +# --mode=MODE use operation mode MODE +# --preserve-dup-deps don't remove duplicate dependency libraries +# --quiet, --silent don't print informational messages +# --tag=TAG use configuration variables from tag TAG +# -v, --verbose print informational messages (default) +# --version print version information +# -h, --help print short or long help message +# +# MODE must be one of the following: +# +# clean remove files from the build directory +# compile compile a source file into a libtool object +# execute automatically set library path, then run a program +# finish complete the installation of libtool libraries +# install install libraries or executables +# link create a library or an executable +# uninstall remove libraries from an installed directory +# +# MODE-ARGS vary depending on the MODE. +# Try `$progname --help --mode=MODE' for a more detailed description of MODE. +# +# When reporting a bug, please describe a test case to reproduce it and +# include the following information: +# +# host-triplet: $host +# shell: $SHELL +# compiler: $LTCC +# compiler flags: $LTCFLAGS +# linker: $LD (gnu? $with_gnu_ld) +# $progname: (GNU libtool) 2.2.6b Debian-2.2.6b-2ubuntu1 +# automake: $automake_version +# autoconf: $autoconf_version +# +# Report bugs to . + +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION="2.2.6b Debian-2.2.6b-2ubuntu1" +TIMESTAMP="" +package_revision=1.3017 + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + 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 + +# NLS nuisances: We save the old values to restore during execute mode. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +lt_user_locale= +lt_safe_locale= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test \"\${$lt_var+set}\" = set; then + save_$lt_var=\$$lt_var + $lt_var=C + export $lt_var + lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" + lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + fi" +done + +$lt_unset CDPATH + + + + + +: ${CP="cp -f"} +: ${ECHO="echo"} +: ${EGREP="/bin/grep -E"} +: ${FGREP="/bin/grep -F"} +: ${GREP="/bin/grep"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SED="/bin/sed"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} +: ${Xsed="$SED -e 1s/^X//"} + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +exit_status=$EXIT_SUCCESS + +# Make sure IFS has a sensible default +lt_nl=' +' +IFS=" $lt_nl" + +dirname="s,/[^/]*$,," +basename="s,^.*/,," + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi + func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` +} + +# Generated shell functions inserted here. + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac +} + +# func_basename file +func_basename () +{ + func_basename_result="${1##*/}" +} + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}" +} + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +func_stripname () +{ + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"} +} + +# func_opt_split +func_opt_split () +{ + func_opt_split_opt=${1%%=*} + func_opt_split_arg=${1#*=} +} + +# func_lo2o object +func_lo2o () +{ + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac +} + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=${1%.*}.lo +} + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=$(( $* )) +} + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=${#1} +} + + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "$1+=\$2" +} +# Generated shell functions inserted here. + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + +# The name of this program: +# In the unlikely event $progname began with a '-', it would play havoc with +# func_echo (imagine progname=-n), so we prepend ./ in that case: +func_dirname_and_basename "$progpath" +progname=$func_basename_result +case $progname in + -*) progname=./$progname ;; +esac + +# Make sure we have an absolute path for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=$func_dirname_result + progdir=`cd "$progdir" && pwd` + progpath="$progdir/$progname" + ;; + *) + save_IFS="$IFS" + IFS=: + for progdir in $PATH; do + IFS="$save_IFS" + test -x "$progdir/$progname" && break + done + IFS="$save_IFS" + test -n "$progdir" || progdir=`pwd` + progpath="$progdir/$progname" + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed="${SED}"' -e 1s/^X//' +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Re-`\' parameter expansions in output of double_quote_subst that were +# `\'-ed in input to the same. If an odd number of `\' preceded a '$' +# in input to double_quote_subst, that '$' was protected from expansion. +# Since each input `\' is now two `\'s, look for any number of runs of +# four `\'s followed by two `\'s and then a '$'. `\' that '$'. +bs='\\' +bs2='\\\\' +bs4='\\\\\\\\' +dollar='\$' +sed_double_backslash="\ + s/$bs4/&\\ +/g + s/^$bs2$dollar/$bs&/ + s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g + s/\n//g" + +# Standard options: +opt_dry_run=false +opt_help=false +opt_quiet=false +opt_verbose=false +opt_warning=: + +# func_echo arg... +# Echo program name prefixed message, along with the current mode +# name if it has been set yet. +func_echo () +{ + $ECHO "$progname${mode+: }$mode: $*" +} + +# func_verbose arg... +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $opt_verbose && func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + +# func_error arg... +# Echo program name prefixed message to standard error. +func_error () +{ + $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2 +} + +# func_warning arg... +# Echo program name prefixed warning message to standard error. +func_warning () +{ + $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2 + + # bash bug again: + : +} + +# func_fatal_error arg... +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + +# func_fatal_help arg... +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + func_error ${1+"$@"} + func_fatal_error "$help" +} +help="Try \`$progname --help' for more information." ## default + + +# func_grep expression filename +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_mkdir_p directory-path +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + my_directory_path="$1" + my_dir_list= + + if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then + + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$my_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + my_dir_list="$my_directory_path:$my_dir_list" + + # If the last portion added has no slash in it, the list is done + case $my_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"` + done + my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'` + + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$my_dir" 2>/dev/null || : + done + IFS="$save_mkdir_p_IFS" + + # Bail out if we (or some other process) failed to create a directory. + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" + fi +} + + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$opt_dry_run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || \ + func_fatal_error "cannot create temporary directory \`$my_tmpdir'" + fi + + $ECHO "X$my_tmpdir" | $Xsed +} + + +# func_quote_for_eval arg +# Aesthetically quote ARG to be evaled later. +# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT +# is double-quoted, suitable for a subsequent eval, whereas +# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters +# which are still active within double quotes backslashified. +func_quote_for_eval () +{ + case $1 in + *[\\\`\"\$]*) + func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;; + *) + func_quote_for_eval_unquoted_result="$1" ;; + esac + + case $func_quote_for_eval_unquoted_result in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and and variable + # expansion for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" + ;; + *) + func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" + esac +} + + +# func_quote_for_expand arg +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + case $1 in + *[\\\`\"]*) + my_arg=`$ECHO "X$1" | $Xsed \ + -e "$double_quote_subst" -e "$sed_double_backslash"` ;; + *) + my_arg="$1" ;; + esac + + case $my_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + my_arg="\"$my_arg\"" + ;; + esac + + func_quote_for_expand_result="$my_arg" +} + + +# func_show_eval cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$my_cmd" + my_status=$? + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + +# func_show_eval_locale cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$lt_user_locale + $my_cmd" + my_status=$? + eval "$lt_safe_locale" + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + + + + +# func_version +# Echo version message to standard output and exit. +func_version () +{ + $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / { + s/^# // + s/^# *$// + s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ + p + }' < "$progpath" + exit $? +} + +# func_usage +# Echo short help message to standard output and exit. +func_usage () +{ + $SED -n '/^# Usage:/,/# -h/ { + s/^# // + s/^# *$// + s/\$progname/'$progname'/ + p + }' < "$progpath" + $ECHO + $ECHO "run \`$progname --help | more' for full usage" + exit $? +} + +# func_help +# Echo long help message to standard output and exit. +func_help () +{ + $SED -n '/^# Usage:/,/# Report bugs to/ { + s/^# // + s/^# *$// + s*\$progname*'$progname'* + s*\$host*'"$host"'* + s*\$SHELL*'"$SHELL"'* + s*\$LTCC*'"$LTCC"'* + s*\$LTCFLAGS*'"$LTCFLAGS"'* + s*\$LD*'"$LD"'* + s/\$with_gnu_ld/'"$with_gnu_ld"'/ + s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ + s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ + p + }' < "$progpath" + exit $? +} + +# func_missing_arg argname +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + func_error "missing argument for $1" + exit_cmd=exit +} + +exit_cmd=: + + + + + +# Check that we have a working $ECHO. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then + # Yippee, $ECHO works! + : +else + # Restart under the correct shell, and then maybe $ECHO will work. + exec $SHELL "$progpath" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + +# Parse options once, thoroughly. This comes as soon as possible in +# the script to make things like `libtool --version' happen quickly. +{ + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + esac + + # Parse non-mode specific arguments: + while test "$#" -gt 0; do + opt="$1" + shift + + case $opt in + --config) func_config ;; + + --debug) preserve_args="$preserve_args $opt" + func_echo "enabling shell trace mode" + opt_debug='set -x' + $opt_debug + ;; + + -dlopen) test "$#" -eq 0 && func_missing_arg "$opt" && break + execute_dlfiles="$execute_dlfiles $1" + shift + ;; + + --dry-run | -n) opt_dry_run=: ;; + --features) func_features ;; + --finish) mode="finish" ;; + + --mode) test "$#" -eq 0 && func_missing_arg "$opt" && break + case $1 in + # Valid mode arguments: + clean) ;; + compile) ;; + execute) ;; + finish) ;; + install) ;; + link) ;; + relink) ;; + uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $opt" + exit_cmd=exit + break + ;; + esac + + mode="$1" + shift + ;; + + --preserve-dup-deps) + opt_duplicate_deps=: ;; + + --quiet|--silent) preserve_args="$preserve_args $opt" + opt_silent=: + ;; + + --verbose| -v) preserve_args="$preserve_args $opt" + opt_silent=false + ;; + + --tag) test "$#" -eq 0 && func_missing_arg "$opt" && break + preserve_args="$preserve_args $opt $1" + func_enable_tag "$1" # tagname is set here + shift + ;; + + # Separate optargs to long options: + -dlopen=*|--mode=*|--tag=*) + func_opt_split "$opt" + set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"} + shift + ;; + + -\?|-h) func_usage ;; + --help) opt_help=: ;; + --version) func_version ;; + + -*) func_fatal_help "unrecognized option \`$opt'" ;; + + *) nonopt="$opt" + break + ;; + esac + done + + + case $host in + *cygwin* | *mingw* | *pw32* | *cegcc*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_duplicate_deps + ;; + esac + + # Having warned about all mis-specified options, bail out if + # anything was wrong. + $exit_cmd $EXIT_FAILURE +} + +# func_check_version_match +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +## ----------- ## +## Main. ## +## ----------- ## + +$opt_help || { + # Sanity checks first: + func_check_version_match + + if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + func_fatal_configuration "not configured to build any kind of library" + fi + + test -z "$mode" && func_fatal_error "error: you must specify a MODE." + + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + func_error "unrecognized option \`-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$progname --help --mode=$mode' for more information." +} + + +# func_lalib_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null \ + | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if `file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case "$lalib_p_line" in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test "$lalib_p" = yes +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + func_lalib_p "$1" +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_ltwrapper_scriptname_result="" + if func_ltwrapper_executable_p "$1"; then + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" + fi +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $opt_debug + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$save_ifs + eval cmd=\"$cmd\" + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# `FILE.' does not work on cygwin managed mounts. +func_source () +{ + $opt_debug + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $opt_debug + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_quote_for_eval "$arg" + CC_quoted="$CC_quoted $func_quote_for_eval_result" + done + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_quote_for_eval "$arg" + CC_quoted="$CC_quoted $func_quote_for_eval_result" + done + case "$@ " in + " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with \`--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=${1} + if test "$build_libtool_libs" = yes; then + write_lobj=\'${2}\' + else + write_lobj=none + fi + + if test "$build_old_libs" = yes; then + write_oldobj=\'${3}\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T <?"'"'"' &()|`$[]' \ + && func_warning "libobj name \`$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname="$func_basename_result" + xdir="$func_dirname_result" + lobj=${xdir}$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$ECHO "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + removelist="$removelist $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + removelist="$removelist $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + command="$command -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test "$suppress_opt" = yes; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test "$compiler_c_o" = yes; then + command="$command -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + command="$command$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { +test "$mode" = compile && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -shared do not build a \`.o' file suitable for static linking + -static only build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode \`$mode'" + ;; + esac + + $ECHO + $ECHO "Try \`$progname --help' for more information about other modes." + + exit $? +} + + # Now that we've collected a possible --mode arg, show help if necessary + $opt_help && func_mode_help + + +# func_mode_execute arg... +func_mode_execute () +{ + $opt_debug + # The first argument is the command name. + cmd="$nonopt" + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + test -f "$file" \ + || func_fatal_help "\`$file' is not a file" + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "\`$file' was not linked with \`-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir="$func_dirname_result" + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir="$func_dirname_result" + ;; + + *) + func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file="$progdir/$program" + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_quote_for_eval "$file" + args="$args $func_quote_for_eval_result" + done + + if test "X$opt_dry_run" = Xfalse; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + $ECHO "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + fi +} + +test "$mode" = execute && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $opt_debug + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_silent && exit $EXIT_SUCCESS + + $ECHO "X----------------------------------------------------------------------" | $Xsed + $ECHO "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + $ECHO + $ECHO "If you ever happen to want to link against installed libraries" + $ECHO "in a given directory, LIBDIR, you must either use libtool, and" + $ECHO "specify the full pathname of the library, or use the \`-LLIBDIR'" + $ECHO "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + $ECHO " - add LIBDIR to the \`$shlibpath_var' environment variable" + $ECHO " during execution" + fi + if test -n "$runpath_var"; then + $ECHO " - add LIBDIR to the \`$runpath_var' environment variable" + $ECHO " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + $ECHO " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + $ECHO + + $ECHO "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + $ECHO "more information, such as the ld(1), crle(1) and ld.so(8) manual" + $ECHO "pages." + ;; + *) + $ECHO "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + $ECHO "X----------------------------------------------------------------------" | $Xsed + exit $EXIT_SUCCESS +} + +test "$mode" = finish && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $opt_debug + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + $ECHO "X$nonopt" | $GREP shtool >/dev/null; then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + install_prog="$install_prog$func_quote_for_eval_result" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + case " $install_prog " in + *[\\\ /]cp\ *) ;; + *) prev=$arg ;; + esac + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + install_prog="$install_prog $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the \`$prev' option requires an argument" + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir="$func_dirname_result" + destname="$func_basename_result" + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "\`$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "\`$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir="$func_dirname_result" + dir="$dir$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking \`$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname="$1" + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme="$stripme" + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme="" + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name="$func_basename_result" + instname="$dir/$name"i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to \`$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script \`$wrapper'" + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "\`$lib' has not been installed in \`$libdir'" + finalize=no + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + $opt_dry_run || { + if test "$finalize" = yes; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file="$func_basename_result" + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_silent || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink \`$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file="$outputname" + else + func_warning "cannot relink \`$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name="$func_basename_result" + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run \`$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test "$mode" = install && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $opt_debug + my_outputname="$1" + my_originator="$2" + my_pic_p="${3-no}" + my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms="${my_outputname}S.c" + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${my_outputname}.nm" + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + func_verbose "generating symbol list for \`$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_verbose "extracting global C symbols from \`$progfile'" + $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $opt_dry_run || { + $RM $export_symbols + eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from \`$dlprefile'" + func_basename "$dlprefile" + name="$func_basename_result" + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + $ECHO >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +" + case $host in + *cygwin* | *mingw* | *cegcc* ) + $ECHO >> "$output_objdir/$my_dlsyms" "\ +/* DATA imports from DLLs on WIN32 con't be const, because + runtime relocations are performed -- see ld's documentation + on pseudo-relocs. */" + lt_dlsym_const= ;; + *osf5*) + echo >> "$output_objdir/$my_dlsyms" "\ +/* This system does not cope well with relocations in const data */" + lt_dlsym_const= ;; + *) + lt_dlsym_const=const ;; + esac + + $ECHO >> "$output_objdir/$my_dlsyms" "\ +extern $lt_dlsym_const lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[]; +$lt_dlsym_const lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{\ + { \"$my_originator\", (void *) 0 }," + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + $ECHO >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + if test "X$my_pic_p" != Xno; then + pic_flag_for_symtable=" $pic_flag" + fi + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) symtab_cflags="$symtab_cflags $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' + + # Transform the symbol file into the correct name. + symfileobj="$output_objdir/${my_outputname}S.$objext" + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for \`$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +func_win32_libid () +{ + $opt_debug + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then + win32_nmres=`eval $NM -f posix -A $1 | + $SED -n -e ' + 1,100{ + / I /{ + s,.*,import, + p + q + } + }'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $opt_debug + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?' + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $opt_debug + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib="$func_basename_result" + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir="$my_gentop/$my_xlib_u" + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`basename "$darwin_archive"` + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + + func_extract_archives_result="$my_oldobjs" +} + + + +# func_emit_wrapper_part1 [arg=no] +# +# Emit the first part of a libtool wrapper script on stdout. +# For more information, see the description associated with +# func_emit_wrapper(), below. +func_emit_wrapper_part1 () +{ + func_emit_wrapper_part1_arg1=no + if test -n "$1" ; then + func_emit_wrapper_part1_arg1=$1 + fi + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='${SED} -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + 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 + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + ECHO=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$ECHO works! + : + else + # Restart under the correct shell, and then maybe \$ECHO will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $ECHO "\ + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + done +" +} +# end: func_emit_wrapper_part1 + +# func_emit_wrapper_part2 [arg=no] +# +# Emit the second part of a libtool wrapper script on stdout. +# For more information, see the description associated with +# func_emit_wrapper(), below. +func_emit_wrapper_part2 () +{ + func_emit_wrapper_part2_arg1=no + if test -n "$1" ; then + func_emit_wrapper_part2_arg1=$1 + fi + + $ECHO "\ + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} +# end: func_emit_wrapper_part2 + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory in which it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=no + if test -n "$1" ; then + func_emit_wrapper_arg1=$1 + fi + + # split this up so that func_emit_cwrapperexe_src + # can call each part independently. + func_emit_wrapper_part1 "${func_emit_wrapper_arg1}" + func_emit_wrapper_part2 "${func_emit_wrapper_arg1}" +} + + +# func_to_host_path arg +# +# Convert paths to host format when used with build tools. +# Intended for use with "native" mingw (where libtool itself +# is running under the msys shell), or in the following cross- +# build environments: +# $build $host +# mingw (msys) mingw [e.g. native] +# cygwin mingw +# *nix + wine mingw +# where wine is equipped with the `winepath' executable. +# In the native mingw case, the (msys) shell automatically +# converts paths for any non-msys applications it launches, +# but that facility isn't available from inside the cwrapper. +# Similar accommodations are necessary for $host mingw and +# $build cygwin. Calling this function does no harm for other +# $host/$build combinations not listed above. +# +# ARG is the path (on $build) that should be converted to +# the proper representation for $host. The result is stored +# in $func_to_host_path_result. +func_to_host_path () +{ + func_to_host_path_result="$1" + if test -n "$1" ; then + case $host in + *mingw* ) + lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + case $build in + *mingw* ) # actually, msys + # awkward: cmd appends spaces to result + lt_sed_strip_trailing_spaces="s/[ ]*\$//" + func_to_host_path_tmp1=`( cmd //c echo "$1" |\ + $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + *cygwin* ) + func_to_host_path_tmp1=`cygpath -w "$1"` + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + * ) + # Unfortunately, winepath does not exit with a non-zero + # error code, so we are forced to check the contents of + # stdout. On the other hand, if the command is not + # found, the shell will set an exit code of 127 and print + # *an error message* to stdout. So we must check for both + # error code of zero AND non-empty stdout, which explains + # the odd construction: + func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null` + if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + else + # Allow warning below. + func_to_host_path_result="" + fi + ;; + esac + if test -z "$func_to_host_path_result" ; then + func_error "Could not determine host path corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_path_result="$1" + fi + ;; + esac + fi +} +# end: func_to_host_path + +# func_to_host_pathlist arg +# +# Convert pathlists to host format when used with build tools. +# See func_to_host_path(), above. This function supports the +# following $build/$host combinations (but does no harm for +# combinations not listed here): +# $build $host +# mingw (msys) mingw [e.g. native] +# cygwin mingw +# *nix + wine mingw +# +# Path separators are also converted from $build format to +# $host format. If ARG begins or ends with a path separator +# character, it is preserved (but converted to $host format) +# on output. +# +# ARG is a pathlist (on $build) that should be converted to +# the proper representation on $host. The result is stored +# in $func_to_host_pathlist_result. +func_to_host_pathlist () +{ + func_to_host_pathlist_result="$1" + if test -n "$1" ; then + case $host in + *mingw* ) + lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_to_host_pathlist_tmp2="$1" + # Once set for this call, this variable should not be + # reassigned. It is used in tha fallback case. + func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e 's|^:*||' -e 's|:*$||'` + case $build in + *mingw* ) # Actually, msys. + # Awkward: cmd appends spaces to result. + lt_sed_strip_trailing_spaces="s/[ ]*\$//" + func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\ + $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + *cygwin* ) + func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"` + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + * ) + # unfortunately, winepath doesn't convert pathlists + func_to_host_pathlist_result="" + func_to_host_pathlist_oldIFS=$IFS + IFS=: + for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do + IFS=$func_to_host_pathlist_oldIFS + if test -n "$func_to_host_pathlist_f" ; then + func_to_host_path "$func_to_host_pathlist_f" + if test -n "$func_to_host_path_result" ; then + if test -z "$func_to_host_pathlist_result" ; then + func_to_host_pathlist_result="$func_to_host_path_result" + else + func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result" + fi + fi + fi + IFS=: + done + IFS=$func_to_host_pathlist_oldIFS + ;; + esac + if test -z "$func_to_host_pathlist_result" ; then + func_error "Could not determine the host path(s) corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This may break if $1 contains DOS-style drive + # specifications. The fix is not to complicate the expression + # below, but for the user to provide a working wine installation + # with winepath so that path translation in the cross-to-mingw + # case works properly. + lt_replace_pathsep_nix_to_dos="s|:|;|g" + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\ + $SED -e "$lt_replace_pathsep_nix_to_dos"` + fi + # Now, add the leading and trailing path separators back + case "$1" in + :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result" + ;; + esac + case "$1" in + *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;" + ;; + esac + ;; + esac + fi +} +# end: func_to_host_pathlist + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +# define setmode _setmode +#else +# include +# include +# ifdef __CYGWIN__ +# include +# define HAVE_SETENV +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +#ifdef _MSC_VER +# define S_IXUSR _S_IEXEC +# define stat _stat +# ifndef _INTPTR_T_DEFINED +# define intptr_t int +# endif +#endif + +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifdef __CYGWIN__ +# define FOPEN_WB "wb" +#endif + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +#undef LTWRAPPER_DEBUGPRINTF +#if defined DEBUGWRAPPER +# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args +static void +ltwrapper_debugprintf (const char *fmt, ...) +{ + va_list args; + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); +} +#else +# define LTWRAPPER_DEBUGPRINTF(args) +#endif + +const char *program_name = NULL; + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_fatal (const char *message, ...); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_opt_process_env_set (const char *arg); +void lt_opt_process_env_prepend (const char *arg); +void lt_opt_process_env_append (const char *arg); +int lt_split_name_value (const char *arg, char** name, char** value); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); + +static const char *script_text_part1 = +EOF + + func_emit_wrapper_part1 yes | + $SED -e 's/\([\\"]\)/\\\1/g' \ + -e 's/^/ "/' -e 's/$/\\n"/' + echo ";" + cat <"))); + for (i = 0; i < newargc; i++) + { + LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : ""))); + } + +EOF + + case $host_os in + mingw*) + cat <<"EOF" + /* execv doesn't actually work on mingw as expected on unix */ + rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz); + if (rval == -1) + { + /* failed to start process */ + LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno)); + return 127; + } + return rval; +EOF + ;; + *) + cat <<"EOF" + execv (lt_argv_zero, newargz); + return rval; /* =127, but avoids unused variable warning */ +EOF + ;; + esac + + cat <<"EOF" +} + +void * +xmalloc (size_t num) +{ + void *p = (void *) malloc (num); + if (!p) + lt_fatal ("Memory exhausted"); + + return p; +} + +char * +xstrdup (const char *string) +{ + return string ? strcpy ((char *) xmalloc (strlen (string) + 1), + string) : NULL; +} + +const char * +base_name (const char *name) +{ + const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Skip over the disk name in MSDOS pathnames. */ + if (isalpha ((unsigned char) name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + return base; +} + +int +check_executable (const char *path) +{ + struct stat st; + + LTWRAPPER_DEBUGPRINTF (("(check_executable) : %s\n", + path ? (*path ? path : "EMPTY!") : "NULL!")); + if ((!path) || (!*path)) + return 0; + + if ((stat (path, &st) >= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + LTWRAPPER_DEBUGPRINTF (("(make_executable) : %s\n", + path ? (*path ? path : "EMPTY!") : "NULL!")); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char *concat_name; + + LTWRAPPER_DEBUGPRINTF (("(find_executable) : %s\n", + wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!")); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n", + tmp_pathspec)); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + char *errstr = strerror (errno); + lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal ("Could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp (str, pat) == 0) + *str = '\0'; + } + return str; +} + +static void +lt_error_core (int exit_status, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s: %s: ", program_name, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, "FATAL", message, ap); + va_end (ap); +} + +void +lt_setenv (const char *name, const char *value) +{ + LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n", + (name ? name : ""), + (value ? value : ""))); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + int len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + int orig_value_len = strlen (orig_value); + int add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +int +lt_split_name_value (const char *arg, char** name, char** value) +{ + const char *p; + int len; + if (!arg || !*arg) + return 1; + + p = strchr (arg, (int)'='); + + if (!p) + return 1; + + *value = xstrdup (++p); + + len = strlen (arg) - strlen (*value); + *name = XMALLOC (char, len); + strncpy (*name, arg, len-1); + (*name)[len - 1] = '\0'; + + return 0; +} + +void +lt_opt_process_env_set (const char *arg) +{ + char *name = NULL; + char *value = NULL; + + if (lt_split_name_value (arg, &name, &value) != 0) + { + XFREE (name); + XFREE (value); + lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg); + } + + lt_setenv (name, value); + XFREE (name); + XFREE (value); +} + +void +lt_opt_process_env_prepend (const char *arg) +{ + char *name = NULL; + char *value = NULL; + char *new_value = NULL; + + if (lt_split_name_value (arg, &name, &value) != 0) + { + XFREE (name); + XFREE (value); + lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg); + } + + new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + XFREE (name); + XFREE (value); +} + +void +lt_opt_process_env_append (const char *arg) +{ + char *name = NULL; + char *value = NULL; + char *new_value = NULL; + + if (lt_split_name_value (arg, &name, &value) != 0) + { + XFREE (name); + XFREE (value); + lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg); + } + + new_value = lt_extend_str (getenv (name), value, 1); + lt_setenv (name, new_value); + XFREE (new_value); + XFREE (name); + XFREE (value); +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + (name ? name : ""), + (value ? value : ""))); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + int len = strlen (new_value); + while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[len-1] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + (name ? name : ""), + (value ? value : ""))); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + + +EOF +} +# end: func_emit_cwrapperexe_src + +# func_mode_link arg... +func_mode_link () +{ + $opt_debug + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module="${wl}-single_module" + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + test -f "$arg" \ + || func_fatal_error "symbol file \`$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) deplibs="$deplibs $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# moreargs="$moreargs $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file \`$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + weak) + weak_libs="$weak_libs $arg" + prev= + continue + ;; + xcclinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "\`-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname '-L' '' "$arg" + dir=$func_stripname_result + if test -z "$dir"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between \`-L' and \`$1'" + else + func_fatal_error "need path for \`-L' option" + fi + fi + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of \`$dir'" + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + deplibs="$deplibs System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + deplibs="$deplibs $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot) + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;; + esac + continue + ;; + + -multi_module) + single_module="${wl}-multi_module" + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "\`-no-install' is ignored for $host" + func_warning "assuming \`-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + arg="$arg $wl$func_quote_for_eval_result" + compiler_flags="$compiler_flags $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + arg="$arg $wl$func_quote_for_eval_result" + compiler_flags="$compiler_flags $wl$func_quote_for_eval_result" + linker_flags="$linker_flags $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + # -64, -mips[0-9] enable 64-bit mode on the SGI compiler + # -r[0-9][0-9]* specifies the processor on the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler + # +DA*, +DD* enable 64-bit mode on the HP compiler + # -q* pass through compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* pass through architecture-specific + # compiler args for GCC + # -F/path gives path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC + # @file GCC response files + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + func_append compile_command " $arg" + func_append finalize_command " $arg" + compiler_flags="$compiler_flags $arg" + continue + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + *.$objext) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the \`$prevarg' option requires an argument" + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname="$func_basename_result" + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + func_dirname "$output" "/" "" + output_objdir="$func_dirname_result$objdir" + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_duplicate_deps ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$libs $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; + esac + pre_post_deps="$pre_post_deps $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test "$linkmode,$pass" = "lib,link"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs="$tmp_deplibs" + fi + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; + esac + fi + if test "$linkmode,$pass" = "lib,dlpreopen"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + case $lib in + *.la) func_source "$lib" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"` + case " $weak_libs " in + *" $deplib_base "*) ;; + *) deplibs="$deplibs $deplib" ;; + esac + done + done + libs="$dlprefiles" + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + compiler_flags="$compiler_flags $deplib" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + func_warning "\`-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test "$linkmode" = lib; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + *.ltframework) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + newlib_search_path="$newlib_search_path $func_stripname_result" + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + newlib_search_path="$newlib_search_path $func_stripname_result" + ;; + *) + func_warning "\`-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + func_stripname '-R' '' "$deplib" + dir=$func_stripname_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + $ECHO + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because the file extensions .$libext of this argument makes me believe" + $ECHO "*** that it is just a static archive that I should not use here." + else + $ECHO + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + ;; + esac + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + + if test "$found" = yes || test -f "$lib"; then : + else + func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" + fi + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "\`$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_duplicate_deps ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + elif test "$linkmode" != prog && test "$linkmode" != lib; then + func_fatal_error "\`$lib' is not a convenience library" + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + func_fatal_error "cannot -dlopen a convenience library: \`$lib'" + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + dlprefiles="$dlprefiles $lib $dependency_libs" + else + newdlfiles="$newdlfiles $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of \`$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir="$ladir" + fi + ;; + esac + func_basename "$lib" + laname="$func_basename_result" + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library \`$lib' was moved." + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir" && test "$linkmode" = prog; then + func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + newlib_search_path="$newlib_search_path $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + newlib_search_path="$newlib_search_path $func_stripname_result" + ;; + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_duplicate_deps ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { { test "$prefer_static_libs" = no || + test "$prefer_static_libs,$installed" = "built,yes"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath:" in + *"$absdir:"*) ;; + *) temp_rpath="$temp_rpath$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc*) + # No point in relinking DLLs because paths are not encoded + notinst_deplibs="$notinst_deplibs $lib" + need_relink=no + ;; + *) + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule="" + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule="$dlpremoduletest" + break + fi + done + if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then + $ECHO + if test "$linkmode" = prog; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname="$1" + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc*) + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + func_basename "$soroot" + soname="$func_basename_result" + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from \`$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for \`$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we can not + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null ; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + $ECHO + $ECHO "*** And there doesn't seem to be a static archive available" + $ECHO "*** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + elif test -n "$old_library"; then + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && + test "$hardcode_minus_L" != yes && + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + $ECHO + $ECHO "*** Warning: This system can not link to static lib archive $lib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + $ECHO "*** But as you try to build a module library, libtool will still create " + $ECHO "*** a static module, that should work as long as the dlopening application" + $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + $ECHO + $ECHO "*** However, this would only work if libtool was able to extract symbol" + $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" + $ECHO "*** not find such a program. So, this module is probably useless." + $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$newlib_search_path $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + if $opt_duplicate_deps ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path="$deplib" ;; + *.la) + func_dirname "$deplib" "" "." + dir="$func_dirname_result" + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of \`$dir'" + absdir="$dir" + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl" ; then + depdepl="$absdir/$objdir/$depdepl" + darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" + linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}" + path= + fi + fi + ;; + *) + path="-L$absdir/$objdir" + ;; + esac + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "\`$deplib' seems to be moved" + + path="-L$absdir" + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test "$pass" = link; then + if test "$linkmode" = "prog"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + tmp_libs="$tmp_libs $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + fi + if test "$linkmode" = prog || test "$linkmode" = lib; then + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "\`-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "\`-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test "$module" = no && \ + func_fatal_help "libtool library \`$output' must begin with \`lib'" + + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" + else + $ECHO + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + test "$dlself" != no && \ + func_warning "\`-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test "$#" -gt 1 && \ + func_warning "ignoring multiple \`-rpath's for a libtool library" + + install_libdir="$1" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "\`-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + shift + IFS="$save_ifs" + + test -n "$7" && \ + func_fatal_help "too many parameters to \`-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$1" + number_minor="$2" + number_revision="$3" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_minor" + lt_irix_increment=no + ;; + *) + func_fatal_configuration "$modename: unknown library version type \`$version_type'" + ;; + esac + ;; + no) + current="$1" + revision="$2" + age="$3" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT \`$current' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION \`$revision' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE \`$age' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE \`$age' is greater than the current interface number \`$current'" + func_fatal_error "\`$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current" + ;; + + irix | nonstopux) + if test "X$lt_irix_increment" = "Xno"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + qnx) + major=".$current" + versuffix=".$current" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + + *) + func_fatal_configuration "unknown library version type \`$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + func_warning "undefined symbols not allowed in $host shared libraries" + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + fi + + func_generate_dlsyms "$libname" "$libname" "yes" + libobjs="$libobjs $symfileobj" + test "X$libobjs" = "X " && libobjs= + + if test "$mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + removelist="$removelist $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"` + # deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"` + # dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) dlfiles="$dlfiles $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + deplibs="$deplibs -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $ECHO + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $ECHO + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \ + -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"` + done + fi + if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' | + $GREP . >/dev/null; then + $ECHO + if test "X$deplibs_check_method" = "Xnone"; then + $ECHO "*** Warning: inter-library dependencies are not supported in this platform." + else + $ECHO "*** Warning: inter-library dependencies are not known to be supported." + fi + $ECHO "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + $ECHO + $ECHO "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + $ECHO "*** a static module, that should work as long as the dlopening" + $ECHO "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + $ECHO + $ECHO "*** However, this would only work if libtool was able to extract symbol" + $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" + $ECHO "*** not find such a program. So, this module is probably useless." + $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + $ECHO "*** The inter-library dependencies that have been dropped here will be" + $ECHO "*** automatically added whenever a program is linked with this library" + $ECHO "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + $ECHO + $ECHO "*** Since this library must not contain undefined symbols," + $ECHO "*** because either the platform does not support them or" + $ECHO "*** it was explicitly requested with -no-undefined," + $ECHO "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + deplibs="$new_libs" + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname="$1" + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + linknames="$linknames $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols="$output_objdir/$libname.uexp" + delfiles="$delfiles $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + if test "x`$SED 1q $export_symbols`" != xEXPORTS; then + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols="$export_symbols" + export_symbols= + always_export_symbols=yes + fi + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + func_len " $cmd" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' + fi + + if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + tmp_deplibs="$tmp_deplibs $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test "$compiler_needs_object" = yes && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + libobjs="$libobjs $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + output_la=`$ECHO "X$output" | $Xsed -e "$basename"` + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then + output=${output_objdir}/${output_la}.lnkscript + func_verbose "creating GNU ld script: $output" + $ECHO 'INPUT (' > $output + for obj in $save_libobjs + do + $ECHO "$obj" >> $output + done + $ECHO ')' >> $output + delfiles="$delfiles $output" + elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then + output=${output_objdir}/${output_la}.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test "$compiler_needs_object" = yes; then + firstobj="$1 " + shift + fi + for obj + do + $ECHO "$obj" >> $output + done + delfiles="$delfiles $output" + output=$firstobj\"$file_list_spec$output\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-${k}.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test "X$objlist" = X || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + eval concat_cmds=\"$reload_cmds $objlist $last_robj\" + else + # All subsequent reloadable object files will link in + # the last one created. + eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-${k}.$objext + objlist=$obj + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" + if test -n "$last_robj"; then + eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" + fi + delfiles="$delfiles $output" + + else + output= + fi + + if ${skipped_export-false}; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + fi + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + if ${skipped_export-false}; then + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + fi + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $dlprefiles + libobjs="$libobjs $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "\`-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object \`$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec and hope we can get by with + # turning comma into space.. + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` + else + gentop="$output_objdir/${obj}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "\`-release' is ignored for programs" + + test "$preload" = yes \ + && test "$dlopen_support" = unknown \ + && test "$dlopen_self" = unknown \ + && test "$dlopen_self_static" = unknown && \ + func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test "$tagname" = CXX ; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + compile_command="$compile_command ${wl}-bind_at_load" + finalize_command="$finalize_command ${wl}-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + compile_command="$compile_command $compile_deplibs" + finalize_command="$finalize_command $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" "no" + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=yes + case $host in + *cygwin* | *mingw* ) + if test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + *cegcc) + # Disable wrappers for cegcc, we are cross compiling anyway. + wrappers_required=no + ;; + *) + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + esac + if test "$wrappers_required" = no; then + # Replace the output file specification. + compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.${objext}"; then + func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' + fi + + exit $exit_status + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "\`$output' will be relinked during installation" + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $ECHO for shipping. + if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then + case $progpath in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; + *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; + esac + qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host" ; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save $symfileobj" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + if test "$preload" = yes && test -f "$symfileobj"; then + oldobjs="$oldobjs $symfileobj" + fi + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $addlibs + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $dlprefiles + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + $ECHO "copying selected object files to avoid basename conflicts..." + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase="$func_basename_result" + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + oldobjs="$oldobjs $gentop/$newobj" + ;; + *) oldobjs="$oldobjs $obj" ;; + esac + done + fi + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + newdependency_libs="$newdependency_libs $libdir/$name" + ;; + *) newdependency_libs="$newdependency_libs $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + newdlfiles="$newdlfiles $libdir/$name" + ;; + *) newdlfiles="$newdlfiles $lib" ;; + esac + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + newdlprefiles="$newdlprefiles $libdir/$name" + ;; + esac + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlfiles="$newdlfiles $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlprefiles="$newdlprefiles $abs" + done + dlprefiles="$newdlprefiles" + fi + $RM $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +{ test "$mode" = link || test "$mode" = relink; } && + func_mode_link ${1+"$@"} + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $opt_debug + RM="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) RM="$RM $arg"; rmforce=yes ;; + -*) RM="$RM $arg" ;; + *) files="$files $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + origobjdir="$objdir" + for file in $files; do + func_dirname "$file" "" "." + dir="$func_dirname_result" + if test "X$dir" = X.; then + objdir="$origobjdir" + else + objdir="$dir/$origobjdir" + fi + func_basename "$file" + name="$func_basename_result" + test "$mode" = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test "$mode" = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + + case "$mode" in + clean) + case " $library_names " in + # " " in the beginning catches empty $dlname + *" $dlname "*) ;; + *) rmfiles="$rmfiles $objdir/$dlname" ;; + esac + test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && + test "$pic_object" != none; then + rmfiles="$rmfiles $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && + test "$non_pic_object" != none; then + rmfiles="$rmfiles $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$mode" = clean ; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + rmfiles="$rmfiles $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + rmfiles="$rmfiles $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + rmfiles="$rmfiles $objdir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + objdir="$origobjdir" + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +{ test "$mode" = uninstall || test "$mode" = clean; } && + func_mode_uninstall ${1+"$@"} + +test -z "$mode" && { + help="$generic_help" + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode \`$mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: +# vi:sw=2 + + +# ### BEGIN LIBTOOL TAG CONFIG: CXX + +# The linker used to build libraries. +LD="/usr/bin/ld -m elf_x86_64" + +# Commands used to build an old-style archive. +old_archive_cmds="\$AR \$AR_FLAGS \$oldlib\$oldobjs~\$RANLIB \$oldlib" + +# A language specific compiler. +CC="g++" + +# Is the compiler the GNU compiler? +with_gcc=yes + +# Compiler flag to turn off builtin functions. +no_builtin_flag=" -fno-builtin" + +# How to pass a linker flag through the compiler. +wl="-Wl," + +# Additional compiler flags for building library objects. +pic_flag=" -fPIC -DPIC" + +# Compiler flag to prevent dynamic linking. +link_static_flag="-static" + +# Does compiler simultaneously support -c and -o options? +compiler_c_o="yes" + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=no + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=no + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec="\${wl}--export-dynamic" + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec="\${wl}--whole-archive\$convenience \${wl}--no-whole-archive" + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object="no" + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds="" + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds="" + +# Commands used to build a shared archive. +archive_cmds="\$CC -shared -nostdlib \$predep_objects \$libobjs \$deplibs \$postdep_objects \$compiler_flags \${wl}-soname \$wl\$soname -o \$lib" +archive_expsym_cmds="\$CC -shared -nostdlib \$predep_objects \$libobjs \$deplibs \$postdep_objects \$compiler_flags \${wl}-soname \$wl\$soname \${wl}-retain-symbols-file \$wl\$export_symbols -o \$lib" + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds="" +module_expsym_cmds="" + +# Whether we are building with GNU ld or not. +with_gnu_ld="yes" + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag="" + +# Flag that enforces no undefined symbols. +no_undefined_flag="" + +# Flag to hardcode $libdir into a binary during linking. +# This must work even if $libdir does not exist +hardcode_libdir_flag_spec="\${wl}-rpath \${wl}\$libdir" + +# If ld is used when linking, flag to hardcode $libdir into a binary +# during linking. This must work even if $libdir does not exist. +hardcode_libdir_flag_spec_ld="" + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator="" + +# Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=no + +# Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting ${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=no + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=no + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=unsupported + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=no + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=no + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=no + +# Fix the shell variable $srcfile for the compiler. +fix_srcfile_path="" + +# Set to "yes" if exported symbols are required. +always_export_symbols=no + +# The commands to list exported symbols. +export_symbols_cmds="\$NM \$libobjs \$convenience | \$global_symbol_pipe | \$SED 's/.* //' | sort | uniq > \$export_symbols" + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms="_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*" + +# Symbols that must always be exported. +include_expsyms="" + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds="" + +# Specify filename containing input files. +file_list_spec="" + +# How to hardcode a shared library path into an executable. +hardcode_action=immediate + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs="/usr/lib/gcc/x86_64-redhat-linux/4.1.2 /usr/lib/gcc/x86_64-redhat-linux/4.1.2 /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64 /lib/../lib64 /usr/lib/../lib64" + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects="/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.1.2/crtbeginS.o" +postdep_objects="/usr/lib/gcc/x86_64-redhat-linux/4.1.2/crtendS.o /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crtn.o" +predeps="" +postdeps="-lstdc++ -lm -lgcc_s -lc -lgcc_s" + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path="-L/usr/lib/gcc/x86_64-redhat-linux/4.1.2 -L/usr/lib/gcc/x86_64-redhat-linux/4.1.2 -L/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64" + +# ### END LIBTOOL TAG CONFIG: CXX diff --git a/snappy/snappy-1.0.5/ltmain.sh b/snappy/snappy-1.0.5/ltmain.sh new file mode 100755 index 00000000..7ed280bc --- /dev/null +++ b/snappy/snappy-1.0.5/ltmain.sh @@ -0,0 +1,8413 @@ +# Generated from ltmain.m4sh. + +# ltmain.sh (GNU libtool) 2.2.6b +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool 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. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, +# or obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Usage: $progname [OPTION]... [MODE-ARG]... +# +# Provide generalized library-building support services. +# +# --config show all configuration variables +# --debug enable verbose shell tracing +# -n, --dry-run display commands without modifying any files +# --features display basic configuration information and exit +# --mode=MODE use operation mode MODE +# --preserve-dup-deps don't remove duplicate dependency libraries +# --quiet, --silent don't print informational messages +# --tag=TAG use configuration variables from tag TAG +# -v, --verbose print informational messages (default) +# --version print version information +# -h, --help print short or long help message +# +# MODE must be one of the following: +# +# clean remove files from the build directory +# compile compile a source file into a libtool object +# execute automatically set library path, then run a program +# finish complete the installation of libtool libraries +# install install libraries or executables +# link create a library or an executable +# uninstall remove libraries from an installed directory +# +# MODE-ARGS vary depending on the MODE. +# Try `$progname --help --mode=MODE' for a more detailed description of MODE. +# +# When reporting a bug, please describe a test case to reproduce it and +# include the following information: +# +# host-triplet: $host +# shell: $SHELL +# compiler: $LTCC +# compiler flags: $LTCFLAGS +# linker: $LD (gnu? $with_gnu_ld) +# $progname: (GNU libtool) 2.2.6b Debian-2.2.6b-2ubuntu1 +# automake: $automake_version +# autoconf: $autoconf_version +# +# Report bugs to . + +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION="2.2.6b Debian-2.2.6b-2ubuntu1" +TIMESTAMP="" +package_revision=1.3017 + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + 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 + +# NLS nuisances: We save the old values to restore during execute mode. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +lt_user_locale= +lt_safe_locale= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test \"\${$lt_var+set}\" = set; then + save_$lt_var=\$$lt_var + $lt_var=C + export $lt_var + lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" + lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + fi" +done + +$lt_unset CDPATH + + + + + +: ${CP="cp -f"} +: ${ECHO="echo"} +: ${EGREP="/bin/grep -E"} +: ${FGREP="/bin/grep -F"} +: ${GREP="/bin/grep"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SED="/bin/sed"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} +: ${Xsed="$SED -e 1s/^X//"} + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +exit_status=$EXIT_SUCCESS + +# Make sure IFS has a sensible default +lt_nl=' +' +IFS=" $lt_nl" + +dirname="s,/[^/]*$,," +basename="s,^.*/,," + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi + func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` +} + +# Generated shell functions inserted here. + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + +# The name of this program: +# In the unlikely event $progname began with a '-', it would play havoc with +# func_echo (imagine progname=-n), so we prepend ./ in that case: +func_dirname_and_basename "$progpath" +progname=$func_basename_result +case $progname in + -*) progname=./$progname ;; +esac + +# Make sure we have an absolute path for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=$func_dirname_result + progdir=`cd "$progdir" && pwd` + progpath="$progdir/$progname" + ;; + *) + save_IFS="$IFS" + IFS=: + for progdir in $PATH; do + IFS="$save_IFS" + test -x "$progdir/$progname" && break + done + IFS="$save_IFS" + test -n "$progdir" || progdir=`pwd` + progpath="$progdir/$progname" + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed="${SED}"' -e 1s/^X//' +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Re-`\' parameter expansions in output of double_quote_subst that were +# `\'-ed in input to the same. If an odd number of `\' preceded a '$' +# in input to double_quote_subst, that '$' was protected from expansion. +# Since each input `\' is now two `\'s, look for any number of runs of +# four `\'s followed by two `\'s and then a '$'. `\' that '$'. +bs='\\' +bs2='\\\\' +bs4='\\\\\\\\' +dollar='\$' +sed_double_backslash="\ + s/$bs4/&\\ +/g + s/^$bs2$dollar/$bs&/ + s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g + s/\n//g" + +# Standard options: +opt_dry_run=false +opt_help=false +opt_quiet=false +opt_verbose=false +opt_warning=: + +# func_echo arg... +# Echo program name prefixed message, along with the current mode +# name if it has been set yet. +func_echo () +{ + $ECHO "$progname${mode+: }$mode: $*" +} + +# func_verbose arg... +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $opt_verbose && func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + +# func_error arg... +# Echo program name prefixed message to standard error. +func_error () +{ + $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2 +} + +# func_warning arg... +# Echo program name prefixed warning message to standard error. +func_warning () +{ + $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2 + + # bash bug again: + : +} + +# func_fatal_error arg... +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + +# func_fatal_help arg... +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + func_error ${1+"$@"} + func_fatal_error "$help" +} +help="Try \`$progname --help' for more information." ## default + + +# func_grep expression filename +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_mkdir_p directory-path +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + my_directory_path="$1" + my_dir_list= + + if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then + + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$my_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + my_dir_list="$my_directory_path:$my_dir_list" + + # If the last portion added has no slash in it, the list is done + case $my_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"` + done + my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'` + + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$my_dir" 2>/dev/null || : + done + IFS="$save_mkdir_p_IFS" + + # Bail out if we (or some other process) failed to create a directory. + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" + fi +} + + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$opt_dry_run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || \ + func_fatal_error "cannot create temporary directory \`$my_tmpdir'" + fi + + $ECHO "X$my_tmpdir" | $Xsed +} + + +# func_quote_for_eval arg +# Aesthetically quote ARG to be evaled later. +# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT +# is double-quoted, suitable for a subsequent eval, whereas +# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters +# which are still active within double quotes backslashified. +func_quote_for_eval () +{ + case $1 in + *[\\\`\"\$]*) + func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;; + *) + func_quote_for_eval_unquoted_result="$1" ;; + esac + + case $func_quote_for_eval_unquoted_result in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and and variable + # expansion for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" + ;; + *) + func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" + esac +} + + +# func_quote_for_expand arg +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + case $1 in + *[\\\`\"]*) + my_arg=`$ECHO "X$1" | $Xsed \ + -e "$double_quote_subst" -e "$sed_double_backslash"` ;; + *) + my_arg="$1" ;; + esac + + case $my_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + my_arg="\"$my_arg\"" + ;; + esac + + func_quote_for_expand_result="$my_arg" +} + + +# func_show_eval cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$my_cmd" + my_status=$? + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + +# func_show_eval_locale cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$lt_user_locale + $my_cmd" + my_status=$? + eval "$lt_safe_locale" + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + + + + +# func_version +# Echo version message to standard output and exit. +func_version () +{ + $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / { + s/^# // + s/^# *$// + s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ + p + }' < "$progpath" + exit $? +} + +# func_usage +# Echo short help message to standard output and exit. +func_usage () +{ + $SED -n '/^# Usage:/,/# -h/ { + s/^# // + s/^# *$// + s/\$progname/'$progname'/ + p + }' < "$progpath" + $ECHO + $ECHO "run \`$progname --help | more' for full usage" + exit $? +} + +# func_help +# Echo long help message to standard output and exit. +func_help () +{ + $SED -n '/^# Usage:/,/# Report bugs to/ { + s/^# // + s/^# *$// + s*\$progname*'$progname'* + s*\$host*'"$host"'* + s*\$SHELL*'"$SHELL"'* + s*\$LTCC*'"$LTCC"'* + s*\$LTCFLAGS*'"$LTCFLAGS"'* + s*\$LD*'"$LD"'* + s/\$with_gnu_ld/'"$with_gnu_ld"'/ + s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ + s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ + p + }' < "$progpath" + exit $? +} + +# func_missing_arg argname +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + func_error "missing argument for $1" + exit_cmd=exit +} + +exit_cmd=: + + + + + +# Check that we have a working $ECHO. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then + # Yippee, $ECHO works! + : +else + # Restart under the correct shell, and then maybe $ECHO will work. + exec $SHELL "$progpath" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + +# Parse options once, thoroughly. This comes as soon as possible in +# the script to make things like `libtool --version' happen quickly. +{ + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + esac + + # Parse non-mode specific arguments: + while test "$#" -gt 0; do + opt="$1" + shift + + case $opt in + --config) func_config ;; + + --debug) preserve_args="$preserve_args $opt" + func_echo "enabling shell trace mode" + opt_debug='set -x' + $opt_debug + ;; + + -dlopen) test "$#" -eq 0 && func_missing_arg "$opt" && break + execute_dlfiles="$execute_dlfiles $1" + shift + ;; + + --dry-run | -n) opt_dry_run=: ;; + --features) func_features ;; + --finish) mode="finish" ;; + + --mode) test "$#" -eq 0 && func_missing_arg "$opt" && break + case $1 in + # Valid mode arguments: + clean) ;; + compile) ;; + execute) ;; + finish) ;; + install) ;; + link) ;; + relink) ;; + uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $opt" + exit_cmd=exit + break + ;; + esac + + mode="$1" + shift + ;; + + --preserve-dup-deps) + opt_duplicate_deps=: ;; + + --quiet|--silent) preserve_args="$preserve_args $opt" + opt_silent=: + ;; + + --verbose| -v) preserve_args="$preserve_args $opt" + opt_silent=false + ;; + + --tag) test "$#" -eq 0 && func_missing_arg "$opt" && break + preserve_args="$preserve_args $opt $1" + func_enable_tag "$1" # tagname is set here + shift + ;; + + # Separate optargs to long options: + -dlopen=*|--mode=*|--tag=*) + func_opt_split "$opt" + set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"} + shift + ;; + + -\?|-h) func_usage ;; + --help) opt_help=: ;; + --version) func_version ;; + + -*) func_fatal_help "unrecognized option \`$opt'" ;; + + *) nonopt="$opt" + break + ;; + esac + done + + + case $host in + *cygwin* | *mingw* | *pw32* | *cegcc*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_duplicate_deps + ;; + esac + + # Having warned about all mis-specified options, bail out if + # anything was wrong. + $exit_cmd $EXIT_FAILURE +} + +# func_check_version_match +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +## ----------- ## +## Main. ## +## ----------- ## + +$opt_help || { + # Sanity checks first: + func_check_version_match + + if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + func_fatal_configuration "not configured to build any kind of library" + fi + + test -z "$mode" && func_fatal_error "error: you must specify a MODE." + + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + func_error "unrecognized option \`-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$progname --help --mode=$mode' for more information." +} + + +# func_lalib_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null \ + | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if `file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case "$lalib_p_line" in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test "$lalib_p" = yes +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + func_lalib_p "$1" +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_ltwrapper_scriptname_result="" + if func_ltwrapper_executable_p "$1"; then + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" + fi +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $opt_debug + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$save_ifs + eval cmd=\"$cmd\" + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# `FILE.' does not work on cygwin managed mounts. +func_source () +{ + $opt_debug + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $opt_debug + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_quote_for_eval "$arg" + CC_quoted="$CC_quoted $func_quote_for_eval_result" + done + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_quote_for_eval "$arg" + CC_quoted="$CC_quoted $func_quote_for_eval_result" + done + case "$@ " in + " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with \`--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=${1} + if test "$build_libtool_libs" = yes; then + write_lobj=\'${2}\' + else + write_lobj=none + fi + + if test "$build_old_libs" = yes; then + write_oldobj=\'${3}\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T <?"'"'"' &()|`$[]' \ + && func_warning "libobj name \`$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname="$func_basename_result" + xdir="$func_dirname_result" + lobj=${xdir}$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$ECHO "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + removelist="$removelist $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + removelist="$removelist $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + command="$command -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test "$suppress_opt" = yes; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test "$compiler_c_o" = yes; then + command="$command -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + command="$command$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { +test "$mode" = compile && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -shared do not build a \`.o' file suitable for static linking + -static only build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode \`$mode'" + ;; + esac + + $ECHO + $ECHO "Try \`$progname --help' for more information about other modes." + + exit $? +} + + # Now that we've collected a possible --mode arg, show help if necessary + $opt_help && func_mode_help + + +# func_mode_execute arg... +func_mode_execute () +{ + $opt_debug + # The first argument is the command name. + cmd="$nonopt" + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + test -f "$file" \ + || func_fatal_help "\`$file' is not a file" + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "\`$file' was not linked with \`-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir="$func_dirname_result" + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir="$func_dirname_result" + ;; + + *) + func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file="$progdir/$program" + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_quote_for_eval "$file" + args="$args $func_quote_for_eval_result" + done + + if test "X$opt_dry_run" = Xfalse; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + $ECHO "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + fi +} + +test "$mode" = execute && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $opt_debug + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_silent && exit $EXIT_SUCCESS + + $ECHO "X----------------------------------------------------------------------" | $Xsed + $ECHO "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + $ECHO + $ECHO "If you ever happen to want to link against installed libraries" + $ECHO "in a given directory, LIBDIR, you must either use libtool, and" + $ECHO "specify the full pathname of the library, or use the \`-LLIBDIR'" + $ECHO "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + $ECHO " - add LIBDIR to the \`$shlibpath_var' environment variable" + $ECHO " during execution" + fi + if test -n "$runpath_var"; then + $ECHO " - add LIBDIR to the \`$runpath_var' environment variable" + $ECHO " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + $ECHO " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + $ECHO + + $ECHO "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + $ECHO "more information, such as the ld(1), crle(1) and ld.so(8) manual" + $ECHO "pages." + ;; + *) + $ECHO "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + $ECHO "X----------------------------------------------------------------------" | $Xsed + exit $EXIT_SUCCESS +} + +test "$mode" = finish && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $opt_debug + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + $ECHO "X$nonopt" | $GREP shtool >/dev/null; then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + install_prog="$install_prog$func_quote_for_eval_result" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + case " $install_prog " in + *[\\\ /]cp\ *) ;; + *) prev=$arg ;; + esac + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + install_prog="$install_prog $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the \`$prev' option requires an argument" + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir="$func_dirname_result" + destname="$func_basename_result" + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "\`$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "\`$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir="$func_dirname_result" + dir="$dir$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking \`$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname="$1" + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme="$stripme" + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme="" + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name="$func_basename_result" + instname="$dir/$name"i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to \`$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script \`$wrapper'" + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "\`$lib' has not been installed in \`$libdir'" + finalize=no + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + $opt_dry_run || { + if test "$finalize" = yes; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file="$func_basename_result" + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_silent || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink \`$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file="$outputname" + else + func_warning "cannot relink \`$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name="$func_basename_result" + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run \`$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test "$mode" = install && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $opt_debug + my_outputname="$1" + my_originator="$2" + my_pic_p="${3-no}" + my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms="${my_outputname}S.c" + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${my_outputname}.nm" + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + func_verbose "generating symbol list for \`$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_verbose "extracting global C symbols from \`$progfile'" + $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $opt_dry_run || { + $RM $export_symbols + eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from \`$dlprefile'" + func_basename "$dlprefile" + name="$func_basename_result" + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + $ECHO >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +" + case $host in + *cygwin* | *mingw* | *cegcc* ) + $ECHO >> "$output_objdir/$my_dlsyms" "\ +/* DATA imports from DLLs on WIN32 con't be const, because + runtime relocations are performed -- see ld's documentation + on pseudo-relocs. */" + lt_dlsym_const= ;; + *osf5*) + echo >> "$output_objdir/$my_dlsyms" "\ +/* This system does not cope well with relocations in const data */" + lt_dlsym_const= ;; + *) + lt_dlsym_const=const ;; + esac + + $ECHO >> "$output_objdir/$my_dlsyms" "\ +extern $lt_dlsym_const lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[]; +$lt_dlsym_const lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{\ + { \"$my_originator\", (void *) 0 }," + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + $ECHO >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + if test "X$my_pic_p" != Xno; then + pic_flag_for_symtable=" $pic_flag" + fi + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) symtab_cflags="$symtab_cflags $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' + + # Transform the symbol file into the correct name. + symfileobj="$output_objdir/${my_outputname}S.$objext" + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for \`$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +func_win32_libid () +{ + $opt_debug + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then + win32_nmres=`eval $NM -f posix -A $1 | + $SED -n -e ' + 1,100{ + / I /{ + s,.*,import, + p + q + } + }'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $opt_debug + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?' + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $opt_debug + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib="$func_basename_result" + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir="$my_gentop/$my_xlib_u" + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`basename "$darwin_archive"` + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + + func_extract_archives_result="$my_oldobjs" +} + + + +# func_emit_wrapper_part1 [arg=no] +# +# Emit the first part of a libtool wrapper script on stdout. +# For more information, see the description associated with +# func_emit_wrapper(), below. +func_emit_wrapper_part1 () +{ + func_emit_wrapper_part1_arg1=no + if test -n "$1" ; then + func_emit_wrapper_part1_arg1=$1 + fi + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='${SED} -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + 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 + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + ECHO=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$ECHO works! + : + else + # Restart under the correct shell, and then maybe \$ECHO will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $ECHO "\ + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + done +" +} +# end: func_emit_wrapper_part1 + +# func_emit_wrapper_part2 [arg=no] +# +# Emit the second part of a libtool wrapper script on stdout. +# For more information, see the description associated with +# func_emit_wrapper(), below. +func_emit_wrapper_part2 () +{ + func_emit_wrapper_part2_arg1=no + if test -n "$1" ; then + func_emit_wrapper_part2_arg1=$1 + fi + + $ECHO "\ + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} +# end: func_emit_wrapper_part2 + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory in which it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=no + if test -n "$1" ; then + func_emit_wrapper_arg1=$1 + fi + + # split this up so that func_emit_cwrapperexe_src + # can call each part independently. + func_emit_wrapper_part1 "${func_emit_wrapper_arg1}" + func_emit_wrapper_part2 "${func_emit_wrapper_arg1}" +} + + +# func_to_host_path arg +# +# Convert paths to host format when used with build tools. +# Intended for use with "native" mingw (where libtool itself +# is running under the msys shell), or in the following cross- +# build environments: +# $build $host +# mingw (msys) mingw [e.g. native] +# cygwin mingw +# *nix + wine mingw +# where wine is equipped with the `winepath' executable. +# In the native mingw case, the (msys) shell automatically +# converts paths for any non-msys applications it launches, +# but that facility isn't available from inside the cwrapper. +# Similar accommodations are necessary for $host mingw and +# $build cygwin. Calling this function does no harm for other +# $host/$build combinations not listed above. +# +# ARG is the path (on $build) that should be converted to +# the proper representation for $host. The result is stored +# in $func_to_host_path_result. +func_to_host_path () +{ + func_to_host_path_result="$1" + if test -n "$1" ; then + case $host in + *mingw* ) + lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + case $build in + *mingw* ) # actually, msys + # awkward: cmd appends spaces to result + lt_sed_strip_trailing_spaces="s/[ ]*\$//" + func_to_host_path_tmp1=`( cmd //c echo "$1" |\ + $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + *cygwin* ) + func_to_host_path_tmp1=`cygpath -w "$1"` + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + * ) + # Unfortunately, winepath does not exit with a non-zero + # error code, so we are forced to check the contents of + # stdout. On the other hand, if the command is not + # found, the shell will set an exit code of 127 and print + # *an error message* to stdout. So we must check for both + # error code of zero AND non-empty stdout, which explains + # the odd construction: + func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null` + if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + else + # Allow warning below. + func_to_host_path_result="" + fi + ;; + esac + if test -z "$func_to_host_path_result" ; then + func_error "Could not determine host path corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_path_result="$1" + fi + ;; + esac + fi +} +# end: func_to_host_path + +# func_to_host_pathlist arg +# +# Convert pathlists to host format when used with build tools. +# See func_to_host_path(), above. This function supports the +# following $build/$host combinations (but does no harm for +# combinations not listed here): +# $build $host +# mingw (msys) mingw [e.g. native] +# cygwin mingw +# *nix + wine mingw +# +# Path separators are also converted from $build format to +# $host format. If ARG begins or ends with a path separator +# character, it is preserved (but converted to $host format) +# on output. +# +# ARG is a pathlist (on $build) that should be converted to +# the proper representation on $host. The result is stored +# in $func_to_host_pathlist_result. +func_to_host_pathlist () +{ + func_to_host_pathlist_result="$1" + if test -n "$1" ; then + case $host in + *mingw* ) + lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_to_host_pathlist_tmp2="$1" + # Once set for this call, this variable should not be + # reassigned. It is used in tha fallback case. + func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e 's|^:*||' -e 's|:*$||'` + case $build in + *mingw* ) # Actually, msys. + # Awkward: cmd appends spaces to result. + lt_sed_strip_trailing_spaces="s/[ ]*\$//" + func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\ + $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + *cygwin* ) + func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"` + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + * ) + # unfortunately, winepath doesn't convert pathlists + func_to_host_pathlist_result="" + func_to_host_pathlist_oldIFS=$IFS + IFS=: + for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do + IFS=$func_to_host_pathlist_oldIFS + if test -n "$func_to_host_pathlist_f" ; then + func_to_host_path "$func_to_host_pathlist_f" + if test -n "$func_to_host_path_result" ; then + if test -z "$func_to_host_pathlist_result" ; then + func_to_host_pathlist_result="$func_to_host_path_result" + else + func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result" + fi + fi + fi + IFS=: + done + IFS=$func_to_host_pathlist_oldIFS + ;; + esac + if test -z "$func_to_host_pathlist_result" ; then + func_error "Could not determine the host path(s) corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This may break if $1 contains DOS-style drive + # specifications. The fix is not to complicate the expression + # below, but for the user to provide a working wine installation + # with winepath so that path translation in the cross-to-mingw + # case works properly. + lt_replace_pathsep_nix_to_dos="s|:|;|g" + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\ + $SED -e "$lt_replace_pathsep_nix_to_dos"` + fi + # Now, add the leading and trailing path separators back + case "$1" in + :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result" + ;; + esac + case "$1" in + *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;" + ;; + esac + ;; + esac + fi +} +# end: func_to_host_pathlist + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +# define setmode _setmode +#else +# include +# include +# ifdef __CYGWIN__ +# include +# define HAVE_SETENV +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +#ifdef _MSC_VER +# define S_IXUSR _S_IEXEC +# define stat _stat +# ifndef _INTPTR_T_DEFINED +# define intptr_t int +# endif +#endif + +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifdef __CYGWIN__ +# define FOPEN_WB "wb" +#endif + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +#undef LTWRAPPER_DEBUGPRINTF +#if defined DEBUGWRAPPER +# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args +static void +ltwrapper_debugprintf (const char *fmt, ...) +{ + va_list args; + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); +} +#else +# define LTWRAPPER_DEBUGPRINTF(args) +#endif + +const char *program_name = NULL; + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_fatal (const char *message, ...); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_opt_process_env_set (const char *arg); +void lt_opt_process_env_prepend (const char *arg); +void lt_opt_process_env_append (const char *arg); +int lt_split_name_value (const char *arg, char** name, char** value); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); + +static const char *script_text_part1 = +EOF + + func_emit_wrapper_part1 yes | + $SED -e 's/\([\\"]\)/\\\1/g' \ + -e 's/^/ "/' -e 's/$/\\n"/' + echo ";" + cat <"))); + for (i = 0; i < newargc; i++) + { + LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : ""))); + } + +EOF + + case $host_os in + mingw*) + cat <<"EOF" + /* execv doesn't actually work on mingw as expected on unix */ + rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz); + if (rval == -1) + { + /* failed to start process */ + LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno)); + return 127; + } + return rval; +EOF + ;; + *) + cat <<"EOF" + execv (lt_argv_zero, newargz); + return rval; /* =127, but avoids unused variable warning */ +EOF + ;; + esac + + cat <<"EOF" +} + +void * +xmalloc (size_t num) +{ + void *p = (void *) malloc (num); + if (!p) + lt_fatal ("Memory exhausted"); + + return p; +} + +char * +xstrdup (const char *string) +{ + return string ? strcpy ((char *) xmalloc (strlen (string) + 1), + string) : NULL; +} + +const char * +base_name (const char *name) +{ + const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Skip over the disk name in MSDOS pathnames. */ + if (isalpha ((unsigned char) name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + return base; +} + +int +check_executable (const char *path) +{ + struct stat st; + + LTWRAPPER_DEBUGPRINTF (("(check_executable) : %s\n", + path ? (*path ? path : "EMPTY!") : "NULL!")); + if ((!path) || (!*path)) + return 0; + + if ((stat (path, &st) >= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + LTWRAPPER_DEBUGPRINTF (("(make_executable) : %s\n", + path ? (*path ? path : "EMPTY!") : "NULL!")); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char *concat_name; + + LTWRAPPER_DEBUGPRINTF (("(find_executable) : %s\n", + wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!")); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n", + tmp_pathspec)); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + char *errstr = strerror (errno); + lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal ("Could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp (str, pat) == 0) + *str = '\0'; + } + return str; +} + +static void +lt_error_core (int exit_status, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s: %s: ", program_name, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, "FATAL", message, ap); + va_end (ap); +} + +void +lt_setenv (const char *name, const char *value) +{ + LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n", + (name ? name : ""), + (value ? value : ""))); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + int len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + int orig_value_len = strlen (orig_value); + int add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +int +lt_split_name_value (const char *arg, char** name, char** value) +{ + const char *p; + int len; + if (!arg || !*arg) + return 1; + + p = strchr (arg, (int)'='); + + if (!p) + return 1; + + *value = xstrdup (++p); + + len = strlen (arg) - strlen (*value); + *name = XMALLOC (char, len); + strncpy (*name, arg, len-1); + (*name)[len - 1] = '\0'; + + return 0; +} + +void +lt_opt_process_env_set (const char *arg) +{ + char *name = NULL; + char *value = NULL; + + if (lt_split_name_value (arg, &name, &value) != 0) + { + XFREE (name); + XFREE (value); + lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg); + } + + lt_setenv (name, value); + XFREE (name); + XFREE (value); +} + +void +lt_opt_process_env_prepend (const char *arg) +{ + char *name = NULL; + char *value = NULL; + char *new_value = NULL; + + if (lt_split_name_value (arg, &name, &value) != 0) + { + XFREE (name); + XFREE (value); + lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg); + } + + new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + XFREE (name); + XFREE (value); +} + +void +lt_opt_process_env_append (const char *arg) +{ + char *name = NULL; + char *value = NULL; + char *new_value = NULL; + + if (lt_split_name_value (arg, &name, &value) != 0) + { + XFREE (name); + XFREE (value); + lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg); + } + + new_value = lt_extend_str (getenv (name), value, 1); + lt_setenv (name, new_value); + XFREE (new_value); + XFREE (name); + XFREE (value); +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + (name ? name : ""), + (value ? value : ""))); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + int len = strlen (new_value); + while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[len-1] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + (name ? name : ""), + (value ? value : ""))); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + + +EOF +} +# end: func_emit_cwrapperexe_src + +# func_mode_link arg... +func_mode_link () +{ + $opt_debug + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module="${wl}-single_module" + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + test -f "$arg" \ + || func_fatal_error "symbol file \`$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) deplibs="$deplibs $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# moreargs="$moreargs $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file \`$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + weak) + weak_libs="$weak_libs $arg" + prev= + continue + ;; + xcclinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "\`-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname '-L' '' "$arg" + dir=$func_stripname_result + if test -z "$dir"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between \`-L' and \`$1'" + else + func_fatal_error "need path for \`-L' option" + fi + fi + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of \`$dir'" + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + deplibs="$deplibs System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + deplibs="$deplibs $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot) + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;; + esac + continue + ;; + + -multi_module) + single_module="${wl}-multi_module" + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "\`-no-install' is ignored for $host" + func_warning "assuming \`-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + arg="$arg $wl$func_quote_for_eval_result" + compiler_flags="$compiler_flags $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + arg="$arg $wl$func_quote_for_eval_result" + compiler_flags="$compiler_flags $wl$func_quote_for_eval_result" + linker_flags="$linker_flags $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + # -64, -mips[0-9] enable 64-bit mode on the SGI compiler + # -r[0-9][0-9]* specifies the processor on the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler + # +DA*, +DD* enable 64-bit mode on the HP compiler + # -q* pass through compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* pass through architecture-specific + # compiler args for GCC + # -F/path gives path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC + # @file GCC response files + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + func_append compile_command " $arg" + func_append finalize_command " $arg" + compiler_flags="$compiler_flags $arg" + continue + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + *.$objext) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the \`$prevarg' option requires an argument" + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname="$func_basename_result" + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + func_dirname "$output" "/" "" + output_objdir="$func_dirname_result$objdir" + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_duplicate_deps ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$libs $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; + esac + pre_post_deps="$pre_post_deps $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test "$linkmode,$pass" = "lib,link"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs="$tmp_deplibs" + fi + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; + esac + fi + if test "$linkmode,$pass" = "lib,dlpreopen"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + case $lib in + *.la) func_source "$lib" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"` + case " $weak_libs " in + *" $deplib_base "*) ;; + *) deplibs="$deplibs $deplib" ;; + esac + done + done + libs="$dlprefiles" + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + compiler_flags="$compiler_flags $deplib" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + func_warning "\`-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test "$linkmode" = lib; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + *.ltframework) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + newlib_search_path="$newlib_search_path $func_stripname_result" + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + newlib_search_path="$newlib_search_path $func_stripname_result" + ;; + *) + func_warning "\`-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + func_stripname '-R' '' "$deplib" + dir=$func_stripname_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + $ECHO + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because the file extensions .$libext of this argument makes me believe" + $ECHO "*** that it is just a static archive that I should not use here." + else + $ECHO + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + ;; + esac + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + + if test "$found" = yes || test -f "$lib"; then : + else + func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" + fi + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "\`$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_duplicate_deps ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + elif test "$linkmode" != prog && test "$linkmode" != lib; then + func_fatal_error "\`$lib' is not a convenience library" + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + func_fatal_error "cannot -dlopen a convenience library: \`$lib'" + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + dlprefiles="$dlprefiles $lib $dependency_libs" + else + newdlfiles="$newdlfiles $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of \`$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir="$ladir" + fi + ;; + esac + func_basename "$lib" + laname="$func_basename_result" + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library \`$lib' was moved." + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir" && test "$linkmode" = prog; then + func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + newlib_search_path="$newlib_search_path $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + newlib_search_path="$newlib_search_path $func_stripname_result" + ;; + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_duplicate_deps ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { { test "$prefer_static_libs" = no || + test "$prefer_static_libs,$installed" = "built,yes"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath:" in + *"$absdir:"*) ;; + *) temp_rpath="$temp_rpath$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc*) + # No point in relinking DLLs because paths are not encoded + notinst_deplibs="$notinst_deplibs $lib" + need_relink=no + ;; + *) + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule="" + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule="$dlpremoduletest" + break + fi + done + if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then + $ECHO + if test "$linkmode" = prog; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname="$1" + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc*) + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + func_basename "$soroot" + soname="$func_basename_result" + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from \`$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for \`$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we can not + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null ; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + $ECHO + $ECHO "*** And there doesn't seem to be a static archive available" + $ECHO "*** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + elif test -n "$old_library"; then + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && + test "$hardcode_minus_L" != yes && + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + $ECHO + $ECHO "*** Warning: This system can not link to static lib archive $lib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + $ECHO "*** But as you try to build a module library, libtool will still create " + $ECHO "*** a static module, that should work as long as the dlopening application" + $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + $ECHO + $ECHO "*** However, this would only work if libtool was able to extract symbol" + $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" + $ECHO "*** not find such a program. So, this module is probably useless." + $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$newlib_search_path $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + if $opt_duplicate_deps ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path="$deplib" ;; + *.la) + func_dirname "$deplib" "" "." + dir="$func_dirname_result" + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of \`$dir'" + absdir="$dir" + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl" ; then + depdepl="$absdir/$objdir/$depdepl" + darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" + linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}" + path= + fi + fi + ;; + *) + path="-L$absdir/$objdir" + ;; + esac + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "\`$deplib' seems to be moved" + + path="-L$absdir" + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test "$pass" = link; then + if test "$linkmode" = "prog"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + tmp_libs="$tmp_libs $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + fi + if test "$linkmode" = prog || test "$linkmode" = lib; then + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "\`-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "\`-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test "$module" = no && \ + func_fatal_help "libtool library \`$output' must begin with \`lib'" + + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" + else + $ECHO + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + test "$dlself" != no && \ + func_warning "\`-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test "$#" -gt 1 && \ + func_warning "ignoring multiple \`-rpath's for a libtool library" + + install_libdir="$1" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "\`-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + shift + IFS="$save_ifs" + + test -n "$7" && \ + func_fatal_help "too many parameters to \`-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$1" + number_minor="$2" + number_revision="$3" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_minor" + lt_irix_increment=no + ;; + *) + func_fatal_configuration "$modename: unknown library version type \`$version_type'" + ;; + esac + ;; + no) + current="$1" + revision="$2" + age="$3" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT \`$current' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION \`$revision' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE \`$age' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE \`$age' is greater than the current interface number \`$current'" + func_fatal_error "\`$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current" + ;; + + irix | nonstopux) + if test "X$lt_irix_increment" = "Xno"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + qnx) + major=".$current" + versuffix=".$current" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + + *) + func_fatal_configuration "unknown library version type \`$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + func_warning "undefined symbols not allowed in $host shared libraries" + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + fi + + func_generate_dlsyms "$libname" "$libname" "yes" + libobjs="$libobjs $symfileobj" + test "X$libobjs" = "X " && libobjs= + + if test "$mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + removelist="$removelist $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"` + # deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"` + # dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) dlfiles="$dlfiles $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + deplibs="$deplibs -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $ECHO + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $ECHO + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \ + -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"` + done + fi + if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' | + $GREP . >/dev/null; then + $ECHO + if test "X$deplibs_check_method" = "Xnone"; then + $ECHO "*** Warning: inter-library dependencies are not supported in this platform." + else + $ECHO "*** Warning: inter-library dependencies are not known to be supported." + fi + $ECHO "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + $ECHO + $ECHO "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + $ECHO "*** a static module, that should work as long as the dlopening" + $ECHO "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + $ECHO + $ECHO "*** However, this would only work if libtool was able to extract symbol" + $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" + $ECHO "*** not find such a program. So, this module is probably useless." + $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + $ECHO "*** The inter-library dependencies that have been dropped here will be" + $ECHO "*** automatically added whenever a program is linked with this library" + $ECHO "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + $ECHO + $ECHO "*** Since this library must not contain undefined symbols," + $ECHO "*** because either the platform does not support them or" + $ECHO "*** it was explicitly requested with -no-undefined," + $ECHO "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + deplibs="$new_libs" + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname="$1" + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + linknames="$linknames $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols="$output_objdir/$libname.uexp" + delfiles="$delfiles $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + if test "x`$SED 1q $export_symbols`" != xEXPORTS; then + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols="$export_symbols" + export_symbols= + always_export_symbols=yes + fi + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + func_len " $cmd" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' + fi + + if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + tmp_deplibs="$tmp_deplibs $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test "$compiler_needs_object" = yes && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + libobjs="$libobjs $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + output_la=`$ECHO "X$output" | $Xsed -e "$basename"` + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then + output=${output_objdir}/${output_la}.lnkscript + func_verbose "creating GNU ld script: $output" + $ECHO 'INPUT (' > $output + for obj in $save_libobjs + do + $ECHO "$obj" >> $output + done + $ECHO ')' >> $output + delfiles="$delfiles $output" + elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then + output=${output_objdir}/${output_la}.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test "$compiler_needs_object" = yes; then + firstobj="$1 " + shift + fi + for obj + do + $ECHO "$obj" >> $output + done + delfiles="$delfiles $output" + output=$firstobj\"$file_list_spec$output\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-${k}.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test "X$objlist" = X || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + eval concat_cmds=\"$reload_cmds $objlist $last_robj\" + else + # All subsequent reloadable object files will link in + # the last one created. + eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-${k}.$objext + objlist=$obj + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" + if test -n "$last_robj"; then + eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" + fi + delfiles="$delfiles $output" + + else + output= + fi + + if ${skipped_export-false}; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + fi + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + if ${skipped_export-false}; then + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + fi + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $dlprefiles + libobjs="$libobjs $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "\`-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object \`$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec and hope we can get by with + # turning comma into space.. + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` + else + gentop="$output_objdir/${obj}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "\`-release' is ignored for programs" + + test "$preload" = yes \ + && test "$dlopen_support" = unknown \ + && test "$dlopen_self" = unknown \ + && test "$dlopen_self_static" = unknown && \ + func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test "$tagname" = CXX ; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + compile_command="$compile_command ${wl}-bind_at_load" + finalize_command="$finalize_command ${wl}-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + compile_command="$compile_command $compile_deplibs" + finalize_command="$finalize_command $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" "no" + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=yes + case $host in + *cygwin* | *mingw* ) + if test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + *cegcc) + # Disable wrappers for cegcc, we are cross compiling anyway. + wrappers_required=no + ;; + *) + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + esac + if test "$wrappers_required" = no; then + # Replace the output file specification. + compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.${objext}"; then + func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' + fi + + exit $exit_status + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "\`$output' will be relinked during installation" + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $ECHO for shipping. + if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then + case $progpath in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; + *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; + esac + qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host" ; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save $symfileobj" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + if test "$preload" = yes && test -f "$symfileobj"; then + oldobjs="$oldobjs $symfileobj" + fi + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $addlibs + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $dlprefiles + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + $ECHO "copying selected object files to avoid basename conflicts..." + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase="$func_basename_result" + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + oldobjs="$oldobjs $gentop/$newobj" + ;; + *) oldobjs="$oldobjs $obj" ;; + esac + done + fi + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + newdependency_libs="$newdependency_libs $libdir/$name" + ;; + *) newdependency_libs="$newdependency_libs $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + newdlfiles="$newdlfiles $libdir/$name" + ;; + *) newdlfiles="$newdlfiles $lib" ;; + esac + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + newdlprefiles="$newdlprefiles $libdir/$name" + ;; + esac + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlfiles="$newdlfiles $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlprefiles="$newdlprefiles $abs" + done + dlprefiles="$newdlprefiles" + fi + $RM $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +{ test "$mode" = link || test "$mode" = relink; } && + func_mode_link ${1+"$@"} + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $opt_debug + RM="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) RM="$RM $arg"; rmforce=yes ;; + -*) RM="$RM $arg" ;; + *) files="$files $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + origobjdir="$objdir" + for file in $files; do + func_dirname "$file" "" "." + dir="$func_dirname_result" + if test "X$dir" = X.; then + objdir="$origobjdir" + else + objdir="$dir/$origobjdir" + fi + func_basename "$file" + name="$func_basename_result" + test "$mode" = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test "$mode" = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + + case "$mode" in + clean) + case " $library_names " in + # " " in the beginning catches empty $dlname + *" $dlname "*) ;; + *) rmfiles="$rmfiles $objdir/$dlname" ;; + esac + test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && + test "$pic_object" != none; then + rmfiles="$rmfiles $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && + test "$non_pic_object" != none; then + rmfiles="$rmfiles $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$mode" = clean ; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + rmfiles="$rmfiles $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + rmfiles="$rmfiles $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + rmfiles="$rmfiles $objdir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + objdir="$origobjdir" + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +{ test "$mode" = uninstall || test "$mode" = clean; } && + func_mode_uninstall ${1+"$@"} + +test -z "$mode" && { + help="$generic_help" + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode \`$mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: +# vi:sw=2 + diff --git a/snappy/snappy-1.0.5/m4/gtest.m4 b/snappy/snappy-1.0.5/m4/gtest.m4 new file mode 100644 index 00000000..98e61f96 --- /dev/null +++ b/snappy/snappy-1.0.5/m4/gtest.m4 @@ -0,0 +1,74 @@ +dnl GTEST_LIB_CHECK([minimum version [, +dnl action if found [,action if not found]]]) +dnl +dnl Check for the presence of the Google Test library, optionally at a minimum +dnl version, and indicate a viable version with the HAVE_GTEST flag. It defines +dnl standard variables for substitution including GTEST_CPPFLAGS, +dnl GTEST_CXXFLAGS, GTEST_LDFLAGS, and GTEST_LIBS. It also defines +dnl GTEST_VERSION as the version of Google Test found. Finally, it provides +dnl optional custom action slots in the event GTEST is found or not. +AC_DEFUN([GTEST_LIB_CHECK], +[ +dnl Provide a flag to enable or disable Google Test usage. +AC_ARG_ENABLE([gtest], + [AS_HELP_STRING([--enable-gtest], + [Enable tests using the Google C++ Testing Framework. + (Default is enabled.)])], + [], + [enable_gtest=]) +AC_ARG_VAR([GTEST_CONFIG], + [The exact path of Google Test's 'gtest-config' script.]) +AC_ARG_VAR([GTEST_CPPFLAGS], + [C-like preprocessor flags for Google Test.]) +AC_ARG_VAR([GTEST_CXXFLAGS], + [C++ compile flags for Google Test.]) +AC_ARG_VAR([GTEST_LDFLAGS], + [Linker path and option flags for Google Test.]) +AC_ARG_VAR([GTEST_LIBS], + [Library linking flags for Google Test.]) +AC_ARG_VAR([GTEST_VERSION], + [The version of Google Test available.]) +HAVE_GTEST="no" +AS_IF([test "x${enable_gtest}" != "xno"], + [AC_MSG_CHECKING([for 'gtest-config']) + AS_IF([test "x${enable_gtest}" = "xyes"], + [AS_IF([test -x "${enable_gtest}/scripts/gtest-config"], + [GTEST_CONFIG="${enable_gtest}/scripts/gtest-config"], + [GTEST_CONFIG="${enable_gtest}/bin/gtest-config"]) + AS_IF([test -x "${GTEST_CONFIG}"], [], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([dnl +Unable to locate either a built or installed Google Test. +The specific location '${enable_gtest}' was provided for a built or installed +Google Test, but no 'gtest-config' script could be found at this location.]) + ])], + [AC_PATH_PROG([GTEST_CONFIG], [gtest-config])]) + AS_IF([test -x "${GTEST_CONFIG}"], + [AC_MSG_RESULT([${GTEST_CONFIG}]) + m4_ifval([$1], + [_gtest_min_version="--min-version=$1" + AC_MSG_CHECKING([for Google Test at least version >= $1])], + [_gtest_min_version="--min-version=0" + AC_MSG_CHECKING([for Google Test])]) + AS_IF([${GTEST_CONFIG} ${_gtest_min_version}], + [AC_MSG_RESULT([yes]) + HAVE_GTEST='yes'], + [AC_MSG_RESULT([no])])], + [AC_MSG_RESULT([no])]) + AS_IF([test "x${HAVE_GTEST}" = "xyes"], + [GTEST_CPPFLAGS=`${GTEST_CONFIG} --cppflags` + GTEST_CXXFLAGS=`${GTEST_CONFIG} --cxxflags` + GTEST_LDFLAGS=`${GTEST_CONFIG} --ldflags` + GTEST_LIBS=`${GTEST_CONFIG} --libs` + GTEST_VERSION=`${GTEST_CONFIG} --version` + AC_DEFINE([HAVE_GTEST],[1],[Defined when Google Test is available.])], + [AS_IF([test "x${enable_gtest}" = "xyes"], + [AC_MSG_ERROR([dnl +Google Test was enabled, but no viable version could be found.]) + ])])]) +AC_SUBST([HAVE_GTEST]) +AM_CONDITIONAL([HAVE_GTEST],[test "x$HAVE_GTEST" = "xyes"]) +AS_IF([test "x$HAVE_GTEST" = "xyes"], + [m4_ifval([$2], [$2])], + [m4_ifval([$3], [$3])]) +]) diff --git a/snappy/snappy-1.0.5/missing b/snappy/snappy-1.0.5/missing new file mode 100755 index 00000000..28055d2a --- /dev/null +++ b/snappy/snappy-1.0.5/missing @@ -0,0 +1,376 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2009-04-28.21; # UTC + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, +# 2008, 2009 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: +sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' +sed_minuso='s/.* -o \([^ ]*\).*/\1/p' + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case $1 in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + autom4te touch the output file, or create a stub one + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and +\`g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# normalize program name to check for. +program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). This is about non-GNU programs, so use $1 not +# $program. +case $1 in + lex*|yacc*) + # Not GNU programs, they don't have --version. + ;; + + tar*) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case $program in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case $f in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te*) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison*|yacc*) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if test $# -ne 1; then + eval LASTARG="\${$#}" + case $LASTARG in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if test ! -f y.tab.h; then + echo >y.tab.h + fi + if test ! -f y.tab.c; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex*|flex*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if test $# -ne 1; then + eval LASTARG="\${$#}" + case $LASTARG in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if test ! -f lex.yy.c; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit $? + fi + ;; + + makeinfo*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n ' + /^@setfilename/{ + s/.* \([^ ]*\) *$/\1/ + p + q + }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + tar*) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case $firstarg in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case $firstarg in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/snappy/snappy-1.0.5/snappy-c.cc b/snappy/snappy-1.0.5/snappy-c.cc new file mode 100644 index 00000000..473a0b09 --- /dev/null +++ b/snappy/snappy-1.0.5/snappy-c.cc @@ -0,0 +1,90 @@ +// Copyright 2011 Martin Gieseking . +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "snappy.h" +#include "snappy-c.h" + +extern "C" { + +snappy_status snappy_compress(const char* input, + size_t input_length, + char* compressed, + size_t *compressed_length) { + if (*compressed_length < snappy_max_compressed_length(input_length)) { + return SNAPPY_BUFFER_TOO_SMALL; + } + snappy::RawCompress(input, input_length, compressed, compressed_length); + return SNAPPY_OK; +} + +snappy_status snappy_uncompress(const char* compressed, + size_t compressed_length, + char* uncompressed, + size_t* uncompressed_length) { + size_t real_uncompressed_length; + if (!snappy::GetUncompressedLength(compressed, + compressed_length, + &real_uncompressed_length)) { + return SNAPPY_INVALID_INPUT; + } + if (*uncompressed_length < real_uncompressed_length) { + return SNAPPY_BUFFER_TOO_SMALL; + } + if (!snappy::RawUncompress(compressed, compressed_length, uncompressed)) { + return SNAPPY_INVALID_INPUT; + } + *uncompressed_length = real_uncompressed_length; + return SNAPPY_OK; +} + +size_t snappy_max_compressed_length(size_t source_length) { + return snappy::MaxCompressedLength(source_length); +} + +snappy_status snappy_uncompressed_length(const char *compressed, + size_t compressed_length, + size_t *result) { + if (snappy::GetUncompressedLength(compressed, + compressed_length, + result)) { + return SNAPPY_OK; + } else { + return SNAPPY_INVALID_INPUT; + } +} + +snappy_status snappy_validate_compressed_buffer(const char *compressed, + size_t compressed_length) { + if (snappy::IsValidCompressedBuffer(compressed, compressed_length)) { + return SNAPPY_OK; + } else { + return SNAPPY_INVALID_INPUT; + } +} + +} // extern "C" diff --git a/snappy/snappy-1.0.5/snappy-c.h b/snappy/snappy-1.0.5/snappy-c.h new file mode 100644 index 00000000..88e1122d --- /dev/null +++ b/snappy/snappy-1.0.5/snappy-c.h @@ -0,0 +1,138 @@ +/* + * Copyright 2011 Martin Gieseking . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Plain C interface (a wrapper around the C++ implementation). + */ + +#ifndef UTIL_SNAPPY_OPENSOURCE_SNAPPY_C_H_ +#define UTIL_SNAPPY_OPENSOURCE_SNAPPY_C_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + * Return values; see the documentation for each function to know + * what each can return. + */ +typedef enum { + SNAPPY_OK = 0, + SNAPPY_INVALID_INPUT = 1, + SNAPPY_BUFFER_TOO_SMALL = 2, +} snappy_status; + +/* + * Takes the data stored in "input[0..input_length-1]" and stores + * it in the array pointed to by "compressed". + * + * signals the space available in "compressed". + * If it is not at least equal to "snappy_max_compressed_length(input_length)", + * SNAPPY_BUFFER_TOO_SMALL is returned. After successful compression, + * contains the true length of the compressed output, + * and SNAPPY_OK is returned. + * + * Example: + * size_t output_length = snappy_max_compressed_length(input_length); + * char* output = (char*)malloc(output_length); + * if (snappy_compress(input, input_length, output, &output_length) + * == SNAPPY_OK) { + * ... Process(output, output_length) ... + * } + * free(output); + */ +snappy_status snappy_compress(const char* input, + size_t input_length, + char* compressed, + size_t* compressed_length); + +/* + * Given data in "compressed[0..compressed_length-1]" generated by + * calling the snappy_compress routine, this routine stores + * the uncompressed data to + * uncompressed[0..uncompressed_length-1]. + * Returns failure (a value not equal to SNAPPY_OK) if the message + * is corrupted and could not be decrypted. + * + * signals the space available in "uncompressed". + * If it is not at least equal to the value returned by + * snappy_uncompressed_length for this stream, SNAPPY_BUFFER_TOO_SMALL + * is returned. After successful decompression, + * contains the true length of the decompressed output. + * + * Example: + * size_t output_length; + * if (snappy_uncompressed_length(input, input_length, &output_length) + * != SNAPPY_OK) { + * ... fail ... + * } + * char* output = (char*)malloc(output_length); + * if (snappy_uncompress(input, input_length, output, &output_length) + * == SNAPPY_OK) { + * ... Process(output, output_length) ... + * } + * free(output); + */ +snappy_status snappy_uncompress(const char* compressed, + size_t compressed_length, + char* uncompressed, + size_t* uncompressed_length); + +/* + * Returns the maximal size of the compressed representation of + * input data that is "source_length" bytes in length. + */ +size_t snappy_max_compressed_length(size_t source_length); + +/* + * REQUIRES: "compressed[]" was produced by snappy_compress() + * Returns SNAPPY_OK and stores the length of the uncompressed data in + * *result normally. Returns SNAPPY_INVALID_INPUT on parsing error. + * This operation takes O(1) time. + */ +snappy_status snappy_uncompressed_length(const char* compressed, + size_t compressed_length, + size_t* result); + +/* + * Check if the contents of "compressed[]" can be uncompressed successfully. + * Does not return the uncompressed data; if so, returns SNAPPY_OK, + * or if not, returns SNAPPY_INVALID_INPUT. + * Takes time proportional to compressed_length, but is usually at least a + * factor of four faster than actual decompression. + */ +snappy_status snappy_validate_compressed_buffer(const char* compressed, + size_t compressed_length); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* UTIL_SNAPPY_OPENSOURCE_SNAPPY_C_H_ */ diff --git a/snappy/snappy-1.0.5/snappy-c.lo b/snappy/snappy-1.0.5/snappy-c.lo new file mode 100644 index 00000000..9798f649 --- /dev/null +++ b/snappy/snappy-1.0.5/snappy-c.lo @@ -0,0 +1,12 @@ +# snappy-c.lo - a libtool object file +# Generated by ltmain.sh (GNU libtool) 2.2.6b Debian-2.2.6b-2ubuntu1 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object='.libs/snappy-c.o' + +# Name of the non-PIC object +non_pic_object='snappy-c.o' + diff --git a/snappy/snappy-1.0.5/snappy-internal.h b/snappy/snappy-1.0.5/snappy-internal.h new file mode 100644 index 00000000..a32eda59 --- /dev/null +++ b/snappy/snappy-1.0.5/snappy-internal.h @@ -0,0 +1,150 @@ +// Copyright 2008 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Internals shared between the Snappy implementation and its unittest. + +#ifndef UTIL_SNAPPY_SNAPPY_INTERNAL_H_ +#define UTIL_SNAPPY_SNAPPY_INTERNAL_H_ + +#include "snappy-stubs-internal.h" + +namespace snappy { +namespace internal { + +class WorkingMemory { + public: + WorkingMemory() : large_table_(NULL) { } + ~WorkingMemory() { delete[] large_table_; } + + // Allocates and clears a hash table using memory in "*this", + // stores the number of buckets in "*table_size" and returns a pointer to + // the base of the hash table. + uint16* GetHashTable(size_t input_size, int* table_size); + + private: + uint16 small_table_[1<<10]; // 2KB + uint16* large_table_; // Allocated only when needed + + DISALLOW_COPY_AND_ASSIGN(WorkingMemory); +}; + +// Flat array compression that does not emit the "uncompressed length" +// prefix. Compresses "input" string to the "*op" buffer. +// +// REQUIRES: "input_length <= kBlockSize" +// REQUIRES: "op" points to an array of memory that is at least +// "MaxCompressedLength(input_length)" in size. +// REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero. +// REQUIRES: "table_size" is a power of two +// +// Returns an "end" pointer into "op" buffer. +// "end - op" is the compressed size of "input". +char* CompressFragment(const char* input, + size_t input_length, + char* op, + uint16* table, + const int table_size); + +// Return the largest n such that +// +// s1[0,n-1] == s2[0,n-1] +// and n <= (s2_limit - s2). +// +// Does not read *s2_limit or beyond. +// Does not read *(s1 + (s2_limit - s2)) or beyond. +// Requires that s2_limit >= s2. +// +// Separate implementation for x86_64, for speed. Uses the fact that +// x86_64 is little endian. +#if defined(ARCH_K8) +static inline int FindMatchLength(const char* s1, + const char* s2, + const char* s2_limit) { + DCHECK_GE(s2_limit, s2); + int matched = 0; + + // Find out how long the match is. We loop over the data 64 bits at a + // time until we find a 64-bit block that doesn't match; then we find + // the first non-matching bit and use that to calculate the total + // length of the match. + while (PREDICT_TRUE(s2 <= s2_limit - 8)) { + if (PREDICT_FALSE(UNALIGNED_LOAD64(s2) == UNALIGNED_LOAD64(s1 + matched))) { + s2 += 8; + matched += 8; + } else { + // On current (mid-2008) Opteron models there is a 3% more + // efficient code sequence to find the first non-matching byte. + // However, what follows is ~10% better on Intel Core 2 and newer, + // and we expect AMD's bsf instruction to improve. + uint64 x = UNALIGNED_LOAD64(s2) ^ UNALIGNED_LOAD64(s1 + matched); + int matching_bits = Bits::FindLSBSetNonZero64(x); + matched += matching_bits >> 3; + return matched; + } + } + while (PREDICT_TRUE(s2 < s2_limit)) { + if (PREDICT_TRUE(s1[matched] == *s2)) { + ++s2; + ++matched; + } else { + return matched; + } + } + return matched; +} +#else +static inline int FindMatchLength(const char* s1, + const char* s2, + const char* s2_limit) { + // Implementation based on the x86-64 version, above. + DCHECK_GE(s2_limit, s2); + int matched = 0; + + while (s2 <= s2_limit - 4 && + UNALIGNED_LOAD32(s2) == UNALIGNED_LOAD32(s1 + matched)) { + s2 += 4; + matched += 4; + } + if (LittleEndian::IsLittleEndian() && s2 <= s2_limit - 4) { + uint32 x = UNALIGNED_LOAD32(s2) ^ UNALIGNED_LOAD32(s1 + matched); + int matching_bits = Bits::FindLSBSetNonZero(x); + matched += matching_bits >> 3; + } else { + while ((s2 < s2_limit) && (s1[matched] == *s2)) { + ++s2; + ++matched; + } + } + return matched; +} +#endif + +} // end namespace internal +} // end namespace snappy + +#endif // UTIL_SNAPPY_SNAPPY_INTERNAL_H_ diff --git a/snappy/snappy-1.0.5/snappy-sinksource.cc b/snappy/snappy-1.0.5/snappy-sinksource.cc new file mode 100644 index 00000000..5844552c --- /dev/null +++ b/snappy/snappy-1.0.5/snappy-sinksource.cc @@ -0,0 +1,71 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include "snappy-sinksource.h" + +namespace snappy { + +Source::~Source() { } + +Sink::~Sink() { } + +char* Sink::GetAppendBuffer(size_t length, char* scratch) { + return scratch; +} + +ByteArraySource::~ByteArraySource() { } + +size_t ByteArraySource::Available() const { return left_; } + +const char* ByteArraySource::Peek(size_t* len) { + *len = left_; + return ptr_; +} + +void ByteArraySource::Skip(size_t n) { + left_ -= n; + ptr_ += n; +} + +UncheckedByteArraySink::~UncheckedByteArraySink() { } + +void UncheckedByteArraySink::Append(const char* data, size_t n) { + // Do no copying if the caller filled in the result of GetAppendBuffer() + if (data != dest_) { + memcpy(dest_, data, n); + } + dest_ += n; +} + +char* UncheckedByteArraySink::GetAppendBuffer(size_t len, char* scratch) { + return dest_; +} + +} diff --git a/snappy/snappy-1.0.5/snappy-sinksource.h b/snappy/snappy-1.0.5/snappy-sinksource.h new file mode 100644 index 00000000..faabfa1e --- /dev/null +++ b/snappy/snappy-1.0.5/snappy-sinksource.h @@ -0,0 +1,137 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef UTIL_SNAPPY_SNAPPY_SINKSOURCE_H_ +#define UTIL_SNAPPY_SNAPPY_SINKSOURCE_H_ + +#include + + +namespace snappy { + +// A Sink is an interface that consumes a sequence of bytes. +class Sink { + public: + Sink() { } + virtual ~Sink(); + + // Append "bytes[0,n-1]" to this. + virtual void Append(const char* bytes, size_t n) = 0; + + // Returns a writable buffer of the specified length for appending. + // May return a pointer to the caller-owned scratch buffer which + // must have at least the indicated length. The returned buffer is + // only valid until the next operation on this Sink. + // + // After writing at most "length" bytes, call Append() with the + // pointer returned from this function and the number of bytes + // written. Many Append() implementations will avoid copying + // bytes if this function returned an internal buffer. + // + // If a non-scratch buffer is returned, the caller may only pass a + // prefix of it to Append(). That is, it is not correct to pass an + // interior pointer of the returned array to Append(). + // + // The default implementation always returns the scratch buffer. + virtual char* GetAppendBuffer(size_t length, char* scratch); + + + private: + // No copying + Sink(const Sink&); + void operator=(const Sink&); +}; + +// A Source is an interface that yields a sequence of bytes +class Source { + public: + Source() { } + virtual ~Source(); + + // Return the number of bytes left to read from the source + virtual size_t Available() const = 0; + + // Peek at the next flat region of the source. Does not reposition + // the source. The returned region is empty iff Available()==0. + // + // Returns a pointer to the beginning of the region and store its + // length in *len. + // + // The returned region is valid until the next call to Skip() or + // until this object is destroyed, whichever occurs first. + // + // The returned region may be larger than Available() (for example + // if this ByteSource is a view on a substring of a larger source). + // The caller is responsible for ensuring that it only reads the + // Available() bytes. + virtual const char* Peek(size_t* len) = 0; + + // Skip the next n bytes. Invalidates any buffer returned by + // a previous call to Peek(). + // REQUIRES: Available() >= n + virtual void Skip(size_t n) = 0; + + private: + // No copying + Source(const Source&); + void operator=(const Source&); +}; + +// A Source implementation that yields the contents of a flat array +class ByteArraySource : public Source { + public: + ByteArraySource(const char* p, size_t n) : ptr_(p), left_(n) { } + virtual ~ByteArraySource(); + virtual size_t Available() const; + virtual const char* Peek(size_t* len); + virtual void Skip(size_t n); + private: + const char* ptr_; + size_t left_; +}; + +// A Sink implementation that writes to a flat array without any bound checks. +class UncheckedByteArraySink : public Sink { + public: + explicit UncheckedByteArraySink(char* dest) : dest_(dest) { } + virtual ~UncheckedByteArraySink(); + virtual void Append(const char* data, size_t n); + virtual char* GetAppendBuffer(size_t len, char* scratch); + + // Return the current output pointer so that a caller can see how + // many bytes were produced. + // Note: this is not a Sink method. + char* CurrentDestination() const { return dest_; } + private: + char* dest_; +}; + + +} + +#endif // UTIL_SNAPPY_SNAPPY_SINKSOURCE_H_ diff --git a/snappy/snappy-1.0.5/snappy-sinksource.lo b/snappy/snappy-1.0.5/snappy-sinksource.lo new file mode 100644 index 00000000..4bca40eb --- /dev/null +++ b/snappy/snappy-1.0.5/snappy-sinksource.lo @@ -0,0 +1,12 @@ +# snappy-sinksource.lo - a libtool object file +# Generated by ltmain.sh (GNU libtool) 2.2.6b Debian-2.2.6b-2ubuntu1 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object='.libs/snappy-sinksource.o' + +# Name of the non-PIC object +non_pic_object='snappy-sinksource.o' + diff --git a/snappy/snappy-1.0.5/snappy-stubs-internal.cc b/snappy/snappy-1.0.5/snappy-stubs-internal.cc new file mode 100644 index 00000000..6ed33437 --- /dev/null +++ b/snappy/snappy-1.0.5/snappy-stubs-internal.cc @@ -0,0 +1,42 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include + +#include "snappy-stubs-internal.h" + +namespace snappy { + +void Varint::Append32(string* s, uint32 value) { + char buf[Varint::kMax32]; + const char* p = Varint::Encode32(buf, value); + s->append(buf, p - buf); +} + +} // namespace snappy diff --git a/snappy/snappy-1.0.5/snappy-stubs-internal.h b/snappy/snappy-1.0.5/snappy-stubs-internal.h new file mode 100644 index 00000000..6033cdfb --- /dev/null +++ b/snappy/snappy-1.0.5/snappy-stubs-internal.h @@ -0,0 +1,571 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Various stubs for the open-source version of Snappy. + +#ifndef UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_ +#define UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include +#include +#include + +#ifdef HAVE_SYS_MMAN_H +#include +#endif + +#include "snappy-stubs-public.h" + +#if defined(__x86_64__) + +// Enable 64-bit optimized versions of some routines. +#define ARCH_K8 1 + +#endif + +// Needed by OS X, among others. +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + +// Pull in std::min, std::ostream, and the likes. This is safe because this +// header file is never used from any public header files. +using namespace std; + +// The size of an array, if known at compile-time. +// Will give unexpected results if used on a pointer. +// We undefine it first, since some compilers already have a definition. +#ifdef ARRAYSIZE +#undef ARRAYSIZE +#endif +#define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a))) + +// Static prediction hints. +#ifdef HAVE_BUILTIN_EXPECT +#define PREDICT_FALSE(x) (__builtin_expect(x, 0)) +#define PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) +#else +#define PREDICT_FALSE(x) x +#define PREDICT_TRUE(x) x +#endif + +// This is only used for recomputing the tag byte table used during +// decompression; for simplicity we just remove it from the open-source +// version (anyone who wants to regenerate it can just do the call +// themselves within main()). +#define DEFINE_bool(flag_name, default_value, description) \ + bool FLAGS_ ## flag_name = default_value +#define DECLARE_bool(flag_name) \ + extern bool FLAGS_ ## flag_name + +namespace snappy { + +static const uint32 kuint32max = static_cast(0xFFFFFFFF); +static const int64 kint64max = static_cast(0x7FFFFFFFFFFFFFFFLL); + +// Logging. + +#define LOG(level) LogMessage() +#define VLOG(level) true ? (void)0 : \ + snappy::LogMessageVoidify() & snappy::LogMessage() + +class LogMessage { + public: + LogMessage() { } + ~LogMessage() { + cerr << endl; + } + + LogMessage& operator<<(const std::string& msg) { + cerr << msg; + return *this; + } + LogMessage& operator<<(int x) { + cerr << x; + return *this; + } +}; + +// Asserts, both versions activated in debug mode only, +// and ones that are always active. + +#define CRASH_UNLESS(condition) \ + PREDICT_TRUE(condition) ? (void)0 : \ + snappy::LogMessageVoidify() & snappy::LogMessageCrash() + +class LogMessageCrash : public LogMessage { + public: + LogMessageCrash() { } + ~LogMessageCrash() { + cerr << endl; + abort(); + } +}; + +// This class is used to explicitly ignore values in the conditional +// logging macros. This avoids compiler warnings like "value computed +// is not used" and "statement has no effect". + +class LogMessageVoidify { + public: + LogMessageVoidify() { } + // This has to be an operator with a precedence lower than << but + // higher than ?: + void operator&(const LogMessage&) { } +}; + +#define CHECK(cond) CRASH_UNLESS(cond) +#define CHECK_LE(a, b) CRASH_UNLESS((a) <= (b)) +#define CHECK_GE(a, b) CRASH_UNLESS((a) >= (b)) +#define CHECK_EQ(a, b) CRASH_UNLESS((a) == (b)) +#define CHECK_NE(a, b) CRASH_UNLESS((a) != (b)) +#define CHECK_LT(a, b) CRASH_UNLESS((a) < (b)) +#define CHECK_GT(a, b) CRASH_UNLESS((a) > (b)) + +#ifdef NDEBUG + +#define DCHECK(cond) CRASH_UNLESS(true) +#define DCHECK_LE(a, b) CRASH_UNLESS(true) +#define DCHECK_GE(a, b) CRASH_UNLESS(true) +#define DCHECK_EQ(a, b) CRASH_UNLESS(true) +#define DCHECK_NE(a, b) CRASH_UNLESS(true) +#define DCHECK_LT(a, b) CRASH_UNLESS(true) +#define DCHECK_GT(a, b) CRASH_UNLESS(true) + +#else + +#define DCHECK(cond) CHECK(cond) +#define DCHECK_LE(a, b) CHECK_LE(a, b) +#define DCHECK_GE(a, b) CHECK_GE(a, b) +#define DCHECK_EQ(a, b) CHECK_EQ(a, b) +#define DCHECK_NE(a, b) CHECK_NE(a, b) +#define DCHECK_LT(a, b) CHECK_LT(a, b) +#define DCHECK_GT(a, b) CHECK_GT(a, b) + +#endif + +// Potentially unaligned loads and stores. + +// x86 and PowerPC can simply do these loads and stores native. + +#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) + +#define UNALIGNED_LOAD16(_p) (*reinterpret_cast(_p)) +#define UNALIGNED_LOAD32(_p) (*reinterpret_cast(_p)) +#define UNALIGNED_LOAD64(_p) (*reinterpret_cast(_p)) + +#define UNALIGNED_STORE16(_p, _val) (*reinterpret_cast(_p) = (_val)) +#define UNALIGNED_STORE32(_p, _val) (*reinterpret_cast(_p) = (_val)) +#define UNALIGNED_STORE64(_p, _val) (*reinterpret_cast(_p) = (_val)) + +// ARMv7 and newer support native unaligned accesses, but only of 16-bit +// and 32-bit values (not 64-bit); older versions either raise a fatal signal, +// do an unaligned read and rotate the words around a bit, or do the reads very +// slowly (trip through kernel mode). There's no simple #define that says just +// “ARMv7 or higher”, so we have to filter away all ARMv5 and ARMv6 +// sub-architectures. +// +// This is a mess, but there's not much we can do about it. + +#elif defined(__arm__) && \ + !defined(__ARM_ARCH_5__) && \ + !defined(__ARM_ARCH_5T__) && \ + !defined(__ARM_ARCH_5TE__) && \ + !defined(__ARM_ARCH_5TEJ__) && \ + !defined(__ARM_ARCH_6__) && \ + !defined(__ARM_ARCH_6J__) && \ + !defined(__ARM_ARCH_6K__) && \ + !defined(__ARM_ARCH_6Z__) && \ + !defined(__ARM_ARCH_6ZK__) && \ + !defined(__ARM_ARCH_6T2__) + +#define UNALIGNED_LOAD16(_p) (*reinterpret_cast(_p)) +#define UNALIGNED_LOAD32(_p) (*reinterpret_cast(_p)) + +#define UNALIGNED_STORE16(_p, _val) (*reinterpret_cast(_p) = (_val)) +#define UNALIGNED_STORE32(_p, _val) (*reinterpret_cast(_p) = (_val)) + +// TODO(user): NEON supports unaligned 64-bit loads and stores. +// See if that would be more efficient on platforms supporting it, +// at least for copies. + +inline uint64 UNALIGNED_LOAD64(const void *p) { + uint64 t; + memcpy(&t, p, sizeof t); + return t; +} + +inline void UNALIGNED_STORE64(void *p, uint64 v) { + memcpy(p, &v, sizeof v); +} + +#else + +// These functions are provided for architectures that don't support +// unaligned loads and stores. + +inline uint16 UNALIGNED_LOAD16(const void *p) { + uint16 t; + memcpy(&t, p, sizeof t); + return t; +} + +inline uint32 UNALIGNED_LOAD32(const void *p) { + uint32 t; + memcpy(&t, p, sizeof t); + return t; +} + +inline uint64 UNALIGNED_LOAD64(const void *p) { + uint64 t; + memcpy(&t, p, sizeof t); + return t; +} + +inline void UNALIGNED_STORE16(void *p, uint16 v) { + memcpy(p, &v, sizeof v); +} + +inline void UNALIGNED_STORE32(void *p, uint32 v) { + memcpy(p, &v, sizeof v); +} + +inline void UNALIGNED_STORE64(void *p, uint64 v) { + memcpy(p, &v, sizeof v); +} + +#endif + +// This can be more efficient than UNALIGNED_LOAD64 + UNALIGNED_STORE64 +// on some platforms, in particular ARM. +inline void UnalignedCopy64(const void *src, void *dst) { + if (sizeof(void *) == 8) { + UNALIGNED_STORE64(dst, UNALIGNED_LOAD64(src)); + } else { + const char *src_char = reinterpret_cast(src); + char *dst_char = reinterpret_cast(dst); + + UNALIGNED_STORE32(dst_char, UNALIGNED_LOAD32(src_char)); + UNALIGNED_STORE32(dst_char + 4, UNALIGNED_LOAD32(src_char + 4)); + } +} + +// The following guarantees declaration of the byte swap functions. +#ifdef WORDS_BIGENDIAN + +#ifdef HAVE_SYS_BYTEORDER_H +#include +#endif + +#ifdef HAVE_SYS_ENDIAN_H +#include +#endif + +#ifdef _MSC_VER +#include +#define bswap_16(x) _byteswap_ushort(x) +#define bswap_32(x) _byteswap_ulong(x) +#define bswap_64(x) _byteswap_uint64(x) + +#elif defined(__APPLE__) +// Mac OS X / Darwin features +#include +#define bswap_16(x) OSSwapInt16(x) +#define bswap_32(x) OSSwapInt32(x) +#define bswap_64(x) OSSwapInt64(x) + +#elif defined(HAVE_BYTESWAP_H) +#include + +#elif defined(bswap32) +// FreeBSD defines bswap{16,32,64} in (already #included). +#define bswap_16(x) bswap16(x) +#define bswap_32(x) bswap32(x) +#define bswap_64(x) bswap64(x) + +#elif defined(BSWAP_64) +// Solaris 10 defines BSWAP_{16,32,64} in (already #included). +#define bswap_16(x) BSWAP_16(x) +#define bswap_32(x) BSWAP_32(x) +#define bswap_64(x) BSWAP_64(x) + +#else + +inline uint16 bswap_16(uint16 x) { + return (x << 8) | (x >> 8); +} + +inline uint32 bswap_32(uint32 x) { + x = ((x & 0xff00ff00UL) >> 8) | ((x & 0x00ff00ffUL) << 8); + return (x >> 16) | (x << 16); +} + +inline uint64 bswap_64(uint64 x) { + x = ((x & 0xff00ff00ff00ff00ULL) >> 8) | ((x & 0x00ff00ff00ff00ffULL) << 8); + x = ((x & 0xffff0000ffff0000ULL) >> 16) | ((x & 0x0000ffff0000ffffULL) << 16); + return (x >> 32) | (x << 32); +} + +#endif + +#endif // WORDS_BIGENDIAN + +// Convert to little-endian storage, opposite of network format. +// Convert x from host to little endian: x = LittleEndian.FromHost(x); +// convert x from little endian to host: x = LittleEndian.ToHost(x); +// +// Store values into unaligned memory converting to little endian order: +// LittleEndian.Store16(p, x); +// +// Load unaligned values stored in little endian converting to host order: +// x = LittleEndian.Load16(p); +class LittleEndian { + public: + // Conversion functions. +#ifdef WORDS_BIGENDIAN + + static uint16 FromHost16(uint16 x) { return bswap_16(x); } + static uint16 ToHost16(uint16 x) { return bswap_16(x); } + + static uint32 FromHost32(uint32 x) { return bswap_32(x); } + static uint32 ToHost32(uint32 x) { return bswap_32(x); } + + static bool IsLittleEndian() { return false; } + +#else // !defined(WORDS_BIGENDIAN) + + static uint16 FromHost16(uint16 x) { return x; } + static uint16 ToHost16(uint16 x) { return x; } + + static uint32 FromHost32(uint32 x) { return x; } + static uint32 ToHost32(uint32 x) { return x; } + + static bool IsLittleEndian() { return true; } + +#endif // !defined(WORDS_BIGENDIAN) + + // Functions to do unaligned loads and stores in little-endian order. + static uint16 Load16(const void *p) { + return ToHost16(UNALIGNED_LOAD16(p)); + } + + static void Store16(void *p, uint16 v) { + UNALIGNED_STORE16(p, FromHost16(v)); + } + + static uint32 Load32(const void *p) { + return ToHost32(UNALIGNED_LOAD32(p)); + } + + static void Store32(void *p, uint32 v) { + UNALIGNED_STORE32(p, FromHost32(v)); + } +}; + +// Some bit-manipulation functions. +class Bits { + public: + // Return floor(log2(n)) for positive integer n. Returns -1 iff n == 0. + static int Log2Floor(uint32 n); + + // Return the first set least / most significant bit, 0-indexed. Returns an + // undefined value if n == 0. FindLSBSetNonZero() is similar to ffs() except + // that it's 0-indexed. + static int FindLSBSetNonZero(uint32 n); + static int FindLSBSetNonZero64(uint64 n); + + private: + DISALLOW_COPY_AND_ASSIGN(Bits); +}; + +#ifdef HAVE_BUILTIN_CTZ + +inline int Bits::Log2Floor(uint32 n) { + return n == 0 ? -1 : 31 ^ __builtin_clz(n); +} + +inline int Bits::FindLSBSetNonZero(uint32 n) { + return __builtin_ctz(n); +} + +inline int Bits::FindLSBSetNonZero64(uint64 n) { + return __builtin_ctzll(n); +} + +#else // Portable versions. + +inline int Bits::Log2Floor(uint32 n) { + if (n == 0) + return -1; + int log = 0; + uint32 value = n; + for (int i = 4; i >= 0; --i) { + int shift = (1 << i); + uint32 x = value >> shift; + if (x != 0) { + value = x; + log += shift; + } + } + assert(value == 1); + return log; +} + +inline int Bits::FindLSBSetNonZero(uint32 n) { + int rc = 31; + for (int i = 4, shift = 1 << 4; i >= 0; --i) { + const uint32 x = n << shift; + if (x != 0) { + n = x; + rc -= shift; + } + shift >>= 1; + } + return rc; +} + +// FindLSBSetNonZero64() is defined in terms of FindLSBSetNonZero(). +inline int Bits::FindLSBSetNonZero64(uint64 n) { + const uint32 bottombits = static_cast(n); + if (bottombits == 0) { + // Bottom bits are zero, so scan in top bits + return 32 + FindLSBSetNonZero(static_cast(n >> 32)); + } else { + return FindLSBSetNonZero(bottombits); + } +} + +#endif // End portable versions. + +// Variable-length integer encoding. +class Varint { + public: + // Maximum lengths of varint encoding of uint32. + static const int kMax32 = 5; + + // Attempts to parse a varint32 from a prefix of the bytes in [ptr,limit-1]. + // Never reads a character at or beyond limit. If a valid/terminated varint32 + // was found in the range, stores it in *OUTPUT and returns a pointer just + // past the last byte of the varint32. Else returns NULL. On success, + // "result <= limit". + static const char* Parse32WithLimit(const char* ptr, const char* limit, + uint32* OUTPUT); + + // REQUIRES "ptr" points to a buffer of length sufficient to hold "v". + // EFFECTS Encodes "v" into "ptr" and returns a pointer to the + // byte just past the last encoded byte. + static char* Encode32(char* ptr, uint32 v); + + // EFFECTS Appends the varint representation of "value" to "*s". + static void Append32(string* s, uint32 value); +}; + +inline const char* Varint::Parse32WithLimit(const char* p, + const char* l, + uint32* OUTPUT) { + const unsigned char* ptr = reinterpret_cast(p); + const unsigned char* limit = reinterpret_cast(l); + uint32 b, result; + if (ptr >= limit) return NULL; + b = *(ptr++); result = b & 127; if (b < 128) goto done; + if (ptr >= limit) return NULL; + b = *(ptr++); result |= (b & 127) << 7; if (b < 128) goto done; + if (ptr >= limit) return NULL; + b = *(ptr++); result |= (b & 127) << 14; if (b < 128) goto done; + if (ptr >= limit) return NULL; + b = *(ptr++); result |= (b & 127) << 21; if (b < 128) goto done; + if (ptr >= limit) return NULL; + b = *(ptr++); result |= (b & 127) << 28; if (b < 16) goto done; + return NULL; // Value is too long to be a varint32 + done: + *OUTPUT = result; + return reinterpret_cast(ptr); +} + +inline char* Varint::Encode32(char* sptr, uint32 v) { + // Operate on characters as unsigneds + unsigned char* ptr = reinterpret_cast(sptr); + static const int B = 128; + if (v < (1<<7)) { + *(ptr++) = v; + } else if (v < (1<<14)) { + *(ptr++) = v | B; + *(ptr++) = v>>7; + } else if (v < (1<<21)) { + *(ptr++) = v | B; + *(ptr++) = (v>>7) | B; + *(ptr++) = v>>14; + } else if (v < (1<<28)) { + *(ptr++) = v | B; + *(ptr++) = (v>>7) | B; + *(ptr++) = (v>>14) | B; + *(ptr++) = v>>21; + } else { + *(ptr++) = v | B; + *(ptr++) = (v>>7) | B; + *(ptr++) = (v>>14) | B; + *(ptr++) = (v>>21) | B; + *(ptr++) = v>>28; + } + return reinterpret_cast(ptr); +} + +// If you know the internal layout of the std::string in use, you can +// replace this function with one that resizes the string without +// filling the new space with zeros (if applicable) -- +// it will be non-portable but faster. +inline void STLStringResizeUninitialized(string* s, size_t new_size) { + s->resize(new_size); +} + +// Return a mutable char* pointing to a string's internal buffer, +// which may not be null-terminated. Writing through this pointer will +// modify the string. +// +// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the +// next call to a string method that invalidates iterators. +// +// As of 2006-04, there is no standard-blessed way of getting a +// mutable reference to a string's internal buffer. However, issue 530 +// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-defects.html#530) +// proposes this as the method. It will officially be part of the standard +// for C++0x. This should already work on all current implementations. +inline char* string_as_array(string* str) { + return str->empty() ? NULL : &*str->begin(); +} + +} // namespace snappy + +#endif // UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_ diff --git a/snappy/snappy-1.0.5/snappy-stubs-internal.lo b/snappy/snappy-1.0.5/snappy-stubs-internal.lo new file mode 100644 index 00000000..52572c4c --- /dev/null +++ b/snappy/snappy-1.0.5/snappy-stubs-internal.lo @@ -0,0 +1,12 @@ +# snappy-stubs-internal.lo - a libtool object file +# Generated by ltmain.sh (GNU libtool) 2.2.6b Debian-2.2.6b-2ubuntu1 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object='.libs/snappy-stubs-internal.o' + +# Name of the non-PIC object +non_pic_object='snappy-stubs-internal.o' + diff --git a/snappy/snappy-1.0.5/snappy-stubs-public.h b/snappy/snappy-1.0.5/snappy-stubs-public.h new file mode 100644 index 00000000..9ee4ca52 --- /dev/null +++ b/snappy/snappy-1.0.5/snappy-stubs-public.h @@ -0,0 +1,85 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// Author: sesse@google.com (Steinar H. Gunderson) +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Various type stubs for the open-source version of Snappy. +// +// This file cannot include config.h, as it is included from snappy.h, +// which is a public header. Instead, snappy-stubs-public.h is generated by +// from snappy-stubs-public.h.in at configure time. + +#ifndef UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_ +#define UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_ + +#if 1 +#include +#endif + +#if 1 +#include +#endif + +#define SNAPPY_MAJOR 1 +#define SNAPPY_MINOR 0 +#define SNAPPY_PATCHLEVEL 5 +#define SNAPPY_VERSION \ + ((SNAPPY_MAJOR << 16) | (SNAPPY_MINOR << 8) | SNAPPY_PATCHLEVEL) + +#include + +namespace snappy { + +#if 1 +typedef int8_t int8; +typedef uint8_t uint8; +typedef int16_t int16; +typedef uint16_t uint16; +typedef int32_t int32; +typedef uint32_t uint32; +typedef int64_t int64; +typedef uint64_t uint64; +#else +typedef signed char int8; +typedef unsigned char uint8; +typedef short int16; +typedef unsigned short uint16; +typedef int int32; +typedef unsigned int uint32; +typedef long long int64; +typedef unsigned long long uint64; +#endif + +typedef std::string string; + +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +} // namespace snappy + +#endif // UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_ diff --git a/snappy/snappy-1.0.5/snappy-stubs-public.h.in b/snappy/snappy-1.0.5/snappy-stubs-public.h.in new file mode 100644 index 00000000..f0babcbe --- /dev/null +++ b/snappy/snappy-1.0.5/snappy-stubs-public.h.in @@ -0,0 +1,85 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// Author: sesse@google.com (Steinar H. Gunderson) +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Various type stubs for the open-source version of Snappy. +// +// This file cannot include config.h, as it is included from snappy.h, +// which is a public header. Instead, snappy-stubs-public.h is generated by +// from snappy-stubs-public.h.in at configure time. + +#ifndef UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_ +#define UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_ + +#if @ac_cv_have_stdint_h@ +#include +#endif + +#if @ac_cv_have_stddef_h@ +#include +#endif + +#define SNAPPY_MAJOR @SNAPPY_MAJOR@ +#define SNAPPY_MINOR @SNAPPY_MINOR@ +#define SNAPPY_PATCHLEVEL @SNAPPY_PATCHLEVEL@ +#define SNAPPY_VERSION \ + ((SNAPPY_MAJOR << 16) | (SNAPPY_MINOR << 8) | SNAPPY_PATCHLEVEL) + +#include + +namespace snappy { + +#if @ac_cv_have_stdint_h@ +typedef int8_t int8; +typedef uint8_t uint8; +typedef int16_t int16; +typedef uint16_t uint16; +typedef int32_t int32; +typedef uint32_t uint32; +typedef int64_t int64; +typedef uint64_t uint64; +#else +typedef signed char int8; +typedef unsigned char uint8; +typedef short int16; +typedef unsigned short uint16; +typedef int int32; +typedef unsigned int uint32; +typedef long long int64; +typedef unsigned long long uint64; +#endif + +typedef std::string string; + +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +} // namespace snappy + +#endif // UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_ diff --git a/snappy/snappy-1.0.5/snappy-test.cc b/snappy/snappy-1.0.5/snappy-test.cc new file mode 100644 index 00000000..223cd92d --- /dev/null +++ b/snappy/snappy-1.0.5/snappy-test.cc @@ -0,0 +1,594 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Various stubs for the unit tests for the open-source version of Snappy. + +#include "snappy-test.h" + +#ifdef HAVE_WINDOWS_H +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#include + +DEFINE_bool(run_microbenchmarks, true, + "Run microbenchmarks before doing anything else."); + +namespace snappy { + +string ReadTestDataFile(const string& base) { + string contents; + const char* srcdir = getenv("srcdir"); // This is set by Automake. + if (srcdir) { + File::ReadFileToStringOrDie( + string(srcdir) + "/testdata/" + base, &contents); + } else { + File::ReadFileToStringOrDie("testdata/" + base, &contents); + } + return contents; +} + +string StringPrintf(const char* format, ...) { + char buf[4096]; + va_list ap; + va_start(ap, format); + vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + return buf; +} + +bool benchmark_running = false; +int64 benchmark_real_time_us = 0; +int64 benchmark_cpu_time_us = 0; +string *benchmark_label = NULL; +int64 benchmark_bytes_processed = 0; + +void ResetBenchmarkTiming() { + benchmark_real_time_us = 0; + benchmark_cpu_time_us = 0; +} + +#ifdef WIN32 +LARGE_INTEGER benchmark_start_real; +FILETIME benchmark_start_cpu; +#else // WIN32 +struct timeval benchmark_start_real; +struct rusage benchmark_start_cpu; +#endif // WIN32 + +void StartBenchmarkTiming() { +#ifdef WIN32 + QueryPerformanceCounter(&benchmark_start_real); + FILETIME dummy; + CHECK(GetProcessTimes( + GetCurrentProcess(), &dummy, &dummy, &dummy, &benchmark_start_cpu)); +#else + gettimeofday(&benchmark_start_real, NULL); + if (getrusage(RUSAGE_SELF, &benchmark_start_cpu) == -1) { + perror("getrusage(RUSAGE_SELF)"); + exit(1); + } +#endif + benchmark_running = true; +} + +void StopBenchmarkTiming() { + if (!benchmark_running) { + return; + } + +#ifdef WIN32 + LARGE_INTEGER benchmark_stop_real; + LARGE_INTEGER benchmark_frequency; + QueryPerformanceCounter(&benchmark_stop_real); + QueryPerformanceFrequency(&benchmark_frequency); + + double elapsed_real = static_cast( + benchmark_stop_real.QuadPart - benchmark_start_real.QuadPart) / + benchmark_frequency.QuadPart; + benchmark_real_time_us += elapsed_real * 1e6 + 0.5; + + FILETIME benchmark_stop_cpu, dummy; + CHECK(GetProcessTimes( + GetCurrentProcess(), &dummy, &dummy, &dummy, &benchmark_stop_cpu)); + + ULARGE_INTEGER start_ulargeint; + start_ulargeint.LowPart = benchmark_start_cpu.dwLowDateTime; + start_ulargeint.HighPart = benchmark_start_cpu.dwHighDateTime; + + ULARGE_INTEGER stop_ulargeint; + stop_ulargeint.LowPart = benchmark_stop_cpu.dwLowDateTime; + stop_ulargeint.HighPart = benchmark_stop_cpu.dwHighDateTime; + + benchmark_cpu_time_us += + (stop_ulargeint.QuadPart - start_ulargeint.QuadPart + 5) / 10; +#else // WIN32 + struct timeval benchmark_stop_real; + gettimeofday(&benchmark_stop_real, NULL); + benchmark_real_time_us += + 1000000 * (benchmark_stop_real.tv_sec - benchmark_start_real.tv_sec); + benchmark_real_time_us += + (benchmark_stop_real.tv_usec - benchmark_start_real.tv_usec); + + struct rusage benchmark_stop_cpu; + if (getrusage(RUSAGE_SELF, &benchmark_stop_cpu) == -1) { + perror("getrusage(RUSAGE_SELF)"); + exit(1); + } + benchmark_cpu_time_us += 1000000 * (benchmark_stop_cpu.ru_utime.tv_sec - + benchmark_start_cpu.ru_utime.tv_sec); + benchmark_cpu_time_us += (benchmark_stop_cpu.ru_utime.tv_usec - + benchmark_start_cpu.ru_utime.tv_usec); +#endif // WIN32 + + benchmark_running = false; +} + +void SetBenchmarkLabel(const string& str) { + if (benchmark_label) { + delete benchmark_label; + } + benchmark_label = new string(str); +} + +void SetBenchmarkBytesProcessed(int64 bytes) { + benchmark_bytes_processed = bytes; +} + +struct BenchmarkRun { + int64 real_time_us; + int64 cpu_time_us; +}; + +struct BenchmarkCompareCPUTime { + bool operator() (const BenchmarkRun& a, const BenchmarkRun& b) const { + return a.cpu_time_us < b.cpu_time_us; + } +}; + +void Benchmark::Run() { + for (int test_case_num = start_; test_case_num <= stop_; ++test_case_num) { + // Run a few iterations first to find out approximately how fast + // the benchmark is. + const int kCalibrateIterations = 100; + ResetBenchmarkTiming(); + StartBenchmarkTiming(); + (*function_)(kCalibrateIterations, test_case_num); + StopBenchmarkTiming(); + + // Let each test case run for about 200ms, but at least as many + // as we used to calibrate. + // Run five times and pick the median. + const int kNumRuns = 5; + const int kMedianPos = kNumRuns / 2; + int num_iterations = 0; + if (benchmark_real_time_us > 0) { + num_iterations = 200000 * kCalibrateIterations / benchmark_real_time_us; + } + num_iterations = max(num_iterations, kCalibrateIterations); + BenchmarkRun benchmark_runs[kNumRuns]; + + for (int run = 0; run < kNumRuns; ++run) { + ResetBenchmarkTiming(); + StartBenchmarkTiming(); + (*function_)(num_iterations, test_case_num); + StopBenchmarkTiming(); + + benchmark_runs[run].real_time_us = benchmark_real_time_us; + benchmark_runs[run].cpu_time_us = benchmark_cpu_time_us; + } + + nth_element(benchmark_runs, + benchmark_runs + kMedianPos, + benchmark_runs + kNumRuns, + BenchmarkCompareCPUTime()); + int64 real_time_us = benchmark_runs[kMedianPos].real_time_us; + int64 cpu_time_us = benchmark_runs[kMedianPos].cpu_time_us; + int64 bytes_per_second = benchmark_bytes_processed * 1000000 / cpu_time_us; + + string heading = StringPrintf("%s/%d", name_.c_str(), test_case_num); + string human_readable_speed; + if (bytes_per_second < 1024) { + human_readable_speed = StringPrintf("%dB/s", bytes_per_second); + } else if (bytes_per_second < 1024 * 1024) { + human_readable_speed = StringPrintf( + "%.1fkB/s", bytes_per_second / 1024.0f); + } else if (bytes_per_second < 1024 * 1024 * 1024) { + human_readable_speed = StringPrintf( + "%.1fMB/s", bytes_per_second / (1024.0f * 1024.0f)); + } else { + human_readable_speed = StringPrintf( + "%.1fGB/s", bytes_per_second / (1024.0f * 1024.0f * 1024.0f)); + } + + fprintf(stderr, +#ifdef WIN32 + "%-18s %10I64d %10I64d %10d %s %s\n", +#else + "%-18s %10lld %10lld %10d %s %s\n", +#endif + heading.c_str(), + static_cast(real_time_us * 1000 / num_iterations), + static_cast(cpu_time_us * 1000 / num_iterations), + num_iterations, + human_readable_speed.c_str(), + benchmark_label->c_str()); + } +} + +#ifdef HAVE_LIBZ + +ZLib::ZLib() + : comp_init_(false), + uncomp_init_(false) { + Reinit(); +} + +ZLib::~ZLib() { + if (comp_init_) { deflateEnd(&comp_stream_); } + if (uncomp_init_) { inflateEnd(&uncomp_stream_); } +} + +void ZLib::Reinit() { + compression_level_ = Z_DEFAULT_COMPRESSION; + window_bits_ = MAX_WBITS; + mem_level_ = 8; // DEF_MEM_LEVEL + if (comp_init_) { + deflateEnd(&comp_stream_); + comp_init_ = false; + } + if (uncomp_init_) { + inflateEnd(&uncomp_stream_); + uncomp_init_ = false; + } + first_chunk_ = true; +} + +void ZLib::Reset() { + first_chunk_ = true; +} + +// --------- COMPRESS MODE + +// Initialization method to be called if we hit an error while +// compressing. On hitting an error, call this method before returning +// the error. +void ZLib::CompressErrorInit() { + deflateEnd(&comp_stream_); + comp_init_ = false; + Reset(); +} + +int ZLib::DeflateInit() { + return deflateInit2(&comp_stream_, + compression_level_, + Z_DEFLATED, + window_bits_, + mem_level_, + Z_DEFAULT_STRATEGY); +} + +int ZLib::CompressInit(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen) { + int err; + + comp_stream_.next_in = (Bytef*)source; + comp_stream_.avail_in = (uInt)*sourceLen; + if ((uLong)comp_stream_.avail_in != *sourceLen) return Z_BUF_ERROR; + comp_stream_.next_out = dest; + comp_stream_.avail_out = (uInt)*destLen; + if ((uLong)comp_stream_.avail_out != *destLen) return Z_BUF_ERROR; + + if ( !first_chunk_ ) // only need to set up stream the first time through + return Z_OK; + + if (comp_init_) { // we've already initted it + err = deflateReset(&comp_stream_); + if (err != Z_OK) { + LOG(WARNING) << "ERROR: Can't reset compress object; creating a new one"; + deflateEnd(&comp_stream_); + comp_init_ = false; + } + } + if (!comp_init_) { // first use + comp_stream_.zalloc = (alloc_func)0; + comp_stream_.zfree = (free_func)0; + comp_stream_.opaque = (voidpf)0; + err = DeflateInit(); + if (err != Z_OK) return err; + comp_init_ = true; + } + return Z_OK; +} + +// In a perfect world we'd always have the full buffer to compress +// when the time came, and we could just call Compress(). Alas, we +// want to do chunked compression on our webserver. In this +// application, we compress the header, send it off, then compress the +// results, send them off, then compress the footer. Thus we need to +// use the chunked compression features of zlib. +int ZLib::CompressAtMostOrAll(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen, + int flush_mode) { // Z_FULL_FLUSH or Z_FINISH + int err; + + if ( (err=CompressInit(dest, destLen, source, sourceLen)) != Z_OK ) + return err; + + // This is used to figure out how many bytes we wrote *this chunk* + int compressed_size = comp_stream_.total_out; + + // Some setup happens only for the first chunk we compress in a run + if ( first_chunk_ ) { + first_chunk_ = false; + } + + // flush_mode is Z_FINISH for all mode, Z_SYNC_FLUSH for incremental + // compression. + err = deflate(&comp_stream_, flush_mode); + + *sourceLen = comp_stream_.avail_in; + + if ((err == Z_STREAM_END || err == Z_OK) + && comp_stream_.avail_in == 0 + && comp_stream_.avail_out != 0 ) { + // we processed everything ok and the output buffer was large enough. + ; + } else if (err == Z_STREAM_END && comp_stream_.avail_in > 0) { + return Z_BUF_ERROR; // should never happen + } else if (err != Z_OK && err != Z_STREAM_END && err != Z_BUF_ERROR) { + // an error happened + CompressErrorInit(); + return err; + } else if (comp_stream_.avail_out == 0) { // not enough space + err = Z_BUF_ERROR; + } + + assert(err == Z_OK || err == Z_STREAM_END || err == Z_BUF_ERROR); + if (err == Z_STREAM_END) + err = Z_OK; + + // update the crc and other metadata + compressed_size = comp_stream_.total_out - compressed_size; // delta + *destLen = compressed_size; + + return err; +} + +int ZLib::CompressChunkOrAll(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int flush_mode) { // Z_FULL_FLUSH or Z_FINISH + const int ret = + CompressAtMostOrAll(dest, destLen, source, &sourceLen, flush_mode); + if (ret == Z_BUF_ERROR) + CompressErrorInit(); + return ret; +} + +// This routine only initializes the compression stream once. Thereafter, it +// just does a deflateReset on the stream, which should be faster. +int ZLib::Compress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen) { + int err; + if ( (err=CompressChunkOrAll(dest, destLen, source, sourceLen, + Z_FINISH)) != Z_OK ) + return err; + Reset(); // reset for next call to Compress + + return Z_OK; +} + + +// --------- UNCOMPRESS MODE + +int ZLib::InflateInit() { + return inflateInit2(&uncomp_stream_, MAX_WBITS); +} + +// Initialization method to be called if we hit an error while +// uncompressing. On hitting an error, call this method before +// returning the error. +void ZLib::UncompressErrorInit() { + inflateEnd(&uncomp_stream_); + uncomp_init_ = false; + Reset(); +} + +int ZLib::UncompressInit(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen) { + int err; + + uncomp_stream_.next_in = (Bytef*)source; + uncomp_stream_.avail_in = (uInt)*sourceLen; + // Check for source > 64K on 16-bit machine: + if ((uLong)uncomp_stream_.avail_in != *sourceLen) return Z_BUF_ERROR; + + uncomp_stream_.next_out = dest; + uncomp_stream_.avail_out = (uInt)*destLen; + if ((uLong)uncomp_stream_.avail_out != *destLen) return Z_BUF_ERROR; + + if ( !first_chunk_ ) // only need to set up stream the first time through + return Z_OK; + + if (uncomp_init_) { // we've already initted it + err = inflateReset(&uncomp_stream_); + if (err != Z_OK) { + LOG(WARNING) + << "ERROR: Can't reset uncompress object; creating a new one"; + UncompressErrorInit(); + } + } + if (!uncomp_init_) { + uncomp_stream_.zalloc = (alloc_func)0; + uncomp_stream_.zfree = (free_func)0; + uncomp_stream_.opaque = (voidpf)0; + err = InflateInit(); + if (err != Z_OK) return err; + uncomp_init_ = true; + } + return Z_OK; +} + +// If you compressed your data a chunk at a time, with CompressChunk, +// you can uncompress it a chunk at a time with UncompressChunk. +// Only difference bewteen chunked and unchunked uncompression +// is the flush mode we use: Z_SYNC_FLUSH (chunked) or Z_FINISH (unchunked). +int ZLib::UncompressAtMostOrAll(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen, + int flush_mode) { // Z_SYNC_FLUSH or Z_FINISH + int err = Z_OK; + + if ( (err=UncompressInit(dest, destLen, source, sourceLen)) != Z_OK ) { + LOG(WARNING) << "UncompressInit: Error: " << err << " SourceLen: " + << *sourceLen; + return err; + } + + // This is used to figure out how many output bytes we wrote *this chunk*: + const uLong old_total_out = uncomp_stream_.total_out; + + // This is used to figure out how many input bytes we read *this chunk*: + const uLong old_total_in = uncomp_stream_.total_in; + + // Some setup happens only for the first chunk we compress in a run + if ( first_chunk_ ) { + first_chunk_ = false; // so we don't do this again + + // For the first chunk *only* (to avoid infinite troubles), we let + // there be no actual data to uncompress. This sometimes triggers + // when the input is only the gzip header, say. + if ( *sourceLen == 0 ) { + *destLen = 0; + return Z_OK; + } + } + + // We'll uncompress as much as we can. If we end OK great, otherwise + // if we get an error that seems to be the gzip footer, we store the + // gzip footer and return OK, otherwise we return the error. + + // flush_mode is Z_SYNC_FLUSH for chunked mode, Z_FINISH for all mode. + err = inflate(&uncomp_stream_, flush_mode); + + // Figure out how many bytes of the input zlib slurped up: + const uLong bytes_read = uncomp_stream_.total_in - old_total_in; + CHECK_LE(source + bytes_read, source + *sourceLen); + *sourceLen = uncomp_stream_.avail_in; + + if ((err == Z_STREAM_END || err == Z_OK) // everything went ok + && uncomp_stream_.avail_in == 0) { // and we read it all + ; + } else if (err == Z_STREAM_END && uncomp_stream_.avail_in > 0) { + LOG(WARNING) + << "UncompressChunkOrAll: Received some extra data, bytes total: " + << uncomp_stream_.avail_in << " bytes: " + << string(reinterpret_cast(uncomp_stream_.next_in), + min(int(uncomp_stream_.avail_in), 20)); + UncompressErrorInit(); + return Z_DATA_ERROR; // what's the extra data for? + } else if (err != Z_OK && err != Z_STREAM_END && err != Z_BUF_ERROR) { + // an error happened + LOG(WARNING) << "UncompressChunkOrAll: Error: " << err + << " avail_out: " << uncomp_stream_.avail_out; + UncompressErrorInit(); + return err; + } else if (uncomp_stream_.avail_out == 0) { + err = Z_BUF_ERROR; + } + + assert(err == Z_OK || err == Z_BUF_ERROR || err == Z_STREAM_END); + if (err == Z_STREAM_END) + err = Z_OK; + + *destLen = uncomp_stream_.total_out - old_total_out; // size for this call + + return err; +} + +int ZLib::UncompressChunkOrAll(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int flush_mode) { // Z_SYNC_FLUSH or Z_FINISH + const int ret = + UncompressAtMostOrAll(dest, destLen, source, &sourceLen, flush_mode); + if (ret == Z_BUF_ERROR) + UncompressErrorInit(); + return ret; +} + +int ZLib::UncompressAtMost(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen) { + return UncompressAtMostOrAll(dest, destLen, source, sourceLen, Z_SYNC_FLUSH); +} + +// We make sure we've uncompressed everything, that is, the current +// uncompress stream is at a compressed-buffer-EOF boundary. In gzip +// mode, we also check the gzip footer to make sure we pass the gzip +// consistency checks. We RETURN true iff both types of checks pass. +bool ZLib::UncompressChunkDone() { + assert(!first_chunk_ && uncomp_init_); + // Make sure we're at the end-of-compressed-data point. This means + // if we call inflate with Z_FINISH we won't consume any input or + // write any output + Bytef dummyin, dummyout; + uLongf dummylen = 0; + if ( UncompressChunkOrAll(&dummyout, &dummylen, &dummyin, 0, Z_FINISH) + != Z_OK ) { + return false; + } + + // Make sure that when we exit, we can start a new round of chunks later + Reset(); + + return true; +} + +// Uncompresses the source buffer into the destination buffer. +// The destination buffer must be long enough to hold the entire +// decompressed contents. +// +// We only initialize the uncomp_stream once. Thereafter, we use +// inflateReset, which should be faster. +// +// Returns Z_OK on success, otherwise, it returns a zlib error code. +int ZLib::Uncompress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen) { + int err; + if ( (err=UncompressChunkOrAll(dest, destLen, source, sourceLen, + Z_FINISH)) != Z_OK ) { + Reset(); // let us try to compress again + return err; + } + if ( !UncompressChunkDone() ) // calls Reset() + return Z_DATA_ERROR; + return Z_OK; // stream_end is ok +} + +#endif // HAVE_LIBZ + +} // namespace snappy diff --git a/snappy/snappy-1.0.5/snappy-test.h b/snappy/snappy-1.0.5/snappy-test.h new file mode 100644 index 00000000..ef6a9553 --- /dev/null +++ b/snappy/snappy-1.0.5/snappy-test.h @@ -0,0 +1,505 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Various stubs for the unit tests for the open-source version of Snappy. + +#ifndef UTIL_SNAPPY_OPENSOURCE_SNAPPY_TEST_H_ +#define UTIL_SNAPPY_OPENSOURCE_SNAPPY_TEST_H_ + +#include "snappy-stubs-internal.h" + +#include +#include + +#ifdef HAVE_SYS_MMAN_H +#include +#endif + +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif + +#include + +#ifdef HAVE_WINDOWS_H +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#include + +#ifdef HAVE_GTEST + +#include +#undef TYPED_TEST +#define TYPED_TEST TEST +#define INIT_GTEST(argc, argv) ::testing::InitGoogleTest(argc, *argv) + +#else + +// Stubs for if the user doesn't have Google Test installed. + +#define TEST(test_case, test_subcase) \ + void Test_ ## test_case ## _ ## test_subcase() +#define INIT_GTEST(argc, argv) + +#define TYPED_TEST TEST +#define EXPECT_EQ CHECK_EQ +#define EXPECT_NE CHECK_NE +#define EXPECT_FALSE(cond) CHECK(!(cond)) + +#endif + +#ifdef HAVE_GFLAGS + +#include + +// This is tricky; both gflags and Google Test want to look at the command line +// arguments. Google Test seems to be the most happy with unknown arguments, +// though, so we call it first and hope for the best. +#define InitGoogle(argv0, argc, argv, remove_flags) \ + INIT_GTEST(argc, argv); \ + google::ParseCommandLineFlags(argc, argv, remove_flags); + +#else + +// If we don't have the gflags package installed, these can only be +// changed at compile time. +#define DEFINE_int32(flag_name, default_value, description) \ + static int FLAGS_ ## flag_name = default_value; + +#define InitGoogle(argv0, argc, argv, remove_flags) \ + INIT_GTEST(argc, argv) + +#endif + +#ifdef HAVE_LIBZ +#include "zlib.h" +#endif + +#ifdef HAVE_LIBLZO2 +#include "lzo/lzo1x.h" +#endif + +#ifdef HAVE_LIBLZF +extern "C" { +#include "lzf.h" +} +#endif + +#ifdef HAVE_LIBFASTLZ +#include "fastlz.h" +#endif + +#ifdef HAVE_LIBQUICKLZ +#include "quicklz.h" +#endif + +namespace { +namespace File { + void Init() { } + + void ReadFileToStringOrDie(const char* filename, string* data) { + FILE* fp = fopen(filename, "rb"); + if (fp == NULL) { + perror(filename); + exit(1); + } + + data->clear(); + while (!feof(fp)) { + char buf[4096]; + size_t ret = fread(buf, 1, 4096, fp); + if (ret == 0 && ferror(fp)) { + perror("fread"); + exit(1); + } + data->append(string(buf, ret)); + } + + fclose(fp); + } + + void ReadFileToStringOrDie(const string& filename, string* data) { + ReadFileToStringOrDie(filename.c_str(), data); + } + + void WriteStringToFileOrDie(const string& str, const char* filename) { + FILE* fp = fopen(filename, "wb"); + if (fp == NULL) { + perror(filename); + exit(1); + } + + int ret = fwrite(str.data(), str.size(), 1, fp); + if (ret != 1) { + perror("fwrite"); + exit(1); + } + + fclose(fp); + } +} // namespace File +} // namespace + +namespace snappy { + +#define FLAGS_test_random_seed 301 +typedef string TypeParam; + +void Test_CorruptedTest_VerifyCorrupted(); +void Test_Snappy_SimpleTests(); +void Test_Snappy_MaxBlowup(); +void Test_Snappy_RandomData(); +void Test_Snappy_FourByteOffset(); +void Test_SnappyCorruption_TruncatedVarint(); +void Test_SnappyCorruption_UnterminatedVarint(); +void Test_Snappy_ReadPastEndOfBuffer(); +void Test_Snappy_FindMatchLength(); +void Test_Snappy_FindMatchLengthRandom(); + +string ReadTestDataFile(const string& base); + +// A sprintf() variant that returns a std::string. +// Not safe for general use due to truncation issues. +string StringPrintf(const char* format, ...); + +// A simple, non-cryptographically-secure random generator. +class ACMRandom { + public: + explicit ACMRandom(uint32 seed) : seed_(seed) {} + + int32 Next(); + + int32 Uniform(int32 n) { + return Next() % n; + } + uint8 Rand8() { + return static_cast((Next() >> 1) & 0x000000ff); + } + bool OneIn(int X) { return Uniform(X) == 0; } + + // Skewed: pick "base" uniformly from range [0,max_log] and then + // return "base" random bits. The effect is to pick a number in the + // range [0,2^max_log-1] with bias towards smaller numbers. + int32 Skewed(int max_log); + + private: + static const uint32 M = 2147483647L; // 2^31-1 + uint32 seed_; +}; + +inline int32 ACMRandom::Next() { + static const uint64 A = 16807; // bits 14, 8, 7, 5, 2, 1, 0 + // We are computing + // seed_ = (seed_ * A) % M, where M = 2^31-1 + // + // seed_ must not be zero or M, or else all subsequent computed values + // will be zero or M respectively. For all other values, seed_ will end + // up cycling through every number in [1,M-1] + uint64 product = seed_ * A; + + // Compute (product % M) using the fact that ((x << 31) % M) == x. + seed_ = (product >> 31) + (product & M); + // The first reduction may overflow by 1 bit, so we may need to repeat. + // mod == M is not possible; using > allows the faster sign-bit-based test. + if (seed_ > M) { + seed_ -= M; + } + return seed_; +} + +inline int32 ACMRandom::Skewed(int max_log) { + const int32 base = (Next() - 1) % (max_log+1); + return (Next() - 1) & ((1u << base)-1); +} + +// A wall-time clock. This stub is not super-accurate, nor resistant to the +// system time changing. +class CycleTimer { + public: + CycleTimer() : real_time_us_(0) {} + + void Start() { +#ifdef WIN32 + QueryPerformanceCounter(&start_); +#else + gettimeofday(&start_, NULL); +#endif + } + + void Stop() { +#ifdef WIN32 + LARGE_INTEGER stop; + LARGE_INTEGER frequency; + QueryPerformanceCounter(&stop); + QueryPerformanceFrequency(&frequency); + + double elapsed = static_cast(stop.QuadPart - start_.QuadPart) / + frequency.QuadPart; + real_time_us_ += elapsed * 1e6 + 0.5; +#else + struct timeval stop; + gettimeofday(&stop, NULL); + + real_time_us_ += 1000000 * (stop.tv_sec - start_.tv_sec); + real_time_us_ += (stop.tv_usec - start_.tv_usec); +#endif + } + + double Get() { + return real_time_us_ * 1e-6; + } + + private: + int64 real_time_us_; +#ifdef WIN32 + LARGE_INTEGER start_; +#else + struct timeval start_; +#endif +}; + +// Minimalistic microbenchmark framework. + +typedef void (*BenchmarkFunction)(int, int); + +class Benchmark { + public: + Benchmark(const string& name, BenchmarkFunction function) : + name_(name), function_(function) {} + + Benchmark* DenseRange(int start, int stop) { + start_ = start; + stop_ = stop; + return this; + } + + void Run(); + + private: + const string name_; + const BenchmarkFunction function_; + int start_, stop_; +}; +#define BENCHMARK(benchmark_name) \ + Benchmark* Benchmark_ ## benchmark_name = \ + (new Benchmark(#benchmark_name, benchmark_name)) + +extern Benchmark* Benchmark_BM_UFlat; +extern Benchmark* Benchmark_BM_UValidate; +extern Benchmark* Benchmark_BM_ZFlat; + +void ResetBenchmarkTiming(); +void StartBenchmarkTiming(); +void StopBenchmarkTiming(); +void SetBenchmarkLabel(const string& str); +void SetBenchmarkBytesProcessed(int64 bytes); + +#ifdef HAVE_LIBZ + +// Object-oriented wrapper around zlib. +class ZLib { + public: + ZLib(); + ~ZLib(); + + // Wipe a ZLib object to a virgin state. This differs from Reset() + // in that it also breaks any state. + void Reinit(); + + // Call this to make a zlib buffer as good as new. Here's the only + // case where they differ: + // CompressChunk(a); CompressChunk(b); CompressChunkDone(); vs + // CompressChunk(a); Reset(); CompressChunk(b); CompressChunkDone(); + // You'll want to use Reset(), then, when you interrupt a compress + // (or uncompress) in the middle of a chunk and want to start over. + void Reset(); + + // According to the zlib manual, when you Compress, the destination + // buffer must have size at least src + .1%*src + 12. This function + // helps you calculate that. Augment this to account for a potential + // gzip header and footer, plus a few bytes of slack. + static int MinCompressbufSize(int uncompress_size) { + return uncompress_size + uncompress_size/1000 + 40; + } + + // Compresses the source buffer into the destination buffer. + // sourceLen is the byte length of the source buffer. + // Upon entry, destLen is the total size of the destination buffer, + // which must be of size at least MinCompressbufSize(sourceLen). + // Upon exit, destLen is the actual size of the compressed buffer. + // + // This function can be used to compress a whole file at once if the + // input file is mmap'ed. + // + // Returns Z_OK if success, Z_MEM_ERROR if there was not + // enough memory, Z_BUF_ERROR if there was not enough room in the + // output buffer. Note that if the output buffer is exactly the same + // size as the compressed result, we still return Z_BUF_ERROR. + // (check CL#1936076) + int Compress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); + + // Uncompresses the source buffer into the destination buffer. + // The destination buffer must be long enough to hold the entire + // decompressed contents. + // + // Returns Z_OK on success, otherwise, it returns a zlib error code. + int Uncompress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); + + // Uncompress data one chunk at a time -- ie you can call this + // more than once. To get this to work you need to call per-chunk + // and "done" routines. + // + // Returns Z_OK if success, Z_MEM_ERROR if there was not + // enough memory, Z_BUF_ERROR if there was not enough room in the + // output buffer. + + int UncompressAtMost(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen); + + // Checks gzip footer information, as needed. Mostly this just + // makes sure the checksums match. Whenever you call this, it + // will assume the last 8 bytes from the previous UncompressChunk + // call are the footer. Returns true iff everything looks ok. + bool UncompressChunkDone(); + + private: + int InflateInit(); // sets up the zlib inflate structure + int DeflateInit(); // sets up the zlib deflate structure + + // These init the zlib data structures for compressing/uncompressing + int CompressInit(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen); + int UncompressInit(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen); + // Initialization method to be called if we hit an error while + // uncompressing. On hitting an error, call this method before + // returning the error. + void UncompressErrorInit(); + + // Helper function for Compress + int CompressChunkOrAll(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int flush_mode); + int CompressAtMostOrAll(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen, + int flush_mode); + + // Likewise for UncompressAndUncompressChunk + int UncompressChunkOrAll(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int flush_mode); + + int UncompressAtMostOrAll(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen, + int flush_mode); + + // Initialization method to be called if we hit an error while + // compressing. On hitting an error, call this method before + // returning the error. + void CompressErrorInit(); + + int compression_level_; // compression level + int window_bits_; // log base 2 of the window size used in compression + int mem_level_; // specifies the amount of memory to be used by + // compressor (1-9) + z_stream comp_stream_; // Zlib stream data structure + bool comp_init_; // True if we have initialized comp_stream_ + z_stream uncomp_stream_; // Zlib stream data structure + bool uncomp_init_; // True if we have initialized uncomp_stream_ + + // These are used only with chunked compression. + bool first_chunk_; // true if we need to emit headers with this chunk +}; + +#endif // HAVE_LIBZ + +} // namespace snappy + +DECLARE_bool(run_microbenchmarks); + +static void RunSpecifiedBenchmarks() { + if (!FLAGS_run_microbenchmarks) { + return; + } + + fprintf(stderr, "Running microbenchmarks.\n"); +#ifndef NDEBUG + fprintf(stderr, "WARNING: Compiled with assertions enabled, will be slow.\n"); +#endif +#ifndef __OPTIMIZE__ + fprintf(stderr, "WARNING: Compiled without optimization, will be slow.\n"); +#endif + fprintf(stderr, "Benchmark Time(ns) CPU(ns) Iterations\n"); + fprintf(stderr, "---------------------------------------------------\n"); + + snappy::Benchmark_BM_UFlat->Run(); + snappy::Benchmark_BM_UValidate->Run(); + snappy::Benchmark_BM_ZFlat->Run(); + + fprintf(stderr, "\n"); +} + +#ifndef HAVE_GTEST + +static inline int RUN_ALL_TESTS() { + fprintf(stderr, "Running correctness tests.\n"); + snappy::Test_CorruptedTest_VerifyCorrupted(); + snappy::Test_Snappy_SimpleTests(); + snappy::Test_Snappy_MaxBlowup(); + snappy::Test_Snappy_RandomData(); + snappy::Test_Snappy_FourByteOffset(); + snappy::Test_SnappyCorruption_TruncatedVarint(); + snappy::Test_SnappyCorruption_UnterminatedVarint(); + snappy::Test_Snappy_ReadPastEndOfBuffer(); + snappy::Test_Snappy_FindMatchLength(); + snappy::Test_Snappy_FindMatchLengthRandom(); + fprintf(stderr, "All tests passed.\n"); + + return 0; +} + +#endif // HAVE_GTEST + +// For main(). +namespace snappy { + +static void CompressFile(const char* fname); +static void UncompressFile(const char* fname); +static void MeasureFile(const char* fname); + +} // namespace + +using snappy::CompressFile; +using snappy::UncompressFile; +using snappy::MeasureFile; + +#endif // UTIL_SNAPPY_OPENSOURCE_SNAPPY_TEST_H_ diff --git a/snappy/snappy-1.0.5/snappy.cc b/snappy/snappy-1.0.5/snappy.cc new file mode 100644 index 00000000..4d4eb42a --- /dev/null +++ b/snappy/snappy-1.0.5/snappy.cc @@ -0,0 +1,1111 @@ +// Copyright 2005 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "snappy.h" +#include "snappy-internal.h" +#include "snappy-sinksource.h" + +#include + +#include +#include +#include + + +namespace snappy { + +// Any hash function will produce a valid compressed bitstream, but a good +// hash function reduces the number of collisions and thus yields better +// compression for compressible input, and more speed for incompressible +// input. Of course, it doesn't hurt if the hash function is reasonably fast +// either, as it gets called a lot. +static inline uint32 HashBytes(uint32 bytes, int shift) { + uint32 kMul = 0x1e35a7bd; + return (bytes * kMul) >> shift; +} +static inline uint32 Hash(const char* p, int shift) { + return HashBytes(UNALIGNED_LOAD32(p), shift); +} + +size_t MaxCompressedLength(size_t source_len) { + // Compressed data can be defined as: + // compressed := item* literal* + // item := literal* copy + // + // The trailing literal sequence has a space blowup of at most 62/60 + // since a literal of length 60 needs one tag byte + one extra byte + // for length information. + // + // Item blowup is trickier to measure. Suppose the "copy" op copies + // 4 bytes of data. Because of a special check in the encoding code, + // we produce a 4-byte copy only if the offset is < 65536. Therefore + // the copy op takes 3 bytes to encode, and this type of item leads + // to at most the 62/60 blowup for representing literals. + // + // Suppose the "copy" op copies 5 bytes of data. If the offset is big + // enough, it will take 5 bytes to encode the copy op. Therefore the + // worst case here is a one-byte literal followed by a five-byte copy. + // I.e., 6 bytes of input turn into 7 bytes of "compressed" data. + // + // This last factor dominates the blowup, so the final estimate is: + return 32 + source_len + source_len/6; +} + +enum { + LITERAL = 0, + COPY_1_BYTE_OFFSET = 1, // 3 bit length + 3 bits of offset in opcode + COPY_2_BYTE_OFFSET = 2, + COPY_4_BYTE_OFFSET = 3 +}; + +// Copy "len" bytes from "src" to "op", one byte at a time. Used for +// handling COPY operations where the input and output regions may +// overlap. For example, suppose: +// src == "ab" +// op == src + 2 +// len == 20 +// After IncrementalCopy(src, op, len), the result will have +// eleven copies of "ab" +// ababababababababababab +// Note that this does not match the semantics of either memcpy() +// or memmove(). +static inline void IncrementalCopy(const char* src, char* op, int len) { + DCHECK_GT(len, 0); + do { + *op++ = *src++; + } while (--len > 0); +} + +// Equivalent to IncrementalCopy except that it can write up to ten extra +// bytes after the end of the copy, and that it is faster. +// +// The main part of this loop is a simple copy of eight bytes at a time until +// we've copied (at least) the requested amount of bytes. However, if op and +// src are less than eight bytes apart (indicating a repeating pattern of +// length < 8), we first need to expand the pattern in order to get the correct +// results. For instance, if the buffer looks like this, with the eight-byte +// and patterns marked as intervals: +// +// abxxxxxxxxxxxx +// [------] src +// [------] op +// +// a single eight-byte copy from to will repeat the pattern once, +// after which we can move two bytes without moving : +// +// ababxxxxxxxxxx +// [------] src +// [------] op +// +// and repeat the exercise until the two no longer overlap. +// +// This allows us to do very well in the special case of one single byte +// repeated many times, without taking a big hit for more general cases. +// +// The worst case of extra writing past the end of the match occurs when +// op - src == 1 and len == 1; the last copy will read from byte positions +// [0..7] and write to [4..11], whereas it was only supposed to write to +// position 1. Thus, ten excess bytes. + +namespace { + +const int kMaxIncrementCopyOverflow = 10; + +} // namespace + +static inline void IncrementalCopyFastPath(const char* src, char* op, int len) { + while (op - src < 8) { + UnalignedCopy64(src, op); + len -= op - src; + op += op - src; + } + while (len > 0) { + UnalignedCopy64(src, op); + src += 8; + op += 8; + len -= 8; + } +} + +static inline char* EmitLiteral(char* op, + const char* literal, + int len, + bool allow_fast_path) { + int n = len - 1; // Zero-length literals are disallowed + if (n < 60) { + // Fits in tag byte + *op++ = LITERAL | (n << 2); + + // The vast majority of copies are below 16 bytes, for which a + // call to memcpy is overkill. This fast path can sometimes + // copy up to 15 bytes too much, but that is okay in the + // main loop, since we have a bit to go on for both sides: + // + // - The input will always have kInputMarginBytes = 15 extra + // available bytes, as long as we're in the main loop, and + // if not, allow_fast_path = false. + // - The output will always have 32 spare bytes (see + // MaxCompressedLength). + if (allow_fast_path && len <= 16) { + UnalignedCopy64(literal, op); + UnalignedCopy64(literal + 8, op + 8); + return op + len; + } + } else { + // Encode in upcoming bytes + char* base = op; + int count = 0; + op++; + while (n > 0) { + *op++ = n & 0xff; + n >>= 8; + count++; + } + assert(count >= 1); + assert(count <= 4); + *base = LITERAL | ((59+count) << 2); + } + memcpy(op, literal, len); + return op + len; +} + +static inline char* EmitCopyLessThan64(char* op, size_t offset, int len) { + DCHECK_LE(len, 64); + DCHECK_GE(len, 4); + DCHECK_LT(offset, 65536); + + if ((len < 12) && (offset < 2048)) { + size_t len_minus_4 = len - 4; + assert(len_minus_4 < 8); // Must fit in 3 bits + *op++ = COPY_1_BYTE_OFFSET | ((len_minus_4) << 2) | ((offset >> 8) << 5); + *op++ = offset & 0xff; + } else { + *op++ = COPY_2_BYTE_OFFSET | ((len-1) << 2); + LittleEndian::Store16(op, offset); + op += 2; + } + return op; +} + +static inline char* EmitCopy(char* op, size_t offset, int len) { + // Emit 64 byte copies but make sure to keep at least four bytes reserved + while (len >= 68) { + op = EmitCopyLessThan64(op, offset, 64); + len -= 64; + } + + // Emit an extra 60 byte copy if have too much data to fit in one copy + if (len > 64) { + op = EmitCopyLessThan64(op, offset, 60); + len -= 60; + } + + // Emit remainder + op = EmitCopyLessThan64(op, offset, len); + return op; +} + + +bool GetUncompressedLength(const char* start, size_t n, size_t* result) { + uint32 v = 0; + const char* limit = start + n; + if (Varint::Parse32WithLimit(start, limit, &v) != NULL) { + *result = v; + return true; + } else { + return false; + } +} + +namespace internal { +uint16* WorkingMemory::GetHashTable(size_t input_size, int* table_size) { + // Use smaller hash table when input.size() is smaller, since we + // fill the table, incurring O(hash table size) overhead for + // compression, and if the input is short, we won't need that + // many hash table entries anyway. + assert(kMaxHashTableSize >= 256); + size_t htsize = 256; + while (htsize < kMaxHashTableSize && htsize < input_size) { + htsize <<= 1; + } + CHECK_EQ(0, htsize & (htsize - 1)) << ": must be power of two"; + CHECK_LE(htsize, kMaxHashTableSize) << ": hash table too large"; + + uint16* table; + if (htsize <= ARRAYSIZE(small_table_)) { + table = small_table_; + } else { + if (large_table_ == NULL) { + large_table_ = new uint16[kMaxHashTableSize]; + } + table = large_table_; + } + + *table_size = htsize; + memset(table, 0, htsize * sizeof(*table)); + return table; +} +} // end namespace internal + +// For 0 <= offset <= 4, GetUint32AtOffset(GetEightBytesAt(p), offset) will +// equal UNALIGNED_LOAD32(p + offset). Motivation: On x86-64 hardware we have +// empirically found that overlapping loads such as +// UNALIGNED_LOAD32(p) ... UNALIGNED_LOAD32(p+1) ... UNALIGNED_LOAD32(p+2) +// are slower than UNALIGNED_LOAD64(p) followed by shifts and casts to uint32. +// +// We have different versions for 64- and 32-bit; ideally we would avoid the +// two functions and just inline the UNALIGNED_LOAD64 call into +// GetUint32AtOffset, but GCC (at least not as of 4.6) is seemingly not clever +// enough to avoid loading the value multiple times then. For 64-bit, the load +// is done when GetEightBytesAt() is called, whereas for 32-bit, the load is +// done at GetUint32AtOffset() time. + +#ifdef ARCH_K8 + +typedef uint64 EightBytesReference; + +static inline EightBytesReference GetEightBytesAt(const char* ptr) { + return UNALIGNED_LOAD64(ptr); +} + +static inline uint32 GetUint32AtOffset(uint64 v, int offset) { + DCHECK_GE(offset, 0); + DCHECK_LE(offset, 4); + return v >> (LittleEndian::IsLittleEndian() ? 8 * offset : 32 - 8 * offset); +} + +#else + +typedef const char* EightBytesReference; + +static inline EightBytesReference GetEightBytesAt(const char* ptr) { + return ptr; +} + +static inline uint32 GetUint32AtOffset(const char* v, int offset) { + DCHECK_GE(offset, 0); + DCHECK_LE(offset, 4); + return UNALIGNED_LOAD32(v + offset); +} + +#endif + +// Flat array compression that does not emit the "uncompressed length" +// prefix. Compresses "input" string to the "*op" buffer. +// +// REQUIRES: "input" is at most "kBlockSize" bytes long. +// REQUIRES: "op" points to an array of memory that is at least +// "MaxCompressedLength(input.size())" in size. +// REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero. +// REQUIRES: "table_size" is a power of two +// +// Returns an "end" pointer into "op" buffer. +// "end - op" is the compressed size of "input". +namespace internal { +char* CompressFragment(const char* input, + size_t input_size, + char* op, + uint16* table, + const int table_size) { + // "ip" is the input pointer, and "op" is the output pointer. + const char* ip = input; + CHECK_LE(input_size, kBlockSize); + CHECK_EQ(table_size & (table_size - 1), 0) << ": table must be power of two"; + const int shift = 32 - Bits::Log2Floor(table_size); + DCHECK_EQ(static_cast(kuint32max >> shift), table_size - 1); + const char* ip_end = input + input_size; + const char* base_ip = ip; + // Bytes in [next_emit, ip) will be emitted as literal bytes. Or + // [next_emit, ip_end) after the main loop. + const char* next_emit = ip; + + const size_t kInputMarginBytes = 15; + if (PREDICT_TRUE(input_size >= kInputMarginBytes)) { + const char* ip_limit = input + input_size - kInputMarginBytes; + + for (uint32 next_hash = Hash(++ip, shift); ; ) { + DCHECK_LT(next_emit, ip); + // The body of this loop calls EmitLiteral once and then EmitCopy one or + // more times. (The exception is that when we're close to exhausting + // the input we goto emit_remainder.) + // + // In the first iteration of this loop we're just starting, so + // there's nothing to copy, so calling EmitLiteral once is + // necessary. And we only start a new iteration when the + // current iteration has determined that a call to EmitLiteral will + // precede the next call to EmitCopy (if any). + // + // Step 1: Scan forward in the input looking for a 4-byte-long match. + // If we get close to exhausting the input then goto emit_remainder. + // + // Heuristic match skipping: If 32 bytes are scanned with no matches + // found, start looking only at every other byte. If 32 more bytes are + // scanned, look at every third byte, etc.. When a match is found, + // immediately go back to looking at every byte. This is a small loss + // (~5% performance, ~0.1% density) for compressible data due to more + // bookkeeping, but for non-compressible data (such as JPEG) it's a huge + // win since the compressor quickly "realizes" the data is incompressible + // and doesn't bother looking for matches everywhere. + // + // The "skip" variable keeps track of how many bytes there are since the + // last match; dividing it by 32 (ie. right-shifting by five) gives the + // number of bytes to move ahead for each iteration. + uint32 skip = 32; + + const char* next_ip = ip; + const char* candidate; + do { + ip = next_ip; + uint32 hash = next_hash; + DCHECK_EQ(hash, Hash(ip, shift)); + uint32 bytes_between_hash_lookups = skip++ >> 5; + next_ip = ip + bytes_between_hash_lookups; + if (PREDICT_FALSE(next_ip > ip_limit)) { + goto emit_remainder; + } + next_hash = Hash(next_ip, shift); + candidate = base_ip + table[hash]; + DCHECK_GE(candidate, base_ip); + DCHECK_LT(candidate, ip); + + table[hash] = ip - base_ip; + } while (PREDICT_TRUE(UNALIGNED_LOAD32(ip) != + UNALIGNED_LOAD32(candidate))); + + // Step 2: A 4-byte match has been found. We'll later see if more + // than 4 bytes match. But, prior to the match, input + // bytes [next_emit, ip) are unmatched. Emit them as "literal bytes." + DCHECK_LE(next_emit + 16, ip_end); + op = EmitLiteral(op, next_emit, ip - next_emit, true); + + // Step 3: Call EmitCopy, and then see if another EmitCopy could + // be our next move. Repeat until we find no match for the + // input immediately after what was consumed by the last EmitCopy call. + // + // If we exit this loop normally then we need to call EmitLiteral next, + // though we don't yet know how big the literal will be. We handle that + // by proceeding to the next iteration of the main loop. We also can exit + // this loop via goto if we get close to exhausting the input. + EightBytesReference input_bytes; + uint32 candidate_bytes = 0; + + do { + // We have a 4-byte match at ip, and no need to emit any + // "literal bytes" prior to ip. + const char* base = ip; + int matched = 4 + FindMatchLength(candidate + 4, ip + 4, ip_end); + ip += matched; + size_t offset = base - candidate; + DCHECK_EQ(0, memcmp(base, candidate, matched)); + op = EmitCopy(op, offset, matched); + // We could immediately start working at ip now, but to improve + // compression we first update table[Hash(ip - 1, ...)]. + const char* insert_tail = ip - 1; + next_emit = ip; + if (PREDICT_FALSE(ip >= ip_limit)) { + goto emit_remainder; + } + input_bytes = GetEightBytesAt(insert_tail); + uint32 prev_hash = HashBytes(GetUint32AtOffset(input_bytes, 0), shift); + table[prev_hash] = ip - base_ip - 1; + uint32 cur_hash = HashBytes(GetUint32AtOffset(input_bytes, 1), shift); + candidate = base_ip + table[cur_hash]; + candidate_bytes = UNALIGNED_LOAD32(candidate); + table[cur_hash] = ip - base_ip; + } while (GetUint32AtOffset(input_bytes, 1) == candidate_bytes); + + next_hash = HashBytes(GetUint32AtOffset(input_bytes, 2), shift); + ++ip; + } + } + + emit_remainder: + // Emit the remaining bytes as a literal + if (next_emit < ip_end) { + op = EmitLiteral(op, next_emit, ip_end - next_emit, false); + } + + return op; +} +} // end namespace internal + +// Signature of output types needed by decompression code. +// The decompression code is templatized on a type that obeys this +// signature so that we do not pay virtual function call overhead in +// the middle of a tight decompression loop. +// +// class DecompressionWriter { +// public: +// // Called before decompression +// void SetExpectedLength(size_t length); +// +// // Called after decompression +// bool CheckLength() const; +// +// // Called repeatedly during decompression +// bool Append(const char* ip, size_t length); +// bool AppendFromSelf(uint32 offset, size_t length); +// +// // The difference between TryFastAppend and Append is that TryFastAppend +// // is allowed to read up to bytes from the input buffer, +// // whereas Append is allowed to read . +// // +// // Also, TryFastAppend is allowed to return false, declining the append, +// // without it being a fatal error -- just "return false" would be +// // a perfectly legal implementation of TryFastAppend. The intention +// // is for TryFastAppend to allow a fast path in the common case of +// // a small append. +// // +// // NOTE(user): TryFastAppend must always return decline (return false) +// // if is 61 or more, as in this case the literal length is not +// // decoded fully. In practice, this should not be a big problem, +// // as it is unlikely that one would implement a fast path accepting +// // this much data. +// bool TryFastAppend(const char* ip, size_t available, size_t length); +// }; + +// ----------------------------------------------------------------------- +// Lookup table for decompression code. Generated by ComputeTable() below. +// ----------------------------------------------------------------------- + +// Mapping from i in range [0,4] to a mask to extract the bottom 8*i bits +static const uint32 wordmask[] = { + 0u, 0xffu, 0xffffu, 0xffffffu, 0xffffffffu +}; + +// Data stored per entry in lookup table: +// Range Bits-used Description +// ------------------------------------ +// 1..64 0..7 Literal/copy length encoded in opcode byte +// 0..7 8..10 Copy offset encoded in opcode byte / 256 +// 0..4 11..13 Extra bytes after opcode +// +// We use eight bits for the length even though 7 would have sufficed +// because of efficiency reasons: +// (1) Extracting a byte is faster than a bit-field +// (2) It properly aligns copy offset so we do not need a <<8 +static const uint16 char_table[256] = { + 0x0001, 0x0804, 0x1001, 0x2001, 0x0002, 0x0805, 0x1002, 0x2002, + 0x0003, 0x0806, 0x1003, 0x2003, 0x0004, 0x0807, 0x1004, 0x2004, + 0x0005, 0x0808, 0x1005, 0x2005, 0x0006, 0x0809, 0x1006, 0x2006, + 0x0007, 0x080a, 0x1007, 0x2007, 0x0008, 0x080b, 0x1008, 0x2008, + 0x0009, 0x0904, 0x1009, 0x2009, 0x000a, 0x0905, 0x100a, 0x200a, + 0x000b, 0x0906, 0x100b, 0x200b, 0x000c, 0x0907, 0x100c, 0x200c, + 0x000d, 0x0908, 0x100d, 0x200d, 0x000e, 0x0909, 0x100e, 0x200e, + 0x000f, 0x090a, 0x100f, 0x200f, 0x0010, 0x090b, 0x1010, 0x2010, + 0x0011, 0x0a04, 0x1011, 0x2011, 0x0012, 0x0a05, 0x1012, 0x2012, + 0x0013, 0x0a06, 0x1013, 0x2013, 0x0014, 0x0a07, 0x1014, 0x2014, + 0x0015, 0x0a08, 0x1015, 0x2015, 0x0016, 0x0a09, 0x1016, 0x2016, + 0x0017, 0x0a0a, 0x1017, 0x2017, 0x0018, 0x0a0b, 0x1018, 0x2018, + 0x0019, 0x0b04, 0x1019, 0x2019, 0x001a, 0x0b05, 0x101a, 0x201a, + 0x001b, 0x0b06, 0x101b, 0x201b, 0x001c, 0x0b07, 0x101c, 0x201c, + 0x001d, 0x0b08, 0x101d, 0x201d, 0x001e, 0x0b09, 0x101e, 0x201e, + 0x001f, 0x0b0a, 0x101f, 0x201f, 0x0020, 0x0b0b, 0x1020, 0x2020, + 0x0021, 0x0c04, 0x1021, 0x2021, 0x0022, 0x0c05, 0x1022, 0x2022, + 0x0023, 0x0c06, 0x1023, 0x2023, 0x0024, 0x0c07, 0x1024, 0x2024, + 0x0025, 0x0c08, 0x1025, 0x2025, 0x0026, 0x0c09, 0x1026, 0x2026, + 0x0027, 0x0c0a, 0x1027, 0x2027, 0x0028, 0x0c0b, 0x1028, 0x2028, + 0x0029, 0x0d04, 0x1029, 0x2029, 0x002a, 0x0d05, 0x102a, 0x202a, + 0x002b, 0x0d06, 0x102b, 0x202b, 0x002c, 0x0d07, 0x102c, 0x202c, + 0x002d, 0x0d08, 0x102d, 0x202d, 0x002e, 0x0d09, 0x102e, 0x202e, + 0x002f, 0x0d0a, 0x102f, 0x202f, 0x0030, 0x0d0b, 0x1030, 0x2030, + 0x0031, 0x0e04, 0x1031, 0x2031, 0x0032, 0x0e05, 0x1032, 0x2032, + 0x0033, 0x0e06, 0x1033, 0x2033, 0x0034, 0x0e07, 0x1034, 0x2034, + 0x0035, 0x0e08, 0x1035, 0x2035, 0x0036, 0x0e09, 0x1036, 0x2036, + 0x0037, 0x0e0a, 0x1037, 0x2037, 0x0038, 0x0e0b, 0x1038, 0x2038, + 0x0039, 0x0f04, 0x1039, 0x2039, 0x003a, 0x0f05, 0x103a, 0x203a, + 0x003b, 0x0f06, 0x103b, 0x203b, 0x003c, 0x0f07, 0x103c, 0x203c, + 0x0801, 0x0f08, 0x103d, 0x203d, 0x1001, 0x0f09, 0x103e, 0x203e, + 0x1801, 0x0f0a, 0x103f, 0x203f, 0x2001, 0x0f0b, 0x1040, 0x2040 +}; + +// In debug mode, allow optional computation of the table at startup. +// Also, check that the decompression table is correct. +#ifndef NDEBUG +DEFINE_bool(snappy_dump_decompression_table, false, + "If true, we print the decompression table at startup."); + +static uint16 MakeEntry(unsigned int extra, + unsigned int len, + unsigned int copy_offset) { + // Check that all of the fields fit within the allocated space + DCHECK_EQ(extra, extra & 0x7); // At most 3 bits + DCHECK_EQ(copy_offset, copy_offset & 0x7); // At most 3 bits + DCHECK_EQ(len, len & 0x7f); // At most 7 bits + return len | (copy_offset << 8) | (extra << 11); +} + +static void ComputeTable() { + uint16 dst[256]; + + // Place invalid entries in all places to detect missing initialization + int assigned = 0; + for (int i = 0; i < 256; i++) { + dst[i] = 0xffff; + } + + // Small LITERAL entries. We store (len-1) in the top 6 bits. + for (unsigned int len = 1; len <= 60; len++) { + dst[LITERAL | ((len-1) << 2)] = MakeEntry(0, len, 0); + assigned++; + } + + // Large LITERAL entries. We use 60..63 in the high 6 bits to + // encode the number of bytes of length info that follow the opcode. + for (unsigned int extra_bytes = 1; extra_bytes <= 4; extra_bytes++) { + // We set the length field in the lookup table to 1 because extra + // bytes encode len-1. + dst[LITERAL | ((extra_bytes+59) << 2)] = MakeEntry(extra_bytes, 1, 0); + assigned++; + } + + // COPY_1_BYTE_OFFSET. + // + // The tag byte in the compressed data stores len-4 in 3 bits, and + // offset/256 in 5 bits. offset%256 is stored in the next byte. + // + // This format is used for length in range [4..11] and offset in + // range [0..2047] + for (unsigned int len = 4; len < 12; len++) { + for (unsigned int offset = 0; offset < 2048; offset += 256) { + dst[COPY_1_BYTE_OFFSET | ((len-4)<<2) | ((offset>>8)<<5)] = + MakeEntry(1, len, offset>>8); + assigned++; + } + } + + // COPY_2_BYTE_OFFSET. + // Tag contains len-1 in top 6 bits, and offset in next two bytes. + for (unsigned int len = 1; len <= 64; len++) { + dst[COPY_2_BYTE_OFFSET | ((len-1)<<2)] = MakeEntry(2, len, 0); + assigned++; + } + + // COPY_4_BYTE_OFFSET. + // Tag contents len-1 in top 6 bits, and offset in next four bytes. + for (unsigned int len = 1; len <= 64; len++) { + dst[COPY_4_BYTE_OFFSET | ((len-1)<<2)] = MakeEntry(4, len, 0); + assigned++; + } + + // Check that each entry was initialized exactly once. + CHECK_EQ(assigned, 256); + for (int i = 0; i < 256; i++) { + CHECK_NE(dst[i], 0xffff); + } + + if (FLAGS_snappy_dump_decompression_table) { + printf("static const uint16 char_table[256] = {\n "); + for (int i = 0; i < 256; i++) { + printf("0x%04x%s", + dst[i], + ((i == 255) ? "\n" : (((i%8) == 7) ? ",\n " : ", "))); + } + printf("};\n"); + } + + // Check that computed table matched recorded table + for (int i = 0; i < 256; i++) { + CHECK_EQ(dst[i], char_table[i]); + } +} +#endif /* !NDEBUG */ + +// Helper class for decompression +class SnappyDecompressor { + private: + Source* reader_; // Underlying source of bytes to decompress + const char* ip_; // Points to next buffered byte + const char* ip_limit_; // Points just past buffered bytes + uint32 peeked_; // Bytes peeked from reader (need to skip) + bool eof_; // Hit end of input without an error? + char scratch_[5]; // Temporary buffer for PeekFast() boundaries + + // Ensure that all of the tag metadata for the next tag is available + // in [ip_..ip_limit_-1]. Also ensures that [ip,ip+4] is readable even + // if (ip_limit_ - ip_ < 5). + // + // Returns true on success, false on error or end of input. + bool RefillTag(); + + public: + explicit SnappyDecompressor(Source* reader) + : reader_(reader), + ip_(NULL), + ip_limit_(NULL), + peeked_(0), + eof_(false) { + } + + ~SnappyDecompressor() { + // Advance past any bytes we peeked at from the reader + reader_->Skip(peeked_); + } + + // Returns true iff we have hit the end of the input without an error. + bool eof() const { + return eof_; + } + + // Read the uncompressed length stored at the start of the compressed data. + // On succcess, stores the length in *result and returns true. + // On failure, returns false. + bool ReadUncompressedLength(uint32* result) { + DCHECK(ip_ == NULL); // Must not have read anything yet + // Length is encoded in 1..5 bytes + *result = 0; + uint32 shift = 0; + while (true) { + if (shift >= 32) return false; + size_t n; + const char* ip = reader_->Peek(&n); + if (n == 0) return false; + const unsigned char c = *(reinterpret_cast(ip)); + reader_->Skip(1); + *result |= static_cast(c & 0x7f) << shift; + if (c < 128) { + break; + } + shift += 7; + } + return true; + } + + // Process the next item found in the input. + // Returns true if successful, false on error or end of input. + template + void DecompressAllTags(Writer* writer) { + const char* ip = ip_; + + // We could have put this refill fragment only at the beginning of the loop. + // However, duplicating it at the end of each branch gives the compiler more + // scope to optimize the expression based on the local + // context, which overall increases speed. + #define MAYBE_REFILL() \ + if (ip_limit_ - ip < 5) { \ + ip_ = ip; \ + if (!RefillTag()) return; \ + ip = ip_; \ + } + + MAYBE_REFILL(); + for ( ;; ) { + const unsigned char c = *(reinterpret_cast(ip++)); + + if ((c & 0x3) == LITERAL) { + size_t literal_length = (c >> 2) + 1u; + if (writer->TryFastAppend(ip, ip_limit_ - ip, literal_length)) { + DCHECK_LT(literal_length, 61); + ip += literal_length; + MAYBE_REFILL(); + continue; + } + if (PREDICT_FALSE(literal_length >= 61)) { + // Long literal. + const size_t literal_length_length = literal_length - 60; + literal_length = + (LittleEndian::Load32(ip) & wordmask[literal_length_length]) + 1; + ip += literal_length_length; + } + + size_t avail = ip_limit_ - ip; + while (avail < literal_length) { + if (!writer->Append(ip, avail)) return; + literal_length -= avail; + reader_->Skip(peeked_); + size_t n; + ip = reader_->Peek(&n); + avail = n; + peeked_ = avail; + if (avail == 0) return; // Premature end of input + ip_limit_ = ip + avail; + } + if (!writer->Append(ip, literal_length)) { + return; + } + ip += literal_length; + MAYBE_REFILL(); + } else { + const uint32 entry = char_table[c]; + const uint32 trailer = LittleEndian::Load32(ip) & wordmask[entry >> 11]; + const uint32 length = entry & 0xff; + ip += entry >> 11; + + // copy_offset/256 is encoded in bits 8..10. By just fetching + // those bits, we get copy_offset (since the bit-field starts at + // bit 8). + const uint32 copy_offset = entry & 0x700; + if (!writer->AppendFromSelf(copy_offset + trailer, length)) { + return; + } + MAYBE_REFILL(); + } + } + +#undef MAYBE_REFILL + } +}; + +bool SnappyDecompressor::RefillTag() { + const char* ip = ip_; + if (ip == ip_limit_) { + // Fetch a new fragment from the reader + reader_->Skip(peeked_); // All peeked bytes are used up + size_t n; + ip = reader_->Peek(&n); + peeked_ = n; + if (n == 0) { + eof_ = true; + return false; + } + ip_limit_ = ip + n; + } + + // Read the tag character + DCHECK_LT(ip, ip_limit_); + const unsigned char c = *(reinterpret_cast(ip)); + const uint32 entry = char_table[c]; + const uint32 needed = (entry >> 11) + 1; // +1 byte for 'c' + DCHECK_LE(needed, sizeof(scratch_)); + + // Read more bytes from reader if needed + uint32 nbuf = ip_limit_ - ip; + if (nbuf < needed) { + // Stitch together bytes from ip and reader to form the word + // contents. We store the needed bytes in "scratch_". They + // will be consumed immediately by the caller since we do not + // read more than we need. + memmove(scratch_, ip, nbuf); + reader_->Skip(peeked_); // All peeked bytes are used up + peeked_ = 0; + while (nbuf < needed) { + size_t length; + const char* src = reader_->Peek(&length); + if (length == 0) return false; + uint32 to_add = min(needed - nbuf, length); + memcpy(scratch_ + nbuf, src, to_add); + nbuf += to_add; + reader_->Skip(to_add); + } + DCHECK_EQ(nbuf, needed); + ip_ = scratch_; + ip_limit_ = scratch_ + needed; + } else if (nbuf < 5) { + // Have enough bytes, but move into scratch_ so that we do not + // read past end of input + memmove(scratch_, ip, nbuf); + reader_->Skip(peeked_); // All peeked bytes are used up + peeked_ = 0; + ip_ = scratch_; + ip_limit_ = scratch_ + nbuf; + } else { + // Pass pointer to buffer returned by reader_. + ip_ = ip; + } + return true; +} + +template +static bool InternalUncompress(Source* r, + Writer* writer, + uint32 max_len) { + // Read the uncompressed length from the front of the compressed input + SnappyDecompressor decompressor(r); + uint32 uncompressed_len = 0; + if (!decompressor.ReadUncompressedLength(&uncompressed_len)) return false; + return InternalUncompressAllTags( + &decompressor, writer, uncompressed_len, max_len); +} + +template +static bool InternalUncompressAllTags(SnappyDecompressor* decompressor, + Writer* writer, + uint32 uncompressed_len, + uint32 max_len) { + // Protect against possible DoS attack + if (static_cast(uncompressed_len) > max_len) { + return false; + } + + writer->SetExpectedLength(uncompressed_len); + + // Process the entire input + decompressor->DecompressAllTags(writer); + return (decompressor->eof() && writer->CheckLength()); +} + +bool GetUncompressedLength(Source* source, uint32* result) { + SnappyDecompressor decompressor(source); + return decompressor.ReadUncompressedLength(result); +} + +size_t Compress(Source* reader, Sink* writer) { + size_t written = 0; + size_t N = reader->Available(); + char ulength[Varint::kMax32]; + char* p = Varint::Encode32(ulength, N); + writer->Append(ulength, p-ulength); + written += (p - ulength); + + internal::WorkingMemory wmem; + char* scratch = NULL; + char* scratch_output = NULL; + + while (N > 0) { + // Get next block to compress (without copying if possible) + size_t fragment_size; + const char* fragment = reader->Peek(&fragment_size); + DCHECK_NE(fragment_size, 0) << ": premature end of input"; + const size_t num_to_read = min(N, kBlockSize); + size_t bytes_read = fragment_size; + + size_t pending_advance = 0; + if (bytes_read >= num_to_read) { + // Buffer returned by reader is large enough + pending_advance = num_to_read; + fragment_size = num_to_read; + } else { + // Read into scratch buffer + if (scratch == NULL) { + // If this is the last iteration, we want to allocate N bytes + // of space, otherwise the max possible kBlockSize space. + // num_to_read contains exactly the correct value + scratch = new char[num_to_read]; + } + memcpy(scratch, fragment, bytes_read); + reader->Skip(bytes_read); + + while (bytes_read < num_to_read) { + fragment = reader->Peek(&fragment_size); + size_t n = min(fragment_size, num_to_read - bytes_read); + memcpy(scratch + bytes_read, fragment, n); + bytes_read += n; + reader->Skip(n); + } + DCHECK_EQ(bytes_read, num_to_read); + fragment = scratch; + fragment_size = num_to_read; + } + DCHECK_EQ(fragment_size, num_to_read); + + // Get encoding table for compression + int table_size; + uint16* table = wmem.GetHashTable(num_to_read, &table_size); + + // Compress input_fragment and append to dest + const int max_output = MaxCompressedLength(num_to_read); + + // Need a scratch buffer for the output, in case the byte sink doesn't + // have room for us directly. + if (scratch_output == NULL) { + scratch_output = new char[max_output]; + } else { + // Since we encode kBlockSize regions followed by a region + // which is <= kBlockSize in length, a previously allocated + // scratch_output[] region is big enough for this iteration. + } + char* dest = writer->GetAppendBuffer(max_output, scratch_output); + char* end = internal::CompressFragment(fragment, fragment_size, + dest, table, table_size); + writer->Append(dest, end - dest); + written += (end - dest); + + N -= num_to_read; + reader->Skip(pending_advance); + } + + delete[] scratch; + delete[] scratch_output; + + return written; +} + +// ----------------------------------------------------------------------- +// Flat array interfaces +// ----------------------------------------------------------------------- + +// A type that writes to a flat array. +// Note that this is not a "ByteSink", but a type that matches the +// Writer template argument to SnappyDecompressor::DecompressAllTags(). +class SnappyArrayWriter { + private: + char* base_; + char* op_; + char* op_limit_; + + public: + inline explicit SnappyArrayWriter(char* dst) + : base_(dst), + op_(dst) { + } + + inline void SetExpectedLength(size_t len) { + op_limit_ = op_ + len; + } + + inline bool CheckLength() const { + return op_ == op_limit_; + } + + inline bool Append(const char* ip, size_t len) { + char* op = op_; + const size_t space_left = op_limit_ - op; + if (space_left < len) { + return false; + } + memcpy(op, ip, len); + op_ = op + len; + return true; + } + + inline bool TryFastAppend(const char* ip, size_t available, size_t len) { + char* op = op_; + const size_t space_left = op_limit_ - op; + if (len <= 16 && available >= 16 && space_left >= 16) { + // Fast path, used for the majority (about 95%) of invocations. + UnalignedCopy64(ip, op); + UnalignedCopy64(ip + 8, op + 8); + op_ = op + len; + return true; + } else { + return false; + } + } + + inline bool AppendFromSelf(size_t offset, size_t len) { + char* op = op_; + const size_t space_left = op_limit_ - op; + + if (op - base_ <= offset - 1u) { // -1u catches offset==0 + return false; + } + if (len <= 16 && offset >= 8 && space_left >= 16) { + // Fast path, used for the majority (70-80%) of dynamic invocations. + UnalignedCopy64(op - offset, op); + UnalignedCopy64(op - offset + 8, op + 8); + } else { + if (space_left >= len + kMaxIncrementCopyOverflow) { + IncrementalCopyFastPath(op - offset, op, len); + } else { + if (space_left < len) { + return false; + } + IncrementalCopy(op - offset, op, len); + } + } + + op_ = op + len; + return true; + } +}; + +bool RawUncompress(const char* compressed, size_t n, char* uncompressed) { + ByteArraySource reader(compressed, n); + return RawUncompress(&reader, uncompressed); +} + +bool RawUncompress(Source* compressed, char* uncompressed) { + SnappyArrayWriter output(uncompressed); + return InternalUncompress(compressed, &output, kuint32max); +} + +bool Uncompress(const char* compressed, size_t n, string* uncompressed) { + size_t ulength; + if (!GetUncompressedLength(compressed, n, &ulength)) { + return false; + } + // Protect against possible DoS attack + if ((static_cast(ulength) + uncompressed->size()) > + uncompressed->max_size()) { + return false; + } + STLStringResizeUninitialized(uncompressed, ulength); + return RawUncompress(compressed, n, string_as_array(uncompressed)); +} + + +// A Writer that drops everything on the floor and just does validation +class SnappyDecompressionValidator { + private: + size_t expected_; + size_t produced_; + + public: + inline SnappyDecompressionValidator() : produced_(0) { } + inline void SetExpectedLength(size_t len) { + expected_ = len; + } + inline bool CheckLength() const { + return expected_ == produced_; + } + inline bool Append(const char* ip, size_t len) { + produced_ += len; + return produced_ <= expected_; + } + inline bool TryFastAppend(const char* ip, size_t available, size_t length) { + return false; + } + inline bool AppendFromSelf(size_t offset, size_t len) { + if (produced_ <= offset - 1u) return false; // -1u catches offset==0 + produced_ += len; + return produced_ <= expected_; + } +}; + +bool IsValidCompressedBuffer(const char* compressed, size_t n) { + ByteArraySource reader(compressed, n); + SnappyDecompressionValidator writer; + return InternalUncompress(&reader, &writer, kuint32max); +} + +void RawCompress(const char* input, + size_t input_length, + char* compressed, + size_t* compressed_length) { + ByteArraySource reader(input, input_length); + UncheckedByteArraySink writer(compressed); + Compress(&reader, &writer); + + // Compute how many bytes were added + *compressed_length = (writer.CurrentDestination() - compressed); +} + +size_t Compress(const char* input, size_t input_length, string* compressed) { + // Pre-grow the buffer to the max length of the compressed output + compressed->resize(MaxCompressedLength(input_length)); + + size_t compressed_length; + RawCompress(input, input_length, string_as_array(compressed), + &compressed_length); + compressed->resize(compressed_length); + return compressed_length; +} + + +} // end namespace snappy + diff --git a/snappy/snappy-1.0.5/snappy.h b/snappy/snappy-1.0.5/snappy.h new file mode 100644 index 00000000..8c2075fe --- /dev/null +++ b/snappy/snappy-1.0.5/snappy.h @@ -0,0 +1,155 @@ +// Copyright 2005 and onwards Google Inc. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// A light-weight compression algorithm. It is designed for speed of +// compression and decompression, rather than for the utmost in space +// savings. +// +// For getting better compression ratios when you are compressing data +// with long repeated sequences or compressing data that is similar to +// other data, while still compressing fast, you might look at first +// using BMDiff and then compressing the output of BMDiff with +// Snappy. + +#ifndef UTIL_SNAPPY_SNAPPY_H__ +#define UTIL_SNAPPY_SNAPPY_H__ + +#include +#include + +#include "snappy-stubs-public.h" + +namespace snappy { + class Source; + class Sink; + + // ------------------------------------------------------------------------ + // Generic compression/decompression routines. + // ------------------------------------------------------------------------ + + // Compress the bytes read from "*source" and append to "*sink". Return the + // number of bytes written. + size_t Compress(Source* source, Sink* sink); + + bool GetUncompressedLength(Source* source, uint32* result); + + // ------------------------------------------------------------------------ + // Higher-level string based routines (should be sufficient for most users) + // ------------------------------------------------------------------------ + + // Sets "*output" to the compressed version of "input[0,input_length-1]". + // Original contents of *output are lost. + // + // REQUIRES: "input[]" is not an alias of "*output". + size_t Compress(const char* input, size_t input_length, string* output); + + // Decompresses "compressed[0,compressed_length-1]" to "*uncompressed". + // Original contents of "*uncompressed" are lost. + // + // REQUIRES: "compressed[]" is not an alias of "*uncompressed". + // + // returns false if the message is corrupted and could not be decompressed + bool Uncompress(const char* compressed, size_t compressed_length, + string* uncompressed); + + + // ------------------------------------------------------------------------ + // Lower-level character array based routines. May be useful for + // efficiency reasons in certain circumstances. + // ------------------------------------------------------------------------ + + // REQUIRES: "compressed" must point to an area of memory that is at + // least "MaxCompressedLength(input_length)" bytes in length. + // + // Takes the data stored in "input[0..input_length]" and stores + // it in the array pointed to by "compressed". + // + // "*compressed_length" is set to the length of the compressed output. + // + // Example: + // char* output = new char[snappy::MaxCompressedLength(input_length)]; + // size_t output_length; + // RawCompress(input, input_length, output, &output_length); + // ... Process(output, output_length) ... + // delete [] output; + void RawCompress(const char* input, + size_t input_length, + char* compressed, + size_t* compressed_length); + + // Given data in "compressed[0..compressed_length-1]" generated by + // calling the Snappy::Compress routine, this routine + // stores the uncompressed data to + // uncompressed[0..GetUncompressedLength(compressed)-1] + // returns false if the message is corrupted and could not be decrypted + bool RawUncompress(const char* compressed, size_t compressed_length, + char* uncompressed); + + // Given data from the byte source 'compressed' generated by calling + // the Snappy::Compress routine, this routine stores the uncompressed + // data to + // uncompressed[0..GetUncompressedLength(compressed,compressed_length)-1] + // returns false if the message is corrupted and could not be decrypted + bool RawUncompress(Source* compressed, char* uncompressed); + + // Returns the maximal size of the compressed representation of + // input data that is "source_bytes" bytes in length; + size_t MaxCompressedLength(size_t source_bytes); + + // REQUIRES: "compressed[]" was produced by RawCompress() or Compress() + // Returns true and stores the length of the uncompressed data in + // *result normally. Returns false on parsing error. + // This operation takes O(1) time. + bool GetUncompressedLength(const char* compressed, size_t compressed_length, + size_t* result); + + // Returns true iff the contents of "compressed[]" can be uncompressed + // successfully. Does not return the uncompressed data. Takes + // time proportional to compressed_length, but is usually at least + // a factor of four faster than actual decompression. + bool IsValidCompressedBuffer(const char* compressed, + size_t compressed_length); + + // *** DO NOT CHANGE THE VALUE OF kBlockSize *** + // + // New Compression code chops up the input into blocks of at most + // the following size. This ensures that back-references in the + // output never cross kBlockSize block boundaries. This can be + // helpful in implementing blocked decompression. However the + // decompression code should not rely on this guarantee since older + // compression code may not obey it. + static const int kBlockLog = 15; + static const size_t kBlockSize = 1 << kBlockLog; + + static const int kMaxHashTableBits = 14; + static const size_t kMaxHashTableSize = 1 << kMaxHashTableBits; + +} // end namespace snappy + + +#endif // UTIL_SNAPPY_SNAPPY_H__ diff --git a/snappy/snappy-1.0.5/snappy.lo b/snappy/snappy-1.0.5/snappy.lo new file mode 100644 index 00000000..cd2ee8ff --- /dev/null +++ b/snappy/snappy-1.0.5/snappy.lo @@ -0,0 +1,12 @@ +# snappy.lo - a libtool object file +# Generated by ltmain.sh (GNU libtool) 2.2.6b Debian-2.2.6b-2ubuntu1 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object='.libs/snappy.o' + +# Name of the non-PIC object +non_pic_object='snappy.o' + diff --git a/snappy/snappy-1.0.5/snappy_unittest b/snappy/snappy-1.0.5/snappy_unittest new file mode 100755 index 00000000..d6902489 --- /dev/null +++ b/snappy/snappy-1.0.5/snappy_unittest @@ -0,0 +1,148 @@ +#! /bin/sh + +# snappy_unittest - temporary wrapper script for .libs/snappy_unittest +# Generated by ltmain.sh (GNU libtool) 2.2.6b Debian-2.2.6b-2ubuntu1 +# +# The snappy_unittest program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='/bin/sed -e 1s/^X//' +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + 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 + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command="(cd /home/dhruba/local/leveldb.releases/snappy/snappy-1.0.5; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; LD_LIBRARY_PATH=./snappy/libs; export LD_LIBRARY_PATH; PATH=\"/usr/local/jdk-6u7-32//bin:/home/dhruba/maven/bin:/home/dhruba/bin/:/home/dhruba/external/apache-ant-1.8.1/bin/:/usr/local/java/bin/:~/pl/bin:~/maven/bin:/home/dhruba/apache-ant-1.7.0/bin:/usr/kerberos/bin:/opt/local/bin:/usr/local/bin:/bin:/usr/bin:/usr/facebook/scripts:/home/engshare/devtools/facebook/bin:/home/engshare/svnroot/tfb/trunk/www/scripts/bin:/home/engshare/admin/scripts/git:/home/engshare/admin/scripts:/home/dhruba/www/scripts/bin:/home/dhruba/bin\"; export PATH; /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/centos5.2-native/gcc/gcc-4.6.2-glibc-2.13/bin/g++ -O2 -DNDEBUG -o \$progdir/\$file snappy_unittest-snappy_unittest.o snappy_unittest-snappy-test.o ./.libs/libsnappy.so -lz /mnt/gvfs/third-party/d28c90311ca14f9f0b2bb720f4e34b285513d4f4/gcc-4.6.2-glibc-2.13/jemalloc/jemalloc-2.2.4/96de4f9/lib/libjemalloc_pic.a -Wl,-rpath -Wl,/home/dhruba/local/leveldb.releases/snappy/snappy-1.0.5/.libs)" + +# This environment variable determines our operation mode. +if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then + # install mode needs the following variables: + generated_by_libtool_version='2.2.6b' + notinst_deplibs=' libsnappy.la' +else + # When we are sourced in execute mode, $file and $ECHO are already set. + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + ECHO="echo" + file="$0" + # Make sure echo works. + if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then + # Yippee, $ECHO works! + : + else + # Restart under the correct shell, and then maybe $ECHO will work. + exec /bin/sh "$0" --no-reexec ${1+"$@"} + fi + fi + + # Find the directory that this script lives in. + thisdir=`$ECHO "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "x$thisdir" = "x$file" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'` + while test -n "$file"; do + destdir=`$ECHO "X$file" | $Xsed -e 's%/[^/]*$%%'` + + # If there was a directory component, then change thisdir. + if test "x$destdir" != "x$file"; then + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; + *) thisdir="$thisdir/$destdir" ;; + esac + fi + + file=`$ECHO "X$file" | $Xsed -e 's%^.*/%%'` + file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'` + done + + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no + if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then + # special case for '.' + if test "$thisdir" = "."; then + thisdir=`pwd` + fi + # remove .libs from thisdir + case "$thisdir" in + *[\\/].libs ) thisdir=`$ECHO "X$thisdir" | $Xsed -e 's%[\\/][^\\/]*$%%'` ;; + .libs ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=`cd "$thisdir" && pwd` + test -n "$absdir" && thisdir="$absdir" + + program=lt-'snappy_unittest' + progdir="$thisdir/.libs" + + if test ! -f "$progdir/$program" || + { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \ + test "X$file" != "X$progdir/$program"; }; then + + file="$$-$program" + + if test ! -d "$progdir"; then + mkdir "$progdir" + else + rm -f "$progdir/$file" + fi + + # relink executable if necessary + if test -n "$relink_command"; then + if relink_command_output=`eval $relink_command 2>&1`; then : + else + echo "$relink_command_output" >&2 + rm -f "$progdir/$file" + exit 1 + fi + fi + + mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null || + { rm -f "$progdir/$program"; + mv -f "$progdir/$file" "$progdir/$program"; } + rm -f "$progdir/$file" + fi + + if test -f "$progdir/$program"; then + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + # Run the actual program with our arguments. + + exec "$progdir/$program" ${1+"$@"} + + $ECHO "$0: cannot exec $program $*" 1>&2 + exit 1 + fi + else + # The program doesn't exist. + $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2 + $ECHO "This script is just a wrapper for $program." 1>&2 + echo "See the libtool documentation for more information." 1>&2 + exit 1 + fi +fi diff --git a/snappy/snappy-1.0.5/snappy_unittest.cc b/snappy/snappy-1.0.5/snappy_unittest.cc new file mode 100644 index 00000000..f3b9c83c --- /dev/null +++ b/snappy/snappy-1.0.5/snappy_unittest.cc @@ -0,0 +1,1155 @@ +// Copyright 2005 and onwards Google Inc. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include + + +#include +#include +#include + +#include "snappy.h" +#include "snappy-internal.h" +#include "snappy-test.h" +#include "snappy-sinksource.h" + +DEFINE_int32(start_len, -1, + "Starting prefix size for testing (-1: just full file contents)"); +DEFINE_int32(end_len, -1, + "Starting prefix size for testing (-1: just full file contents)"); +DEFINE_int32(bytes, 10485760, + "How many bytes to compress/uncompress per file for timing"); + +DEFINE_bool(zlib, false, + "Run zlib compression (http://www.zlib.net)"); +DEFINE_bool(lzo, false, + "Run LZO compression (http://www.oberhumer.com/opensource/lzo/)"); +DEFINE_bool(quicklz, false, + "Run quickLZ compression (http://www.quicklz.com/)"); +DEFINE_bool(liblzf, false, + "Run libLZF compression " + "(http://www.goof.com/pcg/marc/liblzf.html)"); +DEFINE_bool(fastlz, false, + "Run FastLZ compression (http://www.fastlz.org/"); +DEFINE_bool(snappy, true, "Run snappy compression"); + + +DEFINE_bool(write_compressed, false, + "Write compressed versions of each file to .comp"); +DEFINE_bool(write_uncompressed, false, + "Write uncompressed versions of each file to .uncomp"); + +namespace snappy { + + +#ifdef HAVE_FUNC_MMAP + +// To test against code that reads beyond its input, this class copies a +// string to a newly allocated group of pages, the last of which +// is made unreadable via mprotect. Note that we need to allocate the +// memory with mmap(), as POSIX allows mprotect() only on memory allocated +// with mmap(), and some malloc/posix_memalign implementations expect to +// be able to read previously allocated memory while doing heap allocations. +class DataEndingAtUnreadablePage { + public: + explicit DataEndingAtUnreadablePage(const string& s) { + const size_t page_size = getpagesize(); + const size_t size = s.size(); + // Round up space for string to a multiple of page_size. + size_t space_for_string = (size + page_size - 1) & ~(page_size - 1); + alloc_size_ = space_for_string + page_size; + mem_ = mmap(NULL, alloc_size_, + PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + CHECK_NE(MAP_FAILED, mem_); + protected_page_ = reinterpret_cast(mem_) + space_for_string; + char* dst = protected_page_ - size; + memcpy(dst, s.data(), size); + data_ = dst; + size_ = size; + // Make guard page unreadable. + CHECK_EQ(0, mprotect(protected_page_, page_size, PROT_NONE)); + } + + ~DataEndingAtUnreadablePage() { + // Undo the mprotect. + CHECK_EQ(0, mprotect(protected_page_, getpagesize(), PROT_READ|PROT_WRITE)); + CHECK_EQ(0, munmap(mem_, alloc_size_)); + } + + const char* data() const { return data_; } + size_t size() const { return size_; } + + private: + size_t alloc_size_; + void* mem_; + char* protected_page_; + const char* data_; + size_t size_; +}; + +#else // HAVE_FUNC_MMAP + +// Fallback for systems without mmap. +typedef string DataEndingAtUnreadablePage; + +#endif + +enum CompressorType { + ZLIB, LZO, LIBLZF, QUICKLZ, FASTLZ, SNAPPY +}; + +const char* names[] = { + "ZLIB", "LZO", "LIBLZF", "QUICKLZ", "FASTLZ", "SNAPPY" +}; + +static size_t MinimumRequiredOutputSpace(size_t input_size, + CompressorType comp) { + switch (comp) { +#ifdef ZLIB_VERSION + case ZLIB: + return ZLib::MinCompressbufSize(input_size); +#endif // ZLIB_VERSION + +#ifdef LZO_VERSION + case LZO: + return input_size + input_size/64 + 16 + 3; +#endif // LZO_VERSION + +#ifdef LZF_VERSION + case LIBLZF: + return input_size; +#endif // LZF_VERSION + +#ifdef QLZ_VERSION_MAJOR + case QUICKLZ: + return input_size + 36000; // 36000 is used for scratch. +#endif // QLZ_VERSION_MAJOR + +#ifdef FASTLZ_VERSION + case FASTLZ: + return max(static_cast(ceil(input_size * 1.05)), 66); +#endif // FASTLZ_VERSION + + case SNAPPY: + return snappy::MaxCompressedLength(input_size); + + default: + LOG(FATAL) << "Unknown compression type number " << comp; + } +} + +// Returns true if we successfully compressed, false otherwise. +// +// If compressed_is_preallocated is set, do not resize the compressed buffer. +// This is typically what you want for a benchmark, in order to not spend +// time in the memory allocator. If you do set this flag, however, +// "compressed" must be preinitialized to at least MinCompressbufSize(comp) +// number of bytes, and may contain junk bytes at the end after return. +static bool Compress(const char* input, size_t input_size, CompressorType comp, + string* compressed, bool compressed_is_preallocated) { + if (!compressed_is_preallocated) { + compressed->resize(MinimumRequiredOutputSpace(input_size, comp)); + } + + switch (comp) { +#ifdef ZLIB_VERSION + case ZLIB: { + ZLib zlib; + uLongf destlen = compressed->size(); + int ret = zlib.Compress( + reinterpret_cast(string_as_array(compressed)), + &destlen, + reinterpret_cast(input), + input_size); + CHECK_EQ(Z_OK, ret); + if (!compressed_is_preallocated) { + compressed->resize(destlen); + } + return true; + } +#endif // ZLIB_VERSION + +#ifdef LZO_VERSION + case LZO: { + unsigned char* mem = new unsigned char[LZO1X_1_15_MEM_COMPRESS]; + lzo_uint destlen; + int ret = lzo1x_1_15_compress( + reinterpret_cast(input), + input_size, + reinterpret_cast(string_as_array(compressed)), + &destlen, + mem); + CHECK_EQ(LZO_E_OK, ret); + delete[] mem; + if (!compressed_is_preallocated) { + compressed->resize(destlen); + } + break; + } +#endif // LZO_VERSION + +#ifdef LZF_VERSION + case LIBLZF: { + int destlen = lzf_compress(input, + input_size, + string_as_array(compressed), + input_size); + if (destlen == 0) { + // lzf *can* cause lots of blowup when compressing, so they + // recommend to limit outsize to insize, and just not compress + // if it's bigger. Ideally, we'd just swap input and output. + compressed->assign(input, input_size); + destlen = input_size; + } + if (!compressed_is_preallocated) { + compressed->resize(destlen); + } + break; + } +#endif // LZF_VERSION + +#ifdef QLZ_VERSION_MAJOR + case QUICKLZ: { + qlz_state_compress *state_compress = new qlz_state_compress; + int destlen = qlz_compress(input, + string_as_array(compressed), + input_size, + state_compress); + delete state_compress; + CHECK_NE(0, destlen); + if (!compressed_is_preallocated) { + compressed->resize(destlen); + } + break; + } +#endif // QLZ_VERSION_MAJOR + +#ifdef FASTLZ_VERSION + case FASTLZ: { + // Use level 1 compression since we mostly care about speed. + int destlen = fastlz_compress_level( + 1, + input, + input_size, + string_as_array(compressed)); + if (!compressed_is_preallocated) { + compressed->resize(destlen); + } + CHECK_NE(destlen, 0); + break; + } +#endif // FASTLZ_VERSION + + case SNAPPY: { + size_t destlen; + snappy::RawCompress(input, input_size, + string_as_array(compressed), + &destlen); + CHECK_LE(destlen, snappy::MaxCompressedLength(input_size)); + if (!compressed_is_preallocated) { + compressed->resize(destlen); + } + break; + } + + + default: { + return false; // the asked-for library wasn't compiled in + } + } + return true; +} + +static bool Uncompress(const string& compressed, CompressorType comp, + int size, string* output) { + switch (comp) { +#ifdef ZLIB_VERSION + case ZLIB: { + output->resize(size); + ZLib zlib; + uLongf destlen = output->size(); + int ret = zlib.Uncompress( + reinterpret_cast(string_as_array(output)), + &destlen, + reinterpret_cast(compressed.data()), + compressed.size()); + CHECK_EQ(Z_OK, ret); + CHECK_EQ(static_cast(size), destlen); + break; + } +#endif // ZLIB_VERSION + +#ifdef LZO_VERSION + case LZO: { + output->resize(size); + lzo_uint destlen; + int ret = lzo1x_decompress( + reinterpret_cast(compressed.data()), + compressed.size(), + reinterpret_cast(string_as_array(output)), + &destlen, + NULL); + CHECK_EQ(LZO_E_OK, ret); + CHECK_EQ(static_cast(size), destlen); + break; + } +#endif // LZO_VERSION + +#ifdef LZF_VERSION + case LIBLZF: { + output->resize(size); + int destlen = lzf_decompress(compressed.data(), + compressed.size(), + string_as_array(output), + output->size()); + if (destlen == 0) { + // This error probably means we had decided not to compress, + // and thus have stored input in output directly. + output->assign(compressed.data(), compressed.size()); + destlen = compressed.size(); + } + CHECK_EQ(destlen, size); + break; + } +#endif // LZF_VERSION + +#ifdef QLZ_VERSION_MAJOR + case QUICKLZ: { + output->resize(size); + qlz_state_decompress *state_decompress = new qlz_state_decompress; + int destlen = qlz_decompress(compressed.data(), + string_as_array(output), + state_decompress); + delete state_decompress; + CHECK_EQ(destlen, size); + break; + } +#endif // QLZ_VERSION_MAJOR + +#ifdef FASTLZ_VERSION + case FASTLZ: { + output->resize(size); + int destlen = fastlz_decompress(compressed.data(), + compressed.length(), + string_as_array(output), + size); + CHECK_EQ(destlen, size); + break; + } +#endif // FASTLZ_VERSION + + case SNAPPY: { + snappy::RawUncompress(compressed.data(), compressed.size(), + string_as_array(output)); + break; + } + + + default: { + return false; // the asked-for library wasn't compiled in + } + } + return true; +} + +static void Measure(const char* data, + size_t length, + CompressorType comp, + int repeats, + int block_size) { + // Run tests a few time and pick median running times + static const int kRuns = 5; + double ctime[kRuns]; + double utime[kRuns]; + int compressed_size = 0; + + { + // Chop the input into blocks + int num_blocks = (length + block_size - 1) / block_size; + vector input(num_blocks); + vector input_length(num_blocks); + vector compressed(num_blocks); + vector output(num_blocks); + for (int b = 0; b < num_blocks; b++) { + int input_start = b * block_size; + int input_limit = min((b+1)*block_size, length); + input[b] = data+input_start; + input_length[b] = input_limit-input_start; + + // Pre-grow the output buffer so we don't measure string append time. + compressed[b].resize(MinimumRequiredOutputSpace(block_size, comp)); + } + + // First, try one trial compression to make sure the code is compiled in + if (!Compress(input[0], input_length[0], comp, &compressed[0], true)) { + LOG(WARNING) << "Skipping " << names[comp] << ": " + << "library not compiled in"; + return; + } + + for (int run = 0; run < kRuns; run++) { + CycleTimer ctimer, utimer; + + for (int b = 0; b < num_blocks; b++) { + // Pre-grow the output buffer so we don't measure string append time. + compressed[b].resize(MinimumRequiredOutputSpace(block_size, comp)); + } + + ctimer.Start(); + for (int b = 0; b < num_blocks; b++) + for (int i = 0; i < repeats; i++) + Compress(input[b], input_length[b], comp, &compressed[b], true); + ctimer.Stop(); + + // Compress once more, with resizing, so we don't leave junk + // at the end that will confuse the decompressor. + for (int b = 0; b < num_blocks; b++) { + Compress(input[b], input_length[b], comp, &compressed[b], false); + } + + for (int b = 0; b < num_blocks; b++) { + output[b].resize(input_length[b]); + } + + utimer.Start(); + for (int i = 0; i < repeats; i++) + for (int b = 0; b < num_blocks; b++) + Uncompress(compressed[b], comp, input_length[b], &output[b]); + utimer.Stop(); + + ctime[run] = ctimer.Get(); + utime[run] = utimer.Get(); + } + + compressed_size = 0; + for (int i = 0; i < compressed.size(); i++) { + compressed_size += compressed[i].size(); + } + } + + sort(ctime, ctime + kRuns); + sort(utime, utime + kRuns); + const int med = kRuns/2; + + float comp_rate = (length / ctime[med]) * repeats / 1048576.0; + float uncomp_rate = (length / utime[med]) * repeats / 1048576.0; + string x = names[comp]; + x += ":"; + string urate = (uncomp_rate >= 0) + ? StringPrintf("%.1f", uncomp_rate) + : string("?"); + printf("%-7s [b %dM] bytes %6d -> %6d %4.1f%% " + "comp %5.1f MB/s uncomp %5s MB/s\n", + x.c_str(), + block_size/(1<<20), + static_cast(length), static_cast(compressed_size), + (compressed_size * 100.0) / max(1, length), + comp_rate, + urate.c_str()); +} + + +static int VerifyString(const string& input) { + string compressed; + DataEndingAtUnreadablePage i(input); + const size_t written = snappy::Compress(i.data(), i.size(), &compressed); + CHECK_EQ(written, compressed.size()); + CHECK_LE(compressed.size(), + snappy::MaxCompressedLength(input.size())); + CHECK(snappy::IsValidCompressedBuffer(compressed.data(), compressed.size())); + + string uncompressed; + DataEndingAtUnreadablePage c(compressed); + CHECK(snappy::Uncompress(c.data(), c.size(), &uncompressed)); + CHECK_EQ(uncompressed, input); + return uncompressed.size(); +} + + +// Test that data compressed by a compressor that does not +// obey block sizes is uncompressed properly. +static void VerifyNonBlockedCompression(const string& input) { + if (input.length() > snappy::kBlockSize) { + // We cannot test larger blocks than the maximum block size, obviously. + return; + } + + string prefix; + Varint::Append32(&prefix, input.size()); + + // Setup compression table + snappy::internal::WorkingMemory wmem; + int table_size; + uint16* table = wmem.GetHashTable(input.size(), &table_size); + + // Compress entire input in one shot + string compressed; + compressed += prefix; + compressed.resize(prefix.size()+snappy::MaxCompressedLength(input.size())); + char* dest = string_as_array(&compressed) + prefix.size(); + char* end = snappy::internal::CompressFragment(input.data(), input.size(), + dest, table, table_size); + compressed.resize(end - compressed.data()); + + // Uncompress into string + string uncomp_str; + CHECK(snappy::Uncompress(compressed.data(), compressed.size(), &uncomp_str)); + CHECK_EQ(uncomp_str, input); + +} + +// Expand the input so that it is at least K times as big as block size +static string Expand(const string& input) { + static const int K = 3; + string data = input; + while (data.size() < K * snappy::kBlockSize) { + data += input; + } + return data; +} + +static int Verify(const string& input) { + VLOG(1) << "Verifying input of size " << input.size(); + + // Compress using string based routines + const int result = VerifyString(input); + + + VerifyNonBlockedCompression(input); + if (!input.empty()) { + VerifyNonBlockedCompression(Expand(input)); + } + + + return result; +} + +// This test checks to ensure that snappy doesn't coredump if it gets +// corrupted data. + +static bool IsValidCompressedBuffer(const string& c) { + return snappy::IsValidCompressedBuffer(c.data(), c.size()); +} +static bool Uncompress(const string& c, string* u) { + return snappy::Uncompress(c.data(), c.size(), u); +} + +TYPED_TEST(CorruptedTest, VerifyCorrupted) { + string source = "making sure we don't crash with corrupted input"; + VLOG(1) << source; + string dest; + TypeParam uncmp; + snappy::Compress(source.data(), source.size(), &dest); + + // Mess around with the data. It's hard to simulate all possible + // corruptions; this is just one example ... + CHECK_GT(dest.size(), 3); + dest[1]--; + dest[3]++; + // this really ought to fail. + CHECK(!IsValidCompressedBuffer(TypeParam(dest))); + CHECK(!Uncompress(TypeParam(dest), &uncmp)); + + // This is testing for a security bug - a buffer that decompresses to 100k + // but we lie in the snappy header and only reserve 0 bytes of memory :) + source.resize(100000); + for (int i = 0; i < source.length(); ++i) { + source[i] = 'A'; + } + snappy::Compress(source.data(), source.size(), &dest); + dest[0] = dest[1] = dest[2] = dest[3] = 0; + CHECK(!IsValidCompressedBuffer(TypeParam(dest))); + CHECK(!Uncompress(TypeParam(dest), &uncmp)); + + if (sizeof(void *) == 4) { + // Another security check; check a crazy big length can't DoS us with an + // over-allocation. + // Currently this is done only for 32-bit builds. On 64-bit builds, + // where 3 GB might be an acceptable allocation size, Uncompress() + // attempts to decompress, and sometimes causes the test to run out of + // memory. + dest[0] = dest[1] = dest[2] = dest[3] = 0xff; + // This decodes to a really large size, i.e., about 3 GB. + dest[4] = 'k'; + CHECK(!IsValidCompressedBuffer(TypeParam(dest))); + CHECK(!Uncompress(TypeParam(dest), &uncmp)); + } else { + LOG(WARNING) << "Crazy decompression lengths not checked on 64-bit build"; + } + + // This decodes to about 2 MB; much smaller, but should still fail. + dest[0] = dest[1] = dest[2] = 0xff; + dest[3] = 0x00; + CHECK(!IsValidCompressedBuffer(TypeParam(dest))); + CHECK(!Uncompress(TypeParam(dest), &uncmp)); + + // try reading stuff in from a bad file. + for (int i = 1; i <= 3; ++i) { + string data = ReadTestDataFile(StringPrintf("baddata%d.snappy", i).c_str()); + string uncmp; + // check that we don't return a crazy length + size_t ulen; + CHECK(!snappy::GetUncompressedLength(data.data(), data.size(), &ulen) + || (ulen < (1<<20))); + uint32 ulen2; + snappy::ByteArraySource source(data.data(), data.size()); + CHECK(!snappy::GetUncompressedLength(&source, &ulen2) || + (ulen2 < (1<<20))); + CHECK(!IsValidCompressedBuffer(TypeParam(data))); + CHECK(!Uncompress(TypeParam(data), &uncmp)); + } +} + +// Helper routines to construct arbitrary compressed strings. +// These mirror the compression code in snappy.cc, but are copied +// here so that we can bypass some limitations in the how snappy.cc +// invokes these routines. +static void AppendLiteral(string* dst, const string& literal) { + if (literal.empty()) return; + int n = literal.size() - 1; + if (n < 60) { + // Fit length in tag byte + dst->push_back(0 | (n << 2)); + } else { + // Encode in upcoming bytes + char number[4]; + int count = 0; + while (n > 0) { + number[count++] = n & 0xff; + n >>= 8; + } + dst->push_back(0 | ((59+count) << 2)); + *dst += string(number, count); + } + *dst += literal; +} + +static void AppendCopy(string* dst, int offset, int length) { + while (length > 0) { + // Figure out how much to copy in one shot + int to_copy; + if (length >= 68) { + to_copy = 64; + } else if (length > 64) { + to_copy = 60; + } else { + to_copy = length; + } + length -= to_copy; + + if ((to_copy < 12) && (offset < 2048)) { + assert(to_copy-4 < 8); // Must fit in 3 bits + dst->push_back(1 | ((to_copy-4) << 2) | ((offset >> 8) << 5)); + dst->push_back(offset & 0xff); + } else if (offset < 65536) { + dst->push_back(2 | ((to_copy-1) << 2)); + dst->push_back(offset & 0xff); + dst->push_back(offset >> 8); + } else { + dst->push_back(3 | ((to_copy-1) << 2)); + dst->push_back(offset & 0xff); + dst->push_back((offset >> 8) & 0xff); + dst->push_back((offset >> 16) & 0xff); + dst->push_back((offset >> 24) & 0xff); + } + } +} + +TEST(Snappy, SimpleTests) { + Verify(""); + Verify("a"); + Verify("ab"); + Verify("abc"); + + Verify("aaaaaaa" + string(16, 'b') + string("aaaaa") + "abc"); + Verify("aaaaaaa" + string(256, 'b') + string("aaaaa") + "abc"); + Verify("aaaaaaa" + string(2047, 'b') + string("aaaaa") + "abc"); + Verify("aaaaaaa" + string(65536, 'b') + string("aaaaa") + "abc"); + Verify("abcaaaaaaa" + string(65536, 'b') + string("aaaaa") + "abc"); +} + +// Verify max blowup (lots of four-byte copies) +TEST(Snappy, MaxBlowup) { + string input; + for (int i = 0; i < 20000; i++) { + ACMRandom rnd(i); + uint32 bytes = static_cast(rnd.Next()); + input.append(reinterpret_cast(&bytes), sizeof(bytes)); + } + for (int i = 19999; i >= 0; i--) { + ACMRandom rnd(i); + uint32 bytes = static_cast(rnd.Next()); + input.append(reinterpret_cast(&bytes), sizeof(bytes)); + } + Verify(input); +} + +TEST(Snappy, RandomData) { + ACMRandom rnd(FLAGS_test_random_seed); + + const int num_ops = 20000; + for (int i = 0; i < num_ops; i++) { + if ((i % 1000) == 0) { + VLOG(0) << "Random op " << i << " of " << num_ops; + } + + string x; + int len = rnd.Uniform(4096); + if (i < 100) { + len = 65536 + rnd.Uniform(65536); + } + while (x.size() < len) { + int run_len = 1; + if (rnd.OneIn(10)) { + run_len = rnd.Skewed(8); + } + char c = (i < 100) ? rnd.Uniform(256) : rnd.Skewed(3); + while (run_len-- > 0 && x.size() < len) { + x += c; + } + } + + Verify(x); + } +} + +TEST(Snappy, FourByteOffset) { + // The new compressor cannot generate four-byte offsets since + // it chops up the input into 32KB pieces. So we hand-emit the + // copy manually. + + // The two fragments that make up the input string. + string fragment1 = "012345689abcdefghijklmnopqrstuvwxyz"; + string fragment2 = "some other string"; + + // How many times each fragment is emitted. + const int n1 = 2; + const int n2 = 100000 / fragment2.size(); + const int length = n1 * fragment1.size() + n2 * fragment2.size(); + + string compressed; + Varint::Append32(&compressed, length); + + AppendLiteral(&compressed, fragment1); + string src = fragment1; + for (int i = 0; i < n2; i++) { + AppendLiteral(&compressed, fragment2); + src += fragment2; + } + AppendCopy(&compressed, src.size(), fragment1.size()); + src += fragment1; + CHECK_EQ(length, src.size()); + + string uncompressed; + CHECK(snappy::IsValidCompressedBuffer(compressed.data(), compressed.size())); + CHECK(snappy::Uncompress(compressed.data(), compressed.size(), &uncompressed)); + CHECK_EQ(uncompressed, src); +} + + +static bool CheckUncompressedLength(const string& compressed, + size_t* ulength) { + const bool result1 = snappy::GetUncompressedLength(compressed.data(), + compressed.size(), + ulength); + + snappy::ByteArraySource source(compressed.data(), compressed.size()); + uint32 length; + const bool result2 = snappy::GetUncompressedLength(&source, &length); + CHECK_EQ(result1, result2); + return result1; +} + +TEST(SnappyCorruption, TruncatedVarint) { + string compressed, uncompressed; + size_t ulength; + compressed.push_back('\xf0'); + CHECK(!CheckUncompressedLength(compressed, &ulength)); + CHECK(!snappy::IsValidCompressedBuffer(compressed.data(), compressed.size())); + CHECK(!snappy::Uncompress(compressed.data(), compressed.size(), + &uncompressed)); +} + +TEST(SnappyCorruption, UnterminatedVarint) { + string compressed, uncompressed; + size_t ulength; + compressed.push_back(128); + compressed.push_back(128); + compressed.push_back(128); + compressed.push_back(128); + compressed.push_back(128); + compressed.push_back(10); + CHECK(!CheckUncompressedLength(compressed, &ulength)); + CHECK(!snappy::IsValidCompressedBuffer(compressed.data(), compressed.size())); + CHECK(!snappy::Uncompress(compressed.data(), compressed.size(), + &uncompressed)); +} + +TEST(Snappy, ReadPastEndOfBuffer) { + // Check that we do not read past end of input + + // Make a compressed string that ends with a single-byte literal + string compressed; + Varint::Append32(&compressed, 1); + AppendLiteral(&compressed, "x"); + + string uncompressed; + DataEndingAtUnreadablePage c(compressed); + CHECK(snappy::Uncompress(c.data(), c.size(), &uncompressed)); + CHECK_EQ(uncompressed, string("x")); +} + +// Check for an infinite loop caused by a copy with offset==0 +TEST(Snappy, ZeroOffsetCopy) { + const char* compressed = "\x40\x12\x00\x00"; + // \x40 Length (must be > kMaxIncrementCopyOverflow) + // \x12\x00\x00 Copy with offset==0, length==5 + char uncompressed[100]; + EXPECT_FALSE(snappy::RawUncompress(compressed, 4, uncompressed)); +} + +TEST(Snappy, ZeroOffsetCopyValidation) { + const char* compressed = "\x05\x12\x00\x00"; + // \x05 Length + // \x12\x00\x00 Copy with offset==0, length==5 + EXPECT_FALSE(snappy::IsValidCompressedBuffer(compressed, 4)); +} + + +namespace { + +int TestFindMatchLength(const char* s1, const char *s2, unsigned length) { + return snappy::internal::FindMatchLength(s1, s2, s2 + length); +} + +} // namespace + +TEST(Snappy, FindMatchLength) { + // Exercise all different code paths through the function. + // 64-bit version: + + // Hit s1_limit in 64-bit loop, hit s1_limit in single-character loop. + EXPECT_EQ(6, TestFindMatchLength("012345", "012345", 6)); + EXPECT_EQ(11, TestFindMatchLength("01234567abc", "01234567abc", 11)); + + // Hit s1_limit in 64-bit loop, find a non-match in single-character loop. + EXPECT_EQ(9, TestFindMatchLength("01234567abc", "01234567axc", 9)); + + // Same, but edge cases. + EXPECT_EQ(11, TestFindMatchLength("01234567abc!", "01234567abc!", 11)); + EXPECT_EQ(11, TestFindMatchLength("01234567abc!", "01234567abc?", 11)); + + // Find non-match at once in first loop. + EXPECT_EQ(0, TestFindMatchLength("01234567xxxxxxxx", "?1234567xxxxxxxx", 16)); + EXPECT_EQ(1, TestFindMatchLength("01234567xxxxxxxx", "0?234567xxxxxxxx", 16)); + EXPECT_EQ(4, TestFindMatchLength("01234567xxxxxxxx", "01237654xxxxxxxx", 16)); + EXPECT_EQ(7, TestFindMatchLength("01234567xxxxxxxx", "0123456?xxxxxxxx", 16)); + + // Find non-match in first loop after one block. + EXPECT_EQ(8, TestFindMatchLength("abcdefgh01234567xxxxxxxx", + "abcdefgh?1234567xxxxxxxx", 24)); + EXPECT_EQ(9, TestFindMatchLength("abcdefgh01234567xxxxxxxx", + "abcdefgh0?234567xxxxxxxx", 24)); + EXPECT_EQ(12, TestFindMatchLength("abcdefgh01234567xxxxxxxx", + "abcdefgh01237654xxxxxxxx", 24)); + EXPECT_EQ(15, TestFindMatchLength("abcdefgh01234567xxxxxxxx", + "abcdefgh0123456?xxxxxxxx", 24)); + + // 32-bit version: + + // Short matches. + EXPECT_EQ(0, TestFindMatchLength("01234567", "?1234567", 8)); + EXPECT_EQ(1, TestFindMatchLength("01234567", "0?234567", 8)); + EXPECT_EQ(2, TestFindMatchLength("01234567", "01?34567", 8)); + EXPECT_EQ(3, TestFindMatchLength("01234567", "012?4567", 8)); + EXPECT_EQ(4, TestFindMatchLength("01234567", "0123?567", 8)); + EXPECT_EQ(5, TestFindMatchLength("01234567", "01234?67", 8)); + EXPECT_EQ(6, TestFindMatchLength("01234567", "012345?7", 8)); + EXPECT_EQ(7, TestFindMatchLength("01234567", "0123456?", 8)); + EXPECT_EQ(7, TestFindMatchLength("01234567", "0123456?", 7)); + EXPECT_EQ(7, TestFindMatchLength("01234567!", "0123456??", 7)); + + // Hit s1_limit in 32-bit loop, hit s1_limit in single-character loop. + EXPECT_EQ(10, TestFindMatchLength("xxxxxxabcd", "xxxxxxabcd", 10)); + EXPECT_EQ(10, TestFindMatchLength("xxxxxxabcd?", "xxxxxxabcd?", 10)); + EXPECT_EQ(13, TestFindMatchLength("xxxxxxabcdef", "xxxxxxabcdef", 13)); + + // Same, but edge cases. + EXPECT_EQ(12, TestFindMatchLength("xxxxxx0123abc!", "xxxxxx0123abc!", 12)); + EXPECT_EQ(12, TestFindMatchLength("xxxxxx0123abc!", "xxxxxx0123abc?", 12)); + + // Hit s1_limit in 32-bit loop, find a non-match in single-character loop. + EXPECT_EQ(11, TestFindMatchLength("xxxxxx0123abc", "xxxxxx0123axc", 13)); + + // Find non-match at once in first loop. + EXPECT_EQ(6, TestFindMatchLength("xxxxxx0123xxxxxxxx", + "xxxxxx?123xxxxxxxx", 18)); + EXPECT_EQ(7, TestFindMatchLength("xxxxxx0123xxxxxxxx", + "xxxxxx0?23xxxxxxxx", 18)); + EXPECT_EQ(8, TestFindMatchLength("xxxxxx0123xxxxxxxx", + "xxxxxx0132xxxxxxxx", 18)); + EXPECT_EQ(9, TestFindMatchLength("xxxxxx0123xxxxxxxx", + "xxxxxx012?xxxxxxxx", 18)); + + // Same, but edge cases. + EXPECT_EQ(6, TestFindMatchLength("xxxxxx0123", "xxxxxx?123", 10)); + EXPECT_EQ(7, TestFindMatchLength("xxxxxx0123", "xxxxxx0?23", 10)); + EXPECT_EQ(8, TestFindMatchLength("xxxxxx0123", "xxxxxx0132", 10)); + EXPECT_EQ(9, TestFindMatchLength("xxxxxx0123", "xxxxxx012?", 10)); + + // Find non-match in first loop after one block. + EXPECT_EQ(10, TestFindMatchLength("xxxxxxabcd0123xx", + "xxxxxxabcd?123xx", 16)); + EXPECT_EQ(11, TestFindMatchLength("xxxxxxabcd0123xx", + "xxxxxxabcd0?23xx", 16)); + EXPECT_EQ(12, TestFindMatchLength("xxxxxxabcd0123xx", + "xxxxxxabcd0132xx", 16)); + EXPECT_EQ(13, TestFindMatchLength("xxxxxxabcd0123xx", + "xxxxxxabcd012?xx", 16)); + + // Same, but edge cases. + EXPECT_EQ(10, TestFindMatchLength("xxxxxxabcd0123", "xxxxxxabcd?123", 14)); + EXPECT_EQ(11, TestFindMatchLength("xxxxxxabcd0123", "xxxxxxabcd0?23", 14)); + EXPECT_EQ(12, TestFindMatchLength("xxxxxxabcd0123", "xxxxxxabcd0132", 14)); + EXPECT_EQ(13, TestFindMatchLength("xxxxxxabcd0123", "xxxxxxabcd012?", 14)); +} + +TEST(Snappy, FindMatchLengthRandom) { + const int kNumTrials = 10000; + const int kTypicalLength = 10; + ACMRandom rnd(FLAGS_test_random_seed); + + for (int i = 0; i < kNumTrials; i++) { + string s, t; + char a = rnd.Rand8(); + char b = rnd.Rand8(); + while (!rnd.OneIn(kTypicalLength)) { + s.push_back(rnd.OneIn(2) ? a : b); + t.push_back(rnd.OneIn(2) ? a : b); + } + DataEndingAtUnreadablePage u(s); + DataEndingAtUnreadablePage v(t); + int matched = snappy::internal::FindMatchLength( + u.data(), v.data(), v.data() + t.size()); + if (matched == t.size()) { + EXPECT_EQ(s, t); + } else { + EXPECT_NE(s[matched], t[matched]); + for (int j = 0; j < matched; j++) { + EXPECT_EQ(s[j], t[j]); + } + } + } +} + + +static void CompressFile(const char* fname) { + string fullinput; + File::ReadFileToStringOrDie(fname, &fullinput); + + string compressed; + Compress(fullinput.data(), fullinput.size(), SNAPPY, &compressed, false); + + File::WriteStringToFileOrDie(compressed, + string(fname).append(".comp").c_str()); +} + +static void UncompressFile(const char* fname) { + string fullinput; + File::ReadFileToStringOrDie(fname, &fullinput); + + size_t uncompLength; + CHECK(CheckUncompressedLength(fullinput, &uncompLength)); + + string uncompressed; + uncompressed.resize(uncompLength); + CHECK(snappy::Uncompress(fullinput.data(), fullinput.size(), &uncompressed)); + + File::WriteStringToFileOrDie(uncompressed, + string(fname).append(".uncomp").c_str()); +} + +static void MeasureFile(const char* fname) { + string fullinput; + File::ReadFileToStringOrDie(fname, &fullinput); + printf("%-40s :\n", fname); + + int start_len = (FLAGS_start_len < 0) ? fullinput.size() : FLAGS_start_len; + int end_len = fullinput.size(); + if (FLAGS_end_len >= 0) { + end_len = min(fullinput.size(), FLAGS_end_len); + } + for (int len = start_len; len <= end_len; len++) { + const char* const input = fullinput.data(); + int repeats = (FLAGS_bytes + len) / (len + 1); + if (FLAGS_zlib) Measure(input, len, ZLIB, repeats, 1024<<10); + if (FLAGS_lzo) Measure(input, len, LZO, repeats, 1024<<10); + if (FLAGS_liblzf) Measure(input, len, LIBLZF, repeats, 1024<<10); + if (FLAGS_quicklz) Measure(input, len, QUICKLZ, repeats, 1024<<10); + if (FLAGS_fastlz) Measure(input, len, FASTLZ, repeats, 1024<<10); + if (FLAGS_snappy) Measure(input, len, SNAPPY, repeats, 4096<<10); + + // For block-size based measurements + if (0 && FLAGS_snappy) { + Measure(input, len, SNAPPY, repeats, 8<<10); + Measure(input, len, SNAPPY, repeats, 16<<10); + Measure(input, len, SNAPPY, repeats, 32<<10); + Measure(input, len, SNAPPY, repeats, 64<<10); + Measure(input, len, SNAPPY, repeats, 256<<10); + Measure(input, len, SNAPPY, repeats, 1024<<10); + } + } +} + +static struct { + const char* label; + const char* filename; +} files[] = { + { "html", "html" }, + { "urls", "urls.10K" }, + { "jpg", "house.jpg" }, + { "pdf", "mapreduce-osdi-1.pdf" }, + { "html4", "html_x_4" }, + { "cp", "cp.html" }, + { "c", "fields.c" }, + { "lsp", "grammar.lsp" }, + { "xls", "kennedy.xls" }, + { "txt1", "alice29.txt" }, + { "txt2", "asyoulik.txt" }, + { "txt3", "lcet10.txt" }, + { "txt4", "plrabn12.txt" }, + { "bin", "ptt5" }, + { "sum", "sum" }, + { "man", "xargs.1" }, + { "pb", "geo.protodata" }, + { "gaviota", "kppkn.gtb" }, +}; + +static void BM_UFlat(int iters, int arg) { + StopBenchmarkTiming(); + + // Pick file to process based on "arg" + CHECK_GE(arg, 0); + CHECK_LT(arg, ARRAYSIZE(files)); + string contents = ReadTestDataFile(files[arg].filename); + + string zcontents; + snappy::Compress(contents.data(), contents.size(), &zcontents); + char* dst = new char[contents.size()]; + + SetBenchmarkBytesProcessed(static_cast(iters) * + static_cast(contents.size())); + SetBenchmarkLabel(files[arg].label); + StartBenchmarkTiming(); + while (iters-- > 0) { + CHECK(snappy::RawUncompress(zcontents.data(), zcontents.size(), dst)); + } + StopBenchmarkTiming(); + + delete[] dst; +} +BENCHMARK(BM_UFlat)->DenseRange(0, 17); + +static void BM_UValidate(int iters, int arg) { + StopBenchmarkTiming(); + + // Pick file to process based on "arg" + CHECK_GE(arg, 0); + CHECK_LT(arg, ARRAYSIZE(files)); + string contents = ReadTestDataFile(files[arg].filename); + + string zcontents; + snappy::Compress(contents.data(), contents.size(), &zcontents); + + SetBenchmarkBytesProcessed(static_cast(iters) * + static_cast(contents.size())); + SetBenchmarkLabel(files[arg].label); + StartBenchmarkTiming(); + while (iters-- > 0) { + CHECK(snappy::IsValidCompressedBuffer(zcontents.data(), zcontents.size())); + } + StopBenchmarkTiming(); +} +BENCHMARK(BM_UValidate)->DenseRange(0, 4); + + +static void BM_ZFlat(int iters, int arg) { + StopBenchmarkTiming(); + + // Pick file to process based on "arg" + CHECK_GE(arg, 0); + CHECK_LT(arg, ARRAYSIZE(files)); + string contents = ReadTestDataFile(files[arg].filename); + + char* dst = new char[snappy::MaxCompressedLength(contents.size())]; + + SetBenchmarkBytesProcessed(static_cast(iters) * + static_cast(contents.size())); + StartBenchmarkTiming(); + + size_t zsize = 0; + while (iters-- > 0) { + snappy::RawCompress(contents.data(), contents.size(), dst, &zsize); + } + StopBenchmarkTiming(); + const double compression_ratio = + static_cast(zsize) / std::max(1, contents.size()); + SetBenchmarkLabel(StringPrintf("%s (%.2f %%)", + files[arg].label, 100.0 * compression_ratio)); + VLOG(0) << StringPrintf("compression for %s: %zd -> %zd bytes", + files[arg].label, contents.size(), zsize); + delete[] dst; +} +BENCHMARK(BM_ZFlat)->DenseRange(0, 17); + + +} // namespace snappy + + +int main(int argc, char** argv) { + InitGoogle(argv[0], &argc, &argv, true); + File::Init(); + RunSpecifiedBenchmarks(); + + + if (argc >= 2) { + for (int arg = 1; arg < argc; arg++) { + if (FLAGS_write_compressed) { + CompressFile(argv[arg]); + } else if (FLAGS_write_uncompressed) { + UncompressFile(argv[arg]); + } else { + MeasureFile(argv[arg]); + } + } + return 0; + } + + return RUN_ALL_TESTS(); +} diff --git a/snappy/snappy-1.0.5/stamp-h1 b/snappy/snappy-1.0.5/stamp-h1 new file mode 100644 index 00000000..4547fe1b --- /dev/null +++ b/snappy/snappy-1.0.5/stamp-h1 @@ -0,0 +1 @@ +timestamp for config.h diff --git a/snappy/snappy-1.0.5/testdata/alice29.txt b/snappy/snappy-1.0.5/testdata/alice29.txt new file mode 100644 index 00000000..70336552 --- /dev/null +++ b/snappy/snappy-1.0.5/testdata/alice29.txt @@ -0,0 +1,3609 @@ + + + + + ALICE'S ADVENTURES IN WONDERLAND + + Lewis Carroll + + THE MILLENNIUM FULCRUM EDITION 2.9 + + + + + CHAPTER I + + Down the Rabbit-Hole + + + Alice was beginning to get very tired of sitting by her sister +on the bank, and of having nothing to do: once or twice she had +peeped into the book her sister was reading, but it had no +pictures or conversations in it, `and what is the use of a book,' +thought Alice `without pictures or conversation?' + + So she was considering in her own mind (as well as she could, +for the hot day made her feel very sleepy and stupid), whether +the pleasure of making a daisy-chain would be worth the trouble +of getting up and picking the daisies, when suddenly a White +Rabbit with pink eyes ran close by her. + + There was nothing so VERY remarkable in that; nor did Alice +think it so VERY much out of the way to hear the Rabbit say to +itself, `Oh dear! Oh dear! I shall be late!' (when she thought +it over afterwards, it occurred to her that she ought to have +wondered at this, but at the time it all seemed quite natural); +but when the Rabbit actually TOOK A WATCH OUT OF ITS WAISTCOAT- +POCKET, and looked at it, and then hurried on, Alice started to +her feet, for it flashed across her mind that she had never +before seen a rabbit with either a waistcoat-pocket, or a watch to +take out of it, and burning with curiosity, she ran across the +field after it, and fortunately was just in time to see it pop +down a large rabbit-hole under the hedge. + + In another moment down went Alice after it, never once +considering how in the world she was to get out again. + + The rabbit-hole went straight on like a tunnel for some way, +and then dipped suddenly down, so suddenly that Alice had not a +moment to think about stopping herself before she found herself +falling down a very deep well. + + Either the well was very deep, or she fell very slowly, for she +had plenty of time as she went down to look about her and to +wonder what was going to happen next. First, she tried to look +down and make out what she was coming to, but it was too dark to +see anything; then she looked at the sides of the well, and +noticed that they were filled with cupboards and book-shelves; +here and there she saw maps and pictures hung upon pegs. She +took down a jar from one of the shelves as she passed; it was +labelled `ORANGE MARMALADE', but to her great disappointment it +was empty: she did not like to drop the jar for fear of killing +somebody, so managed to put it into one of the cupboards as she +fell past it. + + `Well!' thought Alice to herself, `after such a fall as this, I +shall think nothing of tumbling down stairs! How brave they'll +all think me at home! Why, I wouldn't say anything about it, +even if I fell off the top of the house!' (Which was very likely +true.) + + Down, down, down. Would the fall NEVER come to an end! `I +wonder how many miles I've fallen by this time?' she said aloud. +`I must be getting somewhere near the centre of the earth. Let +me see: that would be four thousand miles down, I think--' (for, +you see, Alice had learnt several things of this sort in her +lessons in the schoolroom, and though this was not a VERY good +opportunity for showing off her knowledge, as there was no one to +listen to her, still it was good practice to say it over) `--yes, +that's about the right distance--but then I wonder what Latitude +or Longitude I've got to?' (Alice had no idea what Latitude was, +or Longitude either, but thought they were nice grand words to +say.) + + Presently she began again. `I wonder if I shall fall right +THROUGH the earth! How funny it'll seem to come out among the +people that walk with their heads downward! The Antipathies, I +think--' (she was rather glad there WAS no one listening, this +time, as it didn't sound at all the right word) `--but I shall +have to ask them what the name of the country is, you know. +Please, Ma'am, is this New Zealand or Australia?' (and she tried +to curtsey as she spoke--fancy CURTSEYING as you're falling +through the air! Do you think you could manage it?) `And what +an ignorant little girl she'll think me for asking! No, it'll +never do to ask: perhaps I shall see it written up somewhere.' + + Down, down, down. There was nothing else to do, so Alice soon +began talking again. `Dinah'll miss me very much to-night, I +should think!' (Dinah was the cat.) `I hope they'll remember +her saucer of milk at tea-time. Dinah my dear! I wish you were +down here with me! There are no mice in the air, I'm afraid, but +you might catch a bat, and that's very like a mouse, you know. +But do cats eat bats, I wonder?' And here Alice began to get +rather sleepy, and went on saying to herself, in a dreamy sort of +way, `Do cats eat bats? Do cats eat bats?' and sometimes, `Do +bats eat cats?' for, you see, as she couldn't answer either +question, it didn't much matter which way she put it. She felt +that she was dozing off, and had just begun to dream that she +was walking hand in hand with Dinah, and saying to her very +earnestly, `Now, Dinah, tell me the truth: did you ever eat a +bat?' when suddenly, thump! thump! down she came upon a heap of +sticks and dry leaves, and the fall was over. + + Alice was not a bit hurt, and she jumped up on to her feet in a +moment: she looked up, but it was all dark overhead; before her +was another long passage, and the White Rabbit was still in +sight, hurrying down it. There was not a moment to be lost: +away went Alice like the wind, and was just in time to hear it +say, as it turned a corner, `Oh my ears and whiskers, how late +it's getting!' She was close behind it when she turned the +corner, but the Rabbit was no longer to be seen: she found +herself in a long, low hall, which was lit up by a row of lamps +hanging from the roof. + + There were doors all round the hall, but they were all locked; +and when Alice had been all the way down one side and up the +other, trying every door, she walked sadly down the middle, +wondering how she was ever to get out again. + + Suddenly she came upon a little three-legged table, all made of +solid glass; there was nothing on it except a tiny golden key, +and Alice's first thought was that it might belong to one of the +doors of the hall; but, alas! either the locks were too large, or +the key was too small, but at any rate it would not open any of +them. However, on the second time round, she came upon a low +curtain she had not noticed before, and behind it was a little +door about fifteen inches high: she tried the little golden key +in the lock, and to her great delight it fitted! + + Alice opened the door and found that it led into a small +passage, not much larger than a rat-hole: she knelt down and +looked along the passage into the loveliest garden you ever saw. +How she longed to get out of that dark hall, and wander about +among those beds of bright flowers and those cool fountains, but +she could not even get her head though the doorway; `and even if +my head would go through,' thought poor Alice, `it would be of +very little use without my shoulders. Oh, how I wish +I could shut up like a telescope! I think I could, if I only +know how to begin.' For, you see, so many out-of-the-way things +had happened lately, that Alice had begun to think that very few +things indeed were really impossible. + + There seemed to be no use in waiting by the little door, so she +went back to the table, half hoping she might find another key on +it, or at any rate a book of rules for shutting people up like +telescopes: this time she found a little bottle on it, (`which +certainly was not here before,' said Alice,) and round the neck +of the bottle was a paper label, with the words `DRINK ME' +beautifully printed on it in large letters. + + It was all very well to say `Drink me,' but the wise little +Alice was not going to do THAT in a hurry. `No, I'll look +first,' she said, `and see whether it's marked "poison" or not'; +for she had read several nice little histories about children who +had got burnt, and eaten up by wild beasts and other unpleasant +things, all because they WOULD not remember the simple rules +their friends had taught them: such as, that a red-hot poker +will burn you if you hold it too long; and that if you cut your +finger VERY deeply with a knife, it usually bleeds; and she had +never forgotten that, if you drink much from a bottle marked +`poison,' it is almost certain to disagree with you, sooner or +later. + + However, this bottle was NOT marked `poison,' so Alice ventured +to taste it, and finding it very nice, (it had, in fact, a sort +of mixed flavour of cherry-tart, custard, pine-apple, roast +turkey, toffee, and hot buttered toast,) she very soon finished +it off. + + * * * * * * * + + * * * * * * + + * * * * * * * + + `What a curious feeling!' said Alice; `I must be shutting up +like a telescope.' + + And so it was indeed: she was now only ten inches high, and +her face brightened up at the thought that she was now the right +size for going though the little door into that lovely garden. +First, however, she waited for a few minutes to see if she was +going to shrink any further: she felt a little nervous about +this; `for it might end, you know,' said Alice to herself, `in my +going out altogether, like a candle. I wonder what I should be +like then?' And she tried to fancy what the flame of a candle is +like after the candle is blown out, for she could not remember +ever having seen such a thing. + + After a while, finding that nothing more happened, she decided +on going into the garden at once; but, alas for poor Alice! when +she got to the door, she found he had forgotten the little golden +key, and when she went back to the table for it, she found she +could not possibly reach it: she could see it quite plainly +through the glass, and she tried her best to climb up one of the +legs of the table, but it was too slippery; and when she had +tired herself out with trying, the poor little thing sat down and +cried. + + `Come, there's no use in crying like that!' said Alice to +herself, rather sharply; `I advise you to leave off this minute!' +She generally gave herself very good advice, (though she very +seldom followed it), and sometimes she scolded herself so +severely as to bring tears into her eyes; and once she remembered +trying to box her own ears for having cheated herself in a game +of croquet she was playing against herself, for this curious +child was very fond of pretending to be two people. `But it's no +use now,' thought poor Alice, `to pretend to be two people! Why, +there's hardly enough of me left to make ONE respectable +person!' + + Soon her eye fell on a little glass box that was lying under +the table: she opened it, and found in it a very small cake, on +which the words `EAT ME' were beautifully marked in currants. +`Well, I'll eat it,' said Alice, `and if it makes me grow larger, +I can reach the key; and if it makes me grow smaller, I can creep +under the door; so either way I'll get into the garden, and I +don't care which happens!' + + She ate a little bit, and said anxiously to herself, `Which +way? Which way?', holding her hand on the top of her head to +feel which way it was growing, and she was quite surprised to +find that she remained the same size: to be sure, this generally +happens when one eats cake, but Alice had got so much into the +way of expecting nothing but out-of-the-way things to happen, +that it seemed quite dull and stupid for life to go on in the +common way. + + So she set to work, and very soon finished off the cake. + + * * * * * * * + + * * * * * * + + * * * * * * * + + + + + CHAPTER II + + The Pool of Tears + + + `Curiouser and curiouser!' cried Alice (she was so much +surprised, that for the moment she quite forgot how to speak good +English); `now I'm opening out like the largest telescope that +ever was! Good-bye, feet!' (for when she looked down at her +feet, they seemed to be almost out of sight, they were getting so +far off). `Oh, my poor little feet, I wonder who will put on +your shoes and stockings for you now, dears? I'm sure _I_ shan't +be able! I shall be a great deal too far off to trouble myself +about you: you must manage the best way you can; --but I must be +kind to them,' thought Alice, `or perhaps they won't walk the +way I want to go! Let me see: I'll give them a new pair of +boots every Christmas.' + + And she went on planning to herself how she would manage it. +`They must go by the carrier,' she thought; `and how funny it'll +seem, sending presents to one's own feet! And how odd the +directions will look! + + ALICE'S RIGHT FOOT, ESQ. + HEARTHRUG, + NEAR THE FENDER, + (WITH ALICE'S LOVE). + +Oh dear, what nonsense I'm talking!' + + Just then her head struck against the roof of the hall: in +fact she was now more than nine feet high, and she at once took +up the little golden key and hurried off to the garden door. + + Poor Alice! It was as much as she could do, lying down on one +side, to look through into the garden with one eye; but to get +through was more hopeless than ever: she sat down and began to +cry again. + + `You ought to be ashamed of yourself,' said Alice, `a great +girl like you,' (she might well say this), `to go on crying in +this way! Stop this moment, I tell you!' But she went on all +the same, shedding gallons of tears, until there was a large pool +all round her, about four inches deep and reaching half down the +hall. + + After a time she heard a little pattering of feet in the +distance, and she hastily dried her eyes to see what was coming. +It was the White Rabbit returning, splendidly dressed, with a +pair of white kid gloves in one hand and a large fan in the +other: he came trotting along in a great hurry, muttering to +himself as he came, `Oh! the Duchess, the Duchess! Oh! won't she +be savage if I've kept her waiting!' Alice felt so desperate +that she was ready to ask help of any one; so, when the Rabbit +came near her, she began, in a low, timid voice, `If you please, +sir--' The Rabbit started violently, dropped the white kid +gloves and the fan, and skurried away into the darkness as hard +as he could go. + + Alice took up the fan and gloves, and, as the hall was very +hot, she kept fanning herself all the time she went on talking: +`Dear, dear! How queer everything is to-day! And yesterday +things went on just as usual. I wonder if I've been changed in +the night? Let me think: was I the same when I got up this +morning? I almost think I can remember feeling a little +different. But if I'm not the same, the next question is, Who in +the world am I? Ah, THAT'S the great puzzle!' And she began +thinking over all the children she knew that were of the same age +as herself, to see if she could have been changed for any of +them. + + `I'm sure I'm not Ada,' she said, `for her hair goes in such +long ringlets, and mine doesn't go in ringlets at all; and I'm +sure I can't be Mabel, for I know all sorts of things, and she, +oh! she knows such a very little! Besides, SHE'S she, and I'm I, +and--oh dear, how puzzling it all is! I'll try if I know all the +things I used to know. Let me see: four times five is twelve, +and four times six is thirteen, and four times seven is--oh dear! +I shall never get to twenty at that rate! However, the +Multiplication Table doesn't signify: let's try Geography. +London is the capital of Paris, and Paris is the capital of Rome, +and Rome--no, THAT'S all wrong, I'm certain! I must have been +changed for Mabel! I'll try and say "How doth the little--"' +and she crossed her hands on her lap as if she were saying lessons, +and began to repeat it, but her voice sounded hoarse and +strange, and the words did not come the same as they used to do:-- + + `How doth the little crocodile + Improve his shining tail, + And pour the waters of the Nile + On every golden scale! + + `How cheerfully he seems to grin, + How neatly spread his claws, + And welcome little fishes in + With gently smiling jaws!' + + `I'm sure those are not the right words,' said poor Alice, and +her eyes filled with tears again as she went on, `I must be Mabel +after all, and I shall have to go and live in that poky little +house, and have next to no toys to play with, and oh! ever so +many lessons to learn! No, I've made up my mind about it; if I'm +Mabel, I'll stay down here! It'll be no use their putting their +heads down and saying "Come up again, dear!" I shall only look +up and say "Who am I then? Tell me that first, and then, if I +like being that person, I'll come up: if not, I'll stay down +here till I'm somebody else"--but, oh dear!' cried Alice, with a +sudden burst of tears, `I do wish they WOULD put their heads +down! I am so VERY tired of being all alone here!' + + As she said this she looked down at her hands, and was +surprised to see that she had put on one of the Rabbit's little +white kid gloves while she was talking. `How CAN I have done +that?' she thought. `I must be growing small again.' She got up +and went to the table to measure herself by it, and found that, +as nearly as she could guess, she was now about two feet high, +and was going on shrinking rapidly: she soon found out that the +cause of this was the fan she was holding, and she dropped it +hastily, just in time to avoid shrinking away altogether. + +`That WAS a narrow escape!' said Alice, a good deal frightened at +the sudden change, but very glad to find herself still in +existence; `and now for the garden!' and she ran with all speed +back to the little door: but, alas! the little door was shut +again, and the little golden key was lying on the glass table as +before, `and things are worse than ever,' thought the poor child, +`for I never was so small as this before, never! And I declare +it's too bad, that it is!' + + As she said these words her foot slipped, and in another +moment, splash! she was up to her chin in salt water. He first +idea was that she had somehow fallen into the sea, `and in that +case I can go back by railway,' she said to herself. (Alice had +been to the seaside once in her life, and had come to the general +conclusion, that wherever you go to on the English coast you find +a number of bathing machines in the sea, some children digging in +the sand with wooden spades, then a row of lodging houses, and +behind them a railway station.) However, she soon made out that +she was in the pool of tears which she had wept when she was nine +feet high. + + `I wish I hadn't cried so much!' said Alice, as she swam about, +trying to find her way out. `I shall be punished for it now, I +suppose, by being drowned in my own tears! That WILL be a queer +thing, to be sure! However, everything is queer to-day.' + + Just then she heard something splashing about in the pool a +little way off, and she swam nearer to make out what it was: at +first she thought it must be a walrus or hippopotamus, but then +she remembered how small she was now, and she soon made out that +it was only a mouse that had slipped in like herself. + + `Would it be of any use, now,' thought Alice, `to speak to this +mouse? Everything is so out-of-the-way down here, that I should +think very likely it can talk: at any rate, there's no harm in +trying.' So she began: `O Mouse, do you know the way out of +this pool? I am very tired of swimming about here, O Mouse!' +(Alice thought this must be the right way of speaking to a mouse: +she had never done such a thing before, but she remembered having +seen in her brother's Latin Grammar, `A mouse--of a mouse--to a +mouse--a mouse--O mouse!' The Mouse looked at her rather +inquisitively, and seemed to her to wink with one of its little +eyes, but it said nothing. + + `Perhaps it doesn't understand English,' thought Alice; `I +daresay it's a French mouse, come over with William the +Conqueror.' (For, with all her knowledge of history, Alice had +no very clear notion how long ago anything had happened.) So she +began again: `Ou est ma chatte?' which was the first sentence in +her French lesson-book. The Mouse gave a sudden leap out of the +water, and seemed to quiver all over with fright. `Oh, I beg +your pardon!' cried Alice hastily, afraid that she had hurt the +poor animal's feelings. `I quite forgot you didn't like cats.' + + `Not like cats!' cried the Mouse, in a shrill, passionate +voice. `Would YOU like cats if you were me?' + + `Well, perhaps not,' said Alice in a soothing tone: `don't be +angry about it. And yet I wish I could show you our cat Dinah: +I think you'd take a fancy to cats if you could only see her. +She is such a dear quiet thing,' Alice went on, half to herself, +as she swam lazily about in the pool, `and she sits purring so +nicely by the fire, licking her paws and washing her face--and +she is such a nice soft thing to nurse--and she's such a capital +one for catching mice--oh, I beg your pardon!' cried Alice again, +for this time the Mouse was bristling all over, and she felt +certain it must be really offended. `We won't talk about her any +more if you'd rather not.' + + `We indeed!' cried the Mouse, who was trembling down to the end +of his tail. `As if I would talk on such a subject! Our family +always HATED cats: nasty, low, vulgar things! Don't let me hear +the name again!' + + `I won't indeed!' said Alice, in a great hurry to change the +subject of conversation. `Are you--are you fond--of--of dogs?' +The Mouse did not answer, so Alice went on eagerly: `There is +such a nice little dog near our house I should like to show you! +A little bright-eyed terrier, you know, with oh, such long curly +brown hair! And it'll fetch things when you throw them, and +it'll sit up and beg for its dinner, and all sorts of things--I +can't remember half of them--and it belongs to a farmer, you +know, and he says it's so useful, it's worth a hundred pounds! +He says it kills all the rats and--oh dear!' cried Alice in a +sorrowful tone, `I'm afraid I've offended it again!' For the +Mouse was swimming away from her as hard as it could go, and +making quite a commotion in the pool as it went. + + So she called softly after it, `Mouse dear! Do come back +again, and we won't talk about cats or dogs either, if you don't +like them!' When the Mouse heard this, it turned round and swam +slowly back to her: its face was quite pale (with passion, Alice +thought), and it said in a low trembling voice, `Let us get to +the shore, and then I'll tell you my history, and you'll +understand why it is I hate cats and dogs.' + + It was high time to go, for the pool was getting quite crowded +with the birds and animals that had fallen into it: there were a +Duck and a Dodo, a Lory and an Eaglet, and several other curious +creatures. Alice led the way, and the whole party swam to the +shore. + + + + CHAPTER III + + A Caucus-Race and a Long Tale + + + They were indeed a queer-looking party that assembled on the +bank--the birds with draggled feathers, the animals with their +fur clinging close to them, and all dripping wet, cross, and +uncomfortable. + + The first question of course was, how to get dry again: they +had a consultation about this, and after a few minutes it seemed +quite natural to Alice to find herself talking familiarly with +them, as if she had known them all her life. Indeed, she had +quite a long argument with the Lory, who at last turned sulky, +and would only say, `I am older than you, and must know better'; +and this Alice would not allow without knowing how old it was, +and, as the Lory positively refused to tell its age, there was no +more to be said. + + At last the Mouse, who seemed to be a person of authority among +them, called out, `Sit down, all of you, and listen to me! I'LL +soon make you dry enough!' They all sat down at once, in a large +ring, with the Mouse in the middle. Alice kept her eyes +anxiously fixed on it, for she felt sure she would catch a bad +cold if she did not get dry very soon. + + `Ahem!' said the Mouse with an important air, `are you all ready? +This is the driest thing I know. Silence all round, if you please! +"William the Conqueror, whose cause was favoured by the pope, was +soon submitted to by the English, who wanted leaders, and had been +of late much accustomed to usurpation and conquest. Edwin and +Morcar, the earls of Mercia and Northumbria--"' + + `Ugh!' said the Lory, with a shiver. + + `I beg your pardon!' said the Mouse, frowning, but very +politely: `Did you speak?' + + `Not I!' said the Lory hastily. + + `I thought you did,' said the Mouse. `--I proceed. "Edwin and +Morcar, the earls of Mercia and Northumbria, declared for him: +and even Stigand, the patriotic archbishop of Canterbury, found +it advisable--"' + + `Found WHAT?' said the Duck. + + `Found IT,' the Mouse replied rather crossly: `of course you +know what "it" means.' + + `I know what "it" means well enough, when I find a thing,' said +the Duck: `it's generally a frog or a worm. The question is, +what did the archbishop find?' + + The Mouse did not notice this question, but hurriedly went on, +`"--found it advisable to go with Edgar Atheling to meet William +and offer him the crown. William's conduct at first was +moderate. But the insolence of his Normans--" How are you +getting on now, my dear?' it continued, turning to Alice as it +spoke. + + `As wet as ever,' said Alice in a melancholy tone: `it doesn't +seem to dry me at all.' + + `In that case,' said the Dodo solemnly, rising to its feet, `I +move that the meeting adjourn, for the immediate adoption of more +energetic remedies--' + + `Speak English!' said the Eaglet. `I don't know the meaning of +half those long words, and, what's more, I don't believe you do +either!' And the Eaglet bent down its head to hide a smile: +some of the other birds tittered audibly. + + `What I was going to say,' said the Dodo in an offended tone, +`was, that the best thing to get us dry would be a Caucus-race.' + + `What IS a Caucus-race?' said Alice; not that she wanted much +to know, but the Dodo had paused as if it thought that SOMEBODY +ought to speak, and no one else seemed inclined to say anything. + + `Why,' said the Dodo, `the best way to explain it is to do it.' +(And, as you might like to try the thing yourself, some winter +day, I will tell you how the Dodo managed it.) + + First it marked out a race-course, in a sort of circle, (`the +exact shape doesn't matter,' it said,) and then all the party +were placed along the course, here and there. There was no `One, +two, three, and away,' but they began running when they liked, +and left off when they liked, so that it was not easy to know +when the race was over. However, when they had been running half +an hour or so, and were quite dry again, the Dodo suddenly called +out `The race is over!' and they all crowded round it, panting, +and asking, `But who has won?' + + This question the Dodo could not answer without a great deal of +thought, and it sat for a long time with one finger pressed upon +its forehead (the position in which you usually see Shakespeare, +in the pictures of him), while the rest waited in silence. At +last the Dodo said, `EVERYBODY has won, and all must have +prizes.' + + `But who is to give the prizes?' quite a chorus of voices +asked. + + `Why, SHE, of course,' said the Dodo, pointing to Alice with +one finger; and the whole party at once crowded round her, +calling out in a confused way, `Prizes! Prizes!' + + Alice had no idea what to do, and in despair she put her hand +in her pocket, and pulled out a box of comfits, (luckily the salt +water had not got into it), and handed them round as prizes. +There was exactly one a-piece all round. + + `But she must have a prize herself, you know,' said the Mouse. + + `Of course,' the Dodo replied very gravely. `What else have +you got in your pocket?' he went on, turning to Alice. + + `Only a thimble,' said Alice sadly. + + `Hand it over here,' said the Dodo. + + Then they all crowded round her once more, while the Dodo +solemnly presented the thimble, saying `We beg your acceptance of +this elegant thimble'; and, when it had finished this short +speech, they all cheered. + + Alice thought the whole thing very absurd, but they all looked +so grave that she did not dare to laugh; and, as she could not +think of anything to say, she simply bowed, and took the thimble, +looking as solemn as she could. + + The next thing was to eat the comfits: this caused some noise +and confusion, as the large birds complained that they could not +taste theirs, and the small ones choked and had to be patted on +the back. However, it was over at last, and they sat down again +in a ring, and begged the Mouse to tell them something more. + + `You promised to tell me your history, you know,' said Alice, +`and why it is you hate--C and D,' she added in a whisper, half +afraid that it would be offended again. + + `Mine is a long and a sad tale!' said the Mouse, turning to +Alice, and sighing. + + `It IS a long tail, certainly,' said Alice, looking down with +wonder at the Mouse's tail; `but why do you call it sad?' And +she kept on puzzling about it while the Mouse was speaking, so +that her idea of the tale was something like this:-- + + `Fury said to a + mouse, That he + met in the + house, + "Let us + both go to + law: I will + prosecute + YOU. --Come, + I'll take no + denial; We + must have a + trial: For + really this + morning I've + nothing + to do." + Said the + mouse to the + cur, "Such + a trial, + dear Sir, + With + no jury + or judge, + would be + wasting + our + breath." + "I'll be + judge, I'll + be jury," + Said + cunning + old Fury: + "I'll + try the + whole + cause, + and + condemn + you + to + death."' + + + `You are not attending!' said the Mouse to Alice severely. +`What are you thinking of?' + + `I beg your pardon,' said Alice very humbly: `you had got to +the fifth bend, I think?' + + `I had NOT!' cried the Mouse, sharply and very angrily. + + `A knot!' said Alice, always ready to make herself useful, and +looking anxiously about her. `Oh, do let me help to undo it!' + + `I shall do nothing of the sort,' said the Mouse, getting up +and walking away. `You insult me by talking such nonsense!' + + `I didn't mean it!' pleaded poor Alice. `But you're so easily +offended, you know!' + + The Mouse only growled in reply. + + `Please come back and finish your story!' Alice called after +it; and the others all joined in chorus, `Yes, please do!' but +the Mouse only shook its head impatiently, and walked a little +quicker. + + `What a pity it wouldn't stay!' sighed the Lory, as soon as it +was quite out of sight; and an old Crab took the opportunity of +saying to her daughter `Ah, my dear! Let this be a lesson to you +never to lose YOUR temper!' `Hold your tongue, Ma!' said the +young Crab, a little snappishly. `You're enough to try the +patience of an oyster!' + + `I wish I had our Dinah here, I know I do!' said Alice aloud, +addressing nobody in particular. `She'd soon fetch it back!' + + `And who is Dinah, if I might venture to ask the question?' +said the Lory. + + Alice replied eagerly, for she was always ready to talk about +her pet: `Dinah's our cat. And she's such a capital one for +catching mice you can't think! And oh, I wish you could see her +after the birds! Why, she'll eat a little bird as soon as look +at it!' + + This speech caused a remarkable sensation among the party. +Some of the birds hurried off at once: one the old Magpie began +wrapping itself up very carefully, remarking, `I really must be +getting home; the night-air doesn't suit my throat!' and a Canary +called out in a trembling voice to its children, `Come away, my +dears! It's high time you were all in bed!' On various pretexts +they all moved off, and Alice was soon left alone. + + `I wish I hadn't mentioned Dinah!' she said to herself in a +melancholy tone. `Nobody seems to like her, down here, and I'm +sure she's the best cat in the world! Oh, my dear Dinah! I +wonder if I shall ever see you any more!' And here poor Alice +began to cry again, for she felt very lonely and low-spirited. +In a little while, however, she again heard a little pattering of +footsteps in the distance, and she looked up eagerly, half hoping +that the Mouse had changed his mind, and was coming back to +finish his story. + + + + CHAPTER IV + + The Rabbit Sends in a Little Bill + + + It was the White Rabbit, trotting slowly back again, and +looking anxiously about as it went, as if it had lost something; +and she heard it muttering to itself `The Duchess! The Duchess! +Oh my dear paws! Oh my fur and whiskers! She'll get me +executed, as sure as ferrets are ferrets! Where CAN I have +dropped them, I wonder?' Alice guessed in a moment that it was +looking for the fan and the pair of white kid gloves, and she +very good-naturedly began hunting about for them, but they were +nowhere to be seen--everything seemed to have changed since her +swim in the pool, and the great hall, with the glass table and +the little door, had vanished completely. + + Very soon the Rabbit noticed Alice, as she went hunting about, +and called out to her in an angry tone, `Why, Mary Ann, what ARE +you doing out here? Run home this moment, and fetch me a pair of +gloves and a fan! Quick, now!' And Alice was so much frightened +that she ran off at once in the direction it pointed to, without +trying to explain the mistake it had made. + + `He took me for his housemaid,' she said to herself as she ran. +`How surprised he'll be when he finds out who I am! But I'd +better take him his fan and gloves--that is, if I can find them.' +As she said this, she came upon a neat little house, on the door +of which was a bright brass plate with the name `W. RABBIT' +engraved upon it. She went in without knocking, and hurried +upstairs, in great fear lest she should meet the real Mary Ann, +and be turned out of the house before she had found the fan and +gloves. + + `How queer it seems,' Alice said to herself, `to be going +messages for a rabbit! I suppose Dinah'll be sending me on +messages next!' And she began fancying the sort of thing that +would happen: `"Miss Alice! Come here directly, and get ready +for your walk!" "Coming in a minute, nurse! But I've got to see +that the mouse doesn't get out." Only I don't think,' Alice went +on, `that they'd let Dinah stop in the house if it began ordering +people about like that!' + + By this time she had found her way into a tidy little room with +a table in the window, and on it (as she had hoped) a fan and two +or three pairs of tiny white kid gloves: she took up the fan and +a pair of the gloves, and was just going to leave the room, when +her eye fell upon a little bottle that stood near the looking- +glass. There was no label this time with the words `DRINK ME,' +but nevertheless she uncorked it and put it to her lips. `I know +SOMETHING interesting is sure to happen,' she said to herself, +`whenever I eat or drink anything; so I'll just see what this +bottle does. I do hope it'll make me grow large again, for +really I'm quite tired of being such a tiny little thing!' + + It did so indeed, and much sooner than she had expected: +before she had drunk half the bottle, she found her head pressing +against the ceiling, and had to stoop to save her neck from being +broken. She hastily put down the bottle, saying to herself +`That's quite enough--I hope I shan't grow any more--As it is, I +can't get out at the door--I do wish I hadn't drunk quite so +much!' + + Alas! it was too late to wish that! She went on growing, and +growing, and very soon had to kneel down on the floor: in +another minute there was not even room for this, and she tried +the effect of lying down with one elbow against the door, and the +other arm curled round her head. Still she went on growing, and, +as a last resource, she put one arm out of the window, and one +foot up the chimney, and said to herself `Now I can do no more, +whatever happens. What WILL become of me?' + + Luckily for Alice, the little magic bottle had now had its full +effect, and she grew no larger: still it was very uncomfortable, +and, as there seemed to be no sort of chance of her ever getting +out of the room again, no wonder she felt unhappy. + + `It was much pleasanter at home,' thought poor Alice, `when one +wasn't always growing larger and smaller, and being ordered about +by mice and rabbits. I almost wish I hadn't gone down that +rabbit-hole--and yet--and yet--it's rather curious, you know, +this sort of life! I do wonder what CAN have happened to me! +When I used to read fairy-tales, I fancied that kind of thing +never happened, and now here I am in the middle of one! There +ought to be a book written about me, that there ought! And when +I grow up, I'll write one--but I'm grown up now,' she added in a +sorrowful tone; `at least there's no room to grow up any more +HERE.' + + `But then,' thought Alice, `shall I NEVER get any older than I +am now? That'll be a comfort, one way--never to be an old woman- +-but then--always to have lessons to learn! Oh, I shouldn't like +THAT!' + + `Oh, you foolish Alice!' she answered herself. `How can you +learn lessons in here? Why, there's hardly room for YOU, and no +room at all for any lesson-books!' + + And so she went on, taking first one side and then the other, +and making quite a conversation of it altogether; but after a few +minutes she heard a voice outside, and stopped to listen. + + `Mary Ann! Mary Ann!' said the voice. `Fetch me my gloves +this moment!' Then came a little pattering of feet on the +stairs. Alice knew it was the Rabbit coming to look for her, and +she trembled till she shook the house, quite forgetting that she +was now about a thousand times as large as the Rabbit, and had no +reason to be afraid of it. + + Presently the Rabbit came up to the door, and tried to open it; +but, as the door opened inwards, and Alice's elbow was pressed +hard against it, that attempt proved a failure. Alice heard it +say to itself `Then I'll go round and get in at the window.' + + `THAT you won't' thought Alice, and, after waiting till she +fancied she heard the Rabbit just under the window, she suddenly +spread out her hand, and made a snatch in the air. She did not +get hold of anything, but she heard a little shriek and a fall, +and a crash of broken glass, from which she concluded that it was +just possible it had fallen into a cucumber-frame, or something +of the sort. + + Next came an angry voice--the Rabbit's--`Pat! Pat! Where are +you?' And then a voice she had never heard before, `Sure then +I'm here! Digging for apples, yer honour!' + + `Digging for apples, indeed!' said the Rabbit angrily. `Here! +Come and help me out of THIS!' (Sounds of more broken glass.) + + `Now tell me, Pat, what's that in the window?' + + `Sure, it's an arm, yer honour!' (He pronounced it `arrum.') + + `An arm, you goose! Who ever saw one that size? Why, it +fills the whole window!' + + `Sure, it does, yer honour: but it's an arm for all that.' + + `Well, it's got no business there, at any rate: go and take it +away!' + + There was a long silence after this, and Alice could only hear +whispers now and then; such as, `Sure, I don't like it, yer +honour, at all, at all!' `Do as I tell you, you coward!' and at +last she spread out her hand again, and made another snatch in +the air. This time there were TWO little shrieks, and more +sounds of broken glass. `What a number of cucumber-frames there +must be!' thought Alice. `I wonder what they'll do next! As for +pulling me out of the window, I only wish they COULD! I'm sure I +don't want to stay in here any longer!' + + She waited for some time without hearing anything more: at +last came a rumbling of little cartwheels, and the sound of a +good many voice all talking together: she made out the words: +`Where's the other ladder?--Why, I hadn't to bring but one; +Bill's got the other--Bill! fetch it here, lad!--Here, put 'em up +at this corner--No, tie 'em together first--they don't reach half +high enough yet--Oh! they'll do well enough; don't be particular- +-Here, Bill! catch hold of this rope--Will the roof bear?--Mind +that loose slate--Oh, it's coming down! Heads below!' (a loud +crash)--`Now, who did that?--It was Bill, I fancy--Who's to go +down the chimney?--Nay, I shan't! YOU do it!--That I won't, +then!--Bill's to go down--Here, Bill! the master says you're to +go down the chimney!' + + `Oh! So Bill's got to come down the chimney, has he?' said +Alice to herself. `Shy, they seem to put everything upon Bill! +I wouldn't be in Bill's place for a good deal: this fireplace is +narrow, to be sure; but I THINK I can kick a little!' + + She drew her foot as far down the chimney as she could, and +waited till she heard a little animal (she couldn't guess of what +sort it was) scratching and scrambling about in the chimney close +above her: then, saying to herself `This is Bill,' she gave one +sharp kick, and waited to see what would happen next. + + The first thing she heard was a general chorus of `There goes +Bill!' then the Rabbit's voice along--`Catch him, you by the +hedge!' then silence, and then another confusion of voices--`Hold +up his head--Brandy now--Don't choke him--How was it, old fellow? +What happened to you? Tell us all about it!' + + Last came a little feeble, squeaking voice, (`That's Bill,' +thought Alice,) `Well, I hardly know--No more, thank ye; I'm +better now--but I'm a deal too flustered to tell you--all I know +is, something comes at me like a Jack-in-the-box, and up I goes +like a sky-rocket!' + + `So you did, old fellow!' said the others. + + `We must burn the house down!' said the Rabbit's voice; and +Alice called out as loud as she could, `If you do. I'll set +Dinah at you!' + + There was a dead silence instantly, and Alice thought to +herself, `I wonder what they WILL do next! If they had any +sense, they'd take the roof off.' After a minute or two, they +began moving about again, and Alice heard the Rabbit say, `A +barrowful will do, to begin with.' + + `A barrowful of WHAT?' thought Alice; but she had not long to +doubt, for the next moment a shower of little pebbles came +rattling in at the window, and some of them hit her in the face. +`I'll put a stop to this,' she said to herself, and shouted out, +`You'd better not do that again!' which produced another dead +silence. + + Alice noticed with some surprise that the pebbles were all +turning into little cakes as they lay on the floor, and a bright +idea came into her head. `If I eat one of these cakes,' she +thought, `it's sure to make SOME change in my size; and as it +can't possibly make me larger, it must make me smaller, I +suppose.' + + So she swallowed one of the cakes, and was delighted to find +that she began shrinking directly. As soon as she was small +enough to get through the door, she ran out of the house, and +found quite a crowd of little animals and birds waiting outside. +The poor little Lizard, Bill, was in the middle, being held up by +two guinea-pigs, who were giving it something out of a bottle. +They all made a rush at Alice the moment she appeared; but she +ran off as hard as she could, and soon found herself safe in a +thick wood. + + `The first thing I've got to do,' said Alice to herself, as she +wandered about in the wood, `is to grow to my right size again; +and the second thing is to find my way into that lovely garden. +I think that will be the best plan.' + + It sounded an excellent plan, no doubt, and very neatly and +simply arranged; the only difficulty was, that she had not the +smallest idea how to set about it; and while she was peering +about anxiously among the trees, a little sharp bark just over +her head made her look up in a great hurry. + + An enormous puppy was looking down at her with large round +eyes, and feebly stretching out one paw, trying to touch her. +`Poor little thing!' said Alice, in a coaxing tone, and she tried +hard to whistle to it; but she was terribly frightened all the +time at the thought that it might be hungry, in which case it +would be very likely to eat her up in spite of all her coaxing. + + Hardly knowing what she did, she picked up a little bit of +stick, and held it out to the puppy; whereupon the puppy jumped +into the air off all its feet at once, with a yelp of delight, +and rushed at the stick, and made believe to worry it; then Alice +dodged behind a great thistle, to keep herself from being run +over; and the moment she appeared on the other side, the puppy +made another rush at the stick, and tumbled head over heels in +its hurry to get hold of it; then Alice, thinking it was very +like having a game of play with a cart-horse, and expecting every +moment to be trampled under its feet, ran round the thistle +again; then the puppy began a series of short charges at the +stick, running a very little way forwards each time and a long +way back, and barking hoarsely all the while, till at last it sat +down a good way off, panting, with its tongue hanging out of its +mouth, and its great eyes half shut. + + This seemed to Alice a good opportunity for making her escape; +so she set off at once, and ran till she was quite tired and out +of breath, and till the puppy's bark sounded quite faint in the +distance. + + `And yet what a dear little puppy it was!' said Alice, as she +leant against a buttercup to rest herself, and fanned herself +with one of the leaves: `I should have liked teaching it tricks +very much, if--if I'd only been the right size to do it! Oh +dear! I'd nearly forgotten that I've got to grow up again! Let +me see--how IS it to be managed? I suppose I ought to eat or +drink something or other; but the great question is, what?' + + The great question certainly was, what? Alice looked all round +her at the flowers and the blades of grass, but she did not see +anything that looked like the right thing to eat or drink under +the circumstances. There was a large mushroom growing near her, +about the same height as herself; and when she had looked under +it, and on both sides of it, and behind it, it occurred to her +that she might as well look and see what was on the top of it. + + She stretched herself up on tiptoe, and peeped over the edge of +the mushroom, and her eyes immediately met those of a large +caterpillar, that was sitting on the top with its arms folded, +quietly smoking a long hookah, and taking not the smallest notice +of her or of anything else. + + + + CHAPTER V + + Advice from a Caterpillar + + + The Caterpillar and Alice looked at each other for some time in +silence: at last the Caterpillar took the hookah out of its +mouth, and addressed her in a languid, sleepy voice. + + `Who are YOU?' said the Caterpillar. + + This was not an encouraging opening for a conversation. Alice +replied, rather shyly, `I--I hardly know, sir, just at present-- +at least I know who I WAS when I got up this morning, but I think +I must have been changed several times since then.' + + `What do you mean by that?' said the Caterpillar sternly. +`Explain yourself!' + + `I can't explain MYSELF, I'm afraid, sir' said Alice, `because +I'm not myself, you see.' + + `I don't see,' said the Caterpillar. + + `I'm afraid I can't put it more clearly,' Alice replied very +politely, `for I can't understand it myself to begin with; and +being so many different sizes in a day is very confusing.' + + `It isn't,' said the Caterpillar. + + `Well, perhaps you haven't found it so yet,' said Alice; `but +when you have to turn into a chrysalis--you will some day, you +know--and then after that into a butterfly, I should think you'll +feel it a little queer, won't you?' + + `Not a bit,' said the Caterpillar. + + `Well, perhaps your feelings may be different,' said Alice; +`all I know is, it would feel very queer to ME.' + + `You!' said the Caterpillar contemptuously. `Who are YOU?' + + Which brought them back again to the beginning of the +conversation. Alice felt a little irritated at the Caterpillar's +making such VERY short remarks, and she drew herself up and said, +very gravely, `I think, you ought to tell me who YOU are, first.' + + `Why?' said the Caterpillar. + + Here was another puzzling question; and as Alice could not +think of any good reason, and as the Caterpillar seemed to be in +a VERY unpleasant state of mind, she turned away. + + `Come back!' the Caterpillar called after her. `I've something +important to say!' + + This sounded promising, certainly: Alice turned and came back +again. + + `Keep your temper,' said the Caterpillar. + + `Is that all?' said Alice, swallowing down her anger as well as +she could. + + `No,' said the Caterpillar. + + Alice thought she might as well wait, as she had nothing else +to do, and perhaps after all it might tell her something worth +hearing. For some minutes it puffed away without speaking, but +at last it unfolded its arms, took the hookah out of its mouth +again, and said, `So you think you're changed, do you?' + + `I'm afraid I am, sir,' said Alice; `I can't remember things as +I used--and I don't keep the same size for ten minutes together!' + + `Can't remember WHAT things?' said the Caterpillar. + + `Well, I've tried to say "HOW DOTH THE LITTLE BUSY BEE," but it +all came different!' Alice replied in a very melancholy voice. + + `Repeat, "YOU ARE OLD, FATHER WILLIAM,"' said the Caterpillar. + + Alice folded her hands, and began:-- + + `You are old, Father William,' the young man said, + `And your hair has become very white; + And yet you incessantly stand on your head-- + Do you think, at your age, it is right?' + + `In my youth,' Father William replied to his son, + `I feared it might injure the brain; + But, now that I'm perfectly sure I have none, + Why, I do it again and again.' + + `You are old,' said the youth, `as I mentioned before, + And have grown most uncommonly fat; + Yet you turned a back-somersault in at the door-- + Pray, what is the reason of that?' + + `In my youth,' said the sage, as he shook his grey locks, + `I kept all my limbs very supple + By the use of this ointment--one shilling the box-- + Allow me to sell you a couple?' + + `You are old,' said the youth, `and your jaws are too weak + For anything tougher than suet; + Yet you finished the goose, with the bones and the beak-- + Pray how did you manage to do it?' + + `In my youth,' said his father, `I took to the law, + And argued each case with my wife; + And the muscular strength, which it gave to my jaw, + Has lasted the rest of my life.' + + `You are old,' said the youth, `one would hardly suppose + That your eye was as steady as ever; + Yet you balanced an eel on the end of your nose-- + What made you so awfully clever?' + + `I have answered three questions, and that is enough,' + Said his father; `don't give yourself airs! + Do you think I can listen all day to such stuff? + Be off, or I'll kick you down stairs!' + + + `That is not said right,' said the Caterpillar. + + `Not QUITE right, I'm afraid,' said Alice, timidly; `some of the +words have got altered.' + + `It is wrong from beginning to end,' said the Caterpillar +decidedly, and there was silence for some minutes. + + The Caterpillar was the first to speak. + + `What size do you want to be?' it asked. + + `Oh, I'm not particular as to size,' Alice hastily replied; +`only one doesn't like changing so often, you know.' + + `I DON'T know,' said the Caterpillar. + + Alice said nothing: she had never been so much contradicted in +her life before, and she felt that she was losing her temper. + + `Are you content now?' said the Caterpillar. + + `Well, I should like to be a LITTLE larger, sir, if you +wouldn't mind,' said Alice: `three inches is such a wretched +height to be.' + + `It is a very good height indeed!' said the Caterpillar +angrily, rearing itself upright as it spoke (it was exactly three +inches high). + + `But I'm not used to it!' pleaded poor Alice in a piteous tone. +And she thought of herself, `I wish the creatures wouldn't be so +easily offended!' + + `You'll get used to it in time,' said the Caterpillar; and it +put the hookah into its mouth and began smoking again. + + This time Alice waited patiently until it chose to speak again. +In a minute or two the Caterpillar took the hookah out of its +mouth and yawned once or twice, and shook itself. Then it got +down off the mushroom, and crawled away in the grass, merely +remarking as it went, `One side will make you grow taller, and +the other side will make you grow shorter.' + + `One side of WHAT? The other side of WHAT?' thought Alice to +herself. + + `Of the mushroom,' said the Caterpillar, just as if she had +asked it aloud; and in another moment it was out of sight. + + Alice remained looking thoughtfully at the mushroom for a +minute, trying to make out which were the two sides of it; and as +it was perfectly round, she found this a very difficult question. +However, at last she stretched her arms round it as far as they +would go, and broke off a bit of the edge with each hand. + + `And now which is which?' she said to herself, and nibbled a +little of the right-hand bit to try the effect: the next moment +she felt a violent blow underneath her chin: it had struck her +foot! + + She was a good deal frightened by this very sudden change, but +she felt that there was no time to be lost, as she was shrinking +rapidly; so she set to work at once to eat some of the other bit. +Her chin was pressed so closely against her foot, that there was +hardly room to open her mouth; but she did it at last, and +managed to swallow a morsel of the lefthand bit. + + + * * * * * * * + + * * * * * * + + * * * * * * * + + `Come, my head's free at last!' said Alice in a tone of +delight, which changed into alarm in another moment, when she +found that her shoulders were nowhere to be found: all she could +see, when she looked down, was an immense length of neck, which +seemed to rise like a stalk out of a sea of green leaves that lay +far below her. + + `What CAN all that green stuff be?' said Alice. `And where +HAVE my shoulders got to? And oh, my poor hands, how is it I +can't see you?' She was moving them about as she spoke, but no +result seemed to follow, except a little shaking among the +distant green leaves. + + As there seemed to be no chance of getting her hands up to her +head, she tried to get her head down to them, and was delighted +to find that her neck would bend about easily in any direction, +like a serpent. She had just succeeded in curving it down into a +graceful zigzag, and was going to dive in among the leaves, which +she found to be nothing but the tops of the trees under which she +had been wandering, when a sharp hiss made her draw back in a +hurry: a large pigeon had flown into her face, and was beating +her violently with its wings. + + `Serpent!' screamed the Pigeon. + + `I'm NOT a serpent!' said Alice indignantly. `Let me alone!' + + `Serpent, I say again!' repeated the Pigeon, but in a more +subdued tone, and added with a kind of sob, `I've tried every +way, and nothing seems to suit them!' + + `I haven't the least idea what you're talking about,' said +Alice. + + `I've tried the roots of trees, and I've tried banks, and I've +tried hedges,' the Pigeon went on, without attending to her; `but +those serpents! There's no pleasing them!' + + Alice was more and more puzzled, but she thought there was no +use in saying anything more till the Pigeon had finished. + + `As if it wasn't trouble enough hatching the eggs,' said the +Pigeon; `but I must be on the look-out for serpents night and +day! Why, I haven't had a wink of sleep these three weeks!' + + `I'm very sorry you've been annoyed,' said Alice, who was +beginning to see its meaning. + + `And just as I'd taken the highest tree in the wood,' continued +the Pigeon, raising its voice to a shriek, `and just as I was +thinking I should be free of them at last, they must needs come +wriggling down from the sky! Ugh, Serpent!' + + `But I'm NOT a serpent, I tell you!' said Alice. `I'm a--I'm +a--' + + `Well! WHAT are you?' said the Pigeon. `I can see you're +trying to invent something!' + + `I--I'm a little girl,' said Alice, rather doubtfully, as she +remembered the number of changes she had gone through that day. + + `A likely story indeed!' said the Pigeon in a tone of the +deepest contempt. `I've seen a good many little girls in my +time, but never ONE with such a neck as that! No, no! You're a +serpent; and there's no use denying it. I suppose you'll be +telling me next that you never tasted an egg!' + + `I HAVE tasted eggs, certainly,' said Alice, who was a very +truthful child; `but little girls eat eggs quite as much as +serpents do, you know.' + + `I don't believe it,' said the Pigeon; `but if they do, why +then they're a kind of serpent, that's all I can say.' + + This was such a new idea to Alice, that she was quite silent +for a minute or two, which gave the Pigeon the opportunity of +adding, `You're looking for eggs, I know THAT well enough; and +what does it matter to me whether you're a little girl or a +serpent?' + + `It matters a good deal to ME,' said Alice hastily; `but I'm +not looking for eggs, as it happens; and if I was, I shouldn't +want YOURS: I don't like them raw.' + + `Well, be off, then!' said the Pigeon in a sulky tone, as it +settled down again into its nest. Alice crouched down among the +trees as well as she could, for her neck kept getting entangled +among the branches, and every now and then she had to stop and +untwist it. After a while she remembered that she still held the +pieces of mushroom in her hands, and she set to work very +carefully, nibbling first at one and then at the other, and +growing sometimes taller and sometimes shorter, until she had +succeeded in bringing herself down to her usual height. + + It was so long since she had been anything near the right size, +that it felt quite strange at first; but she got used to it in a +few minutes, and began talking to herself, as usual. `Come, +there's half my plan done now! How puzzling all these changes +are! I'm never sure what I'm going to be, from one minute to +another! However, I've got back to my right size: the next +thing is, to get into that beautiful garden--how IS that to be +done, I wonder?' As she said this, she came suddenly upon an +open place, with a little house in it about four feet high. +`Whoever lives there,' thought Alice, `it'll never do to come +upon them THIS size: why, I should frighten them out of their +wits!' So she began nibbling at the righthand bit again, and did +not venture to go near the house till she had brought herself +down to nine inches high. + + + + CHAPTER VI + + Pig and Pepper + + + For a minute or two she stood looking at the house, and +wondering what to do next, when suddenly a footman in livery came +running out of the wood--(she considered him to be a footman +because he was in livery: otherwise, judging by his face only, +she would have called him a fish)--and rapped loudly at the door +with his knuckles. It was opened by another footman in livery, +with a round face, and large eyes like a frog; and both footmen, +Alice noticed, had powdered hair that curled all over their +heads. She felt very curious to know what it was all about, and +crept a little way out of the wood to listen. + + The Fish-Footman began by producing from under his arm a great +letter, nearly as large as himself, and this he handed over to +the other, saying, in a solemn tone, `For the Duchess. An +invitation from the Queen to play croquet.' The Frog-Footman +repeated, in the same solemn tone, only changing the order of the +words a little, `From the Queen. An invitation for the Duchess +to play croquet.' + + Then they both bowed low, and their curls got entangled +together. + + Alice laughed so much at this, that she had to run back into +the wood for fear of their hearing her; and when she next peeped +out the Fish-Footman was gone, and the other was sitting on the +ground near the door, staring stupidly up into the sky. + + Alice went timidly up to the door, and knocked. + + `There's no sort of use in knocking,' said the Footman, `and +that for two reasons. First, because I'm on the same side of the +door as you are; secondly, because they're making such a noise +inside, no one could possibly hear you.' And certainly there was +a most extraordinary noise going on within--a constant howling +and sneezing, and every now and then a great crash, as if a dish +or kettle had been broken to pieces. + + `Please, then,' said Alice, `how am I to get in?' + + `There might be some sense in your knocking,' the Footman went +on without attending to her, `if we had the door between us. For +instance, if you were INSIDE, you might knock, and I could let +you out, you know.' He was looking up into the sky all the time +he was speaking, and this Alice thought decidedly uncivil. `But +perhaps he can't help it,' she said to herself; `his eyes are so +VERY nearly at the top of his head. But at any rate he might +answer questions.--How am I to get in?' she repeated, aloud. + + `I shall sit here,' the Footman remarked, `till tomorrow--' + + At this moment the door of the house opened, and a large plate +came skimming out, straight at the Footman's head: it just +grazed his nose, and broke to pieces against one of the trees +behind him. + + `--or next day, maybe,' the Footman continued in the same tone, +exactly as if nothing had happened. + + `How am I to get in?' asked Alice again, in a louder tone. + + `ARE you to get in at all?' said the Footman. `That's the +first question, you know.' + + It was, no doubt: only Alice did not like to be told so. +`It's really dreadful,' she muttered to herself, `the way all the +creatures argue. It's enough to drive one crazy!' + + The Footman seemed to think this a good opportunity for +repeating his remark, with variations. `I shall sit here,' he +said, `on and off, for days and days.' + + `But what am I to do?' said Alice. + + `Anything you like,' said the Footman, and began whistling. + + `Oh, there's no use in talking to him,' said Alice desperately: +`he's perfectly idiotic!' And she opened the door and went in. + + The door led right into a large kitchen, which was full of +smoke from one end to the other: the Duchess was sitting on a +three-legged stool in the middle, nursing a baby; the cook was +leaning over the fire, stirring a large cauldron which seemed to +be full of soup. + + `There's certainly too much pepper in that soup!' Alice said to +herself, as well as she could for sneezing. + + There was certainly too much of it in the air. Even the +Duchess sneezed occasionally; and as for the baby, it was +sneezing and howling alternately without a moment's pause. The +only things in the kitchen that did not sneeze, were the cook, +and a large cat which was sitting on the hearth and grinning from +ear to ear. + + `Please would you tell me,' said Alice, a little timidly, for +she was not quite sure whether it was good manners for her to +speak first, `why your cat grins like that?' + + `It's a Cheshire cat,' said the Duchess, `and that's why. +Pig!' + + She said the last word with such sudden violence that Alice +quite jumped; but she saw in another moment that it was addressed +to the baby, and not to her, so she took courage, and went on +again:-- + + `I didn't know that Cheshire cats always grinned; in fact, I +didn't know that cats COULD grin.' + + `They all can,' said the Duchess; `and most of 'em do.' + + `I don't know of any that do,' Alice said very politely, +feeling quite pleased to have got into a conversation. + + `You don't know much,' said the Duchess; `and that's a fact.' + + Alice did not at all like the tone of this remark, and thought +it would be as well to introduce some other subject of +conversation. While she was trying to fix on one, the cook took +the cauldron of soup off the fire, and at once set to work +throwing everything within her reach at the Duchess and the baby +--the fire-irons came first; then followed a shower of saucepans, +plates, and dishes. The Duchess took no notice of them even when +they hit her; and the baby was howling so much already, that it +was quite impossible to say whether the blows hurt it or not. + + `Oh, PLEASE mind what you're doing!' cried Alice, jumping up +and down in an agony of terror. `Oh, there goes his PRECIOUS +nose'; as an unusually large saucepan flew close by it, and very +nearly carried it off. + + `If everybody minded their own business,' the Duchess said in a +hoarse growl, `the world would go round a deal faster than it +does.' + + `Which would NOT be an advantage,' said Alice, who felt very +glad to get an opportunity of showing off a little of her +knowledge. `Just think of what work it would make with the day +and night! You see the earth takes twenty-four hours to turn +round on its axis--' + + `Talking of axes,' said the Duchess, `chop off her head!' + + Alice glanced rather anxiously at the cook, to see if she meant +to take the hint; but the cook was busily stirring the soup, and +seemed not to be listening, so she went on again: `Twenty-four +hours, I THINK; or is it twelve? I--' + + `Oh, don't bother ME,' said the Duchess; `I never could abide +figures!' And with that she began nursing her child again, +singing a sort of lullaby to it as she did so, and giving it a +violent shake at the end of every line: + + `Speak roughly to your little boy, + And beat him when he sneezes: + He only does it to annoy, + Because he knows it teases.' + + CHORUS. + + (In which the cook and the baby joined):-- + + `Wow! wow! wow!' + + While the Duchess sang the second verse of the song, she kept +tossing the baby violently up and down, and the poor little thing +howled so, that Alice could hardly hear the words:-- + + `I speak severely to my boy, + I beat him when he sneezes; + For he can thoroughly enjoy + The pepper when he pleases!' + + CHORUS. + + `Wow! wow! wow!' + + `Here! you may nurse it a bit, if you like!' the Duchess said +to Alice, flinging the baby at her as she spoke. `I must go and +get ready to play croquet with the Queen,' and she hurried out of +the room. The cook threw a frying-pan after her as she went out, +but it just missed her. + + Alice caught the baby with some difficulty, as it was a queer- +shaped little creature, and held out its arms and legs in all +directions, `just like a star-fish,' thought Alice. The poor +little thing was snorting like a steam-engine when she caught it, +and kept doubling itself up and straightening itself out again, +so that altogether, for the first minute or two, it was as much +as she could do to hold it. + + As soon as she had made out the proper way of nursing it, +(which was to twist it up into a sort of knot, and then keep +tight hold of its right ear and left foot, so as to prevent its +undoing itself,) she carried it out into the open air. `IF I +don't take this child away with me,' thought Alice, `they're sure +to kill it in a day or two: wouldn't it be murder to leave it +behind?' She said the last words out loud, and the little thing +grunted in reply (it had left off sneezing by this time). `Don't +grunt,' said Alice; `that's not at all a proper way of expressing +yourself.' + + The baby grunted again, and Alice looked very anxiously into +its face to see what was the matter with it. There could be no +doubt that it had a VERY turn-up nose, much more like a snout +than a real nose; also its eyes were getting extremely small for +a baby: altogether Alice did not like the look of the thing at +all. `But perhaps it was only sobbing,' she thought, and looked +into its eyes again, to see if there were any tears. + + No, there were no tears. `If you're going to turn into a pig, +my dear,' said Alice, seriously, `I'll have nothing more to do +with you. Mind now!' The poor little thing sobbed again (or +grunted, it was impossible to say which), and they went on for +some while in silence. + + Alice was just beginning to think to herself, `Now, what am I +to do with this creature when I get it home?' when it grunted +again, so violently, that she looked down into its face in some +alarm. This time there could be NO mistake about it: it was +neither more nor less than a pig, and she felt that it would be +quite absurd for her to carry it further. + + So she set the little creature down, and felt quite relieved to +see it trot away quietly into the wood. `If it had grown up,' +she said to herself, `it would have made a dreadfully ugly child: +but it makes rather a handsome pig, I think.' And she began +thinking over other children she knew, who might do very well as +pigs, and was just saying to herself, `if one only knew the right +way to change them--' when she was a little startled by seeing +the Cheshire Cat sitting on a bough of a tree a few yards off. + + The Cat only grinned when it saw Alice. It looked good- +natured, she thought: still it had VERY long claws and a great +many teeth, so she felt that it ought to be treated with respect. + + `Cheshire Puss,' she began, rather timidly, as she did not at +all know whether it would like the name: however, it only +grinned a little wider. `Come, it's pleased so far,' thought +Alice, and she went on. `Would you tell me, please, which way I +ought to go from here?' + + `That depends a good deal on where you want to get to,' said +the Cat. + + `I don't much care where--' said Alice. + + `Then it doesn't matter which way you go,' said the Cat. + + `--so long as I get SOMEWHERE,' Alice added as an explanation. + + `Oh, you're sure to do that,' said the Cat, `if you only walk +long enough.' + + Alice felt that this could not be denied, so she tried another +question. `What sort of people live about here?' + + `In THAT direction,' the Cat said, waving its right paw round, +`lives a Hatter: and in THAT direction,' waving the other paw, +`lives a March Hare. Visit either you like: they're both mad.' + + `But I don't want to go among mad people,' Alice remarked. + + `Oh, you can't help that,' said the Cat: `we're all mad here. +I'm mad. You're mad.' + + `How do you know I'm mad?' said Alice. + + `You must be,' said the Cat, `or you wouldn't have come here.' + + Alice didn't think that proved it at all; however, she went on +`And how do you know that you're mad?' + + `To begin with,' said the Cat, `a dog's not mad. You grant +that?' + + `I suppose so,' said Alice. + + `Well, then,' the Cat went on, `you see, a dog growls when it's +angry, and wags its tail when it's pleased. Now I growl when I'm +pleased, and wag my tail when I'm angry. Therefore I'm mad.' + + `I call it purring, not growling,' said Alice. + + `Call it what you like,' said the Cat. `Do you play croquet +with the Queen to-day?' + + `I should like it very much,' said Alice, `but I haven't been +invited yet.' + + `You'll see me there,' said the Cat, and vanished. + + Alice was not much surprised at this, she was getting so used +to queer things happening. While she was looking at the place +where it had been, it suddenly appeared again. + + `By-the-bye, what became of the baby?' said the Cat. `I'd +nearly forgotten to ask.' + + `It turned into a pig,' Alice quietly said, just as if it had +come back in a natural way. + + `I thought it would,' said the Cat, and vanished again. + + Alice waited a little, half expecting to see it again, but it +did not appear, and after a minute or two she walked on in the +direction in which the March Hare was said to live. `I've seen +hatters before,' she said to herself; `the March Hare will be +much the most interesting, and perhaps as this is May it won't be +raving mad--at least not so mad as it was in March.' As she said +this, she looked up, and there was the Cat again, sitting on a +branch of a tree. + + `Did you say pig, or fig?' said the Cat. + + `I said pig,' replied Alice; `and I wish you wouldn't keep +appearing and vanishing so suddenly: you make one quite giddy.' + + `All right,' said the Cat; and this time it vanished quite +slowly, beginning with the end of the tail, and ending with the +grin, which remained some time after the rest of it had gone. + + `Well! I've often seen a cat without a grin,' thought Alice; +`but a grin without a cat! It's the most curious thing I ever +say in my life!' + + She had not gone much farther before she came in sight of the +house of the March Hare: she thought it must be the right house, +because the chimneys were shaped like ears and the roof was +thatched with fur. It was so large a house, that she did not +like to go nearer till she had nibbled some more of the lefthand +bit of mushroom, and raised herself to about two feet high: even +then she walked up towards it rather timidly, saying to herself +`Suppose it should be raving mad after all! I almost wish I'd +gone to see the Hatter instead!' + + + + CHAPTER VII + + A Mad Tea-Party + + + There was a table set out under a tree in front of the house, +and the March Hare and the Hatter were having tea at it: a +Dormouse was sitting between them, fast asleep, and the other two +were using it as a cushion, resting their elbows on it, and the +talking over its head. `Very uncomfortable for the Dormouse,' +thought Alice; `only, as it's asleep, I suppose it doesn't mind.' + + The table was a large one, but the three were all crowded +together at one corner of it: `No room! No room!' they cried +out when they saw Alice coming. `There's PLENTY of room!' said +Alice indignantly, and she sat down in a large arm-chair at one +end of the table. + + `Have some wine,' the March Hare said in an encouraging tone. + + Alice looked all round the table, but there was nothing on it +but tea. `I don't see any wine,' she remarked. + + `There isn't any,' said the March Hare. + + `Then it wasn't very civil of you to offer it,' said Alice +angrily. + + `It wasn't very civil of you to sit down without being +invited,' said the March Hare. + + `I didn't know it was YOUR table,' said Alice; `it's laid for a +great many more than three.' + + `Your hair wants cutting,' said the Hatter. He had been +looking at Alice for some time with great curiosity, and this was +his first speech. + + `You should learn not to make personal remarks,' Alice said +with some severity; `it's very rude.' + + The Hatter opened his eyes very wide on hearing this; but all +he SAID was, `Why is a raven like a writing-desk?' + + `Come, we shall have some fun now!' thought Alice. `I'm glad +they've begun asking riddles.--I believe I can guess that,' she +added aloud. + + `Do you mean that you think you can find out the answer to it?' +said the March Hare. + + `Exactly so,' said Alice. + + `Then you should say what you mean,' the March Hare went on. + + `I do,' Alice hastily replied; `at least--at least I mean what +I say--that's the same thing, you know.' + + `Not the same thing a bit!' said the Hatter. `You might just +as well say that "I see what I eat" is the same thing as "I eat +what I see"!' + + `You might just as well say,' added the March Hare, `that "I +like what I get" is the same thing as "I get what I like"!' + + `You might just as well say,' added the Dormouse, who seemed to +be talking in his sleep, `that "I breathe when I sleep" is the +same thing as "I sleep when I breathe"!' + + `It IS the same thing with you,' said the Hatter, and here the +conversation dropped, and the party sat silent for a minute, +while Alice thought over all she could remember about ravens and +writing-desks, which wasn't much. + + The Hatter was the first to break the silence. `What day of +the month is it?' he said, turning to Alice: he had taken his +watch out of his pocket, and was looking at it uneasily, shaking +it every now and then, and holding it to his ear. + + Alice considered a little, and then said `The fourth.' + + `Two days wrong!' sighed the Hatter. `I told you butter +wouldn't suit the works!' he added looking angrily at the March +Hare. + + `It was the BEST butter,' the March Hare meekly replied. + + `Yes, but some crumbs must have got in as well,' the Hatter +grumbled: `you shouldn't have put it in with the bread-knife.' + + The March Hare took the watch and looked at it gloomily: then +he dipped it into his cup of tea, and looked at it again: but he +could think of nothing better to say than his first remark, `It +was the BEST butter, you know.' + + Alice had been looking over his shoulder with some curiosity. +`What a funny watch!' she remarked. `It tells the day of the +month, and doesn't tell what o'clock it is!' + + `Why should it?' muttered the Hatter. `Does YOUR watch tell +you what year it is?' + + `Of course not,' Alice replied very readily: `but that's +because it stays the same year for such a long time together.' + + `Which is just the case with MINE,' said the Hatter. + + Alice felt dreadfully puzzled. The Hatter's remark seemed to +have no sort of meaning in it, and yet it was certainly English. +`I don't quite understand you,' she said, as politely as she +could. + + `The Dormouse is asleep again,' said the Hatter, and he poured +a little hot tea upon its nose. + + The Dormouse shook its head impatiently, and said, without +opening its eyes, `Of course, of course; just what I was going to +remark myself.' + + `Have you guessed the riddle yet?' the Hatter said, turning to +Alice again. + + `No, I give it up,' Alice replied: `what's the answer?' + + `I haven't the slightest idea,' said the Hatter. + + `Nor I,' said the March Hare. + + Alice sighed wearily. `I think you might do something better +with the time,' she said, `than waste it in asking riddles that +have no answers.' + + `If you knew Time as well as I do,' said the Hatter, `you +wouldn't talk about wasting IT. It's HIM.' + + `I don't know what you mean,' said Alice. + + `Of course you don't!' the Hatter said, tossing his head +contemptuously. `I dare say you never even spoke to Time!' + + `Perhaps not,' Alice cautiously replied: `but I know I have to +beat time when I learn music.' + + `Ah! that accounts for it,' said the Hatter. `He won't stand +beating. Now, if you only kept on good terms with him, he'd do +almost anything you liked with the clock. For instance, suppose +it were nine o'clock in the morning, just time to begin lessons: +you'd only have to whisper a hint to Time, and round goes the +clock in a twinkling! Half-past one, time for dinner!' + + (`I only wish it was,' the March Hare said to itself in a +whisper.) + + `That would be grand, certainly,' said Alice thoughtfully: +`but then--I shouldn't be hungry for it, you know.' + + `Not at first, perhaps,' said the Hatter: `but you could keep +it to half-past one as long as you liked.' + + `Is that the way YOU manage?' Alice asked. + + The Hatter shook his head mournfully. `Not I!' he replied. +`We quarrelled last March--just before HE went mad, you know--' +(pointing with his tea spoon at the March Hare,) `--it was at the +great concert given by the Queen of Hearts, and I had to sing + + "Twinkle, twinkle, little bat! + How I wonder what you're at!" + +You know the song, perhaps?' + + `I've heard something like it,' said Alice. + + `It goes on, you know,' the Hatter continued, `in this way:-- + + "Up above the world you fly, + Like a tea-tray in the sky. + Twinkle, twinkle--"' + +Here the Dormouse shook itself, and began singing in its sleep +`Twinkle, twinkle, twinkle, twinkle--' and went on so long that +they had to pinch it to make it stop. + + `Well, I'd hardly finished the first verse,' said the Hatter, +`when the Queen jumped up and bawled out, "He's murdering the +time! Off with his head!"' + + `How dreadfully savage!' exclaimed Alice. + + `And ever since that,' the Hatter went on in a mournful tone, +`he won't do a thing I ask! It's always six o'clock now.' + + A bright idea came into Alice's head. `Is that the reason so +many tea-things are put out here?' she asked. + + `Yes, that's it,' said the Hatter with a sigh: `it's always +tea-time, and we've no time to wash the things between whiles.' + + `Then you keep moving round, I suppose?' said Alice. + + `Exactly so,' said the Hatter: `as the things get used up.' + + `But what happens when you come to the beginning again?' Alice +ventured to ask. + + `Suppose we change the subject,' the March Hare interrupted, +yawning. `I'm getting tired of this. I vote the young lady +tells us a story.' + + `I'm afraid I don't know one,' said Alice, rather alarmed at +the proposal. + + `Then the Dormouse shall!' they both cried. `Wake up, +Dormouse!' And they pinched it on both sides at once. + + The Dormouse slowly opened his eyes. `I wasn't asleep,' he +said in a hoarse, feeble voice: `I heard every word you fellows +were saying.' + + `Tell us a story!' said the March Hare. + + `Yes, please do!' pleaded Alice. + + `And be quick about it,' added the Hatter, `or you'll be asleep +again before it's done.' + + `Once upon a time there were three little sisters,' the +Dormouse began in a great hurry; `and their names were Elsie, +Lacie, and Tillie; and they lived at the bottom of a well--' + + `What did they live on?' said Alice, who always took a great +interest in questions of eating and drinking. + + `They lived on treacle,' said the Dormouse, after thinking a +minute or two. + + `They couldn't have done that, you know,' Alice gently +remarked; `they'd have been ill.' + + `So they were,' said the Dormouse; `VERY ill.' + + Alice tried to fancy to herself what such an extraordinary ways +of living would be like, but it puzzled her too much, so she went +on: `But why did they live at the bottom of a well?' + + `Take some more tea,' the March Hare said to Alice, very +earnestly. + + `I've had nothing yet,' Alice replied in an offended tone, `so +I can't take more.' + + `You mean you can't take LESS,' said the Hatter: `it's very +easy to take MORE than nothing.' + + `Nobody asked YOUR opinion,' said Alice. + + `Who's making personal remarks now?' the Hatter asked +triumphantly. + + Alice did not quite know what to say to this: so she helped +herself to some tea and bread-and-butter, and then turned to the +Dormouse, and repeated her question. `Why did they live at the +bottom of a well?' + + The Dormouse again took a minute or two to think about it, and +then said, `It was a treacle-well.' + + `There's no such thing!' Alice was beginning very angrily, but +the Hatter and the March Hare went `Sh! sh!' and the Dormouse +sulkily remarked, `If you can't be civil, you'd better finish the +story for yourself.' + + `No, please go on!' Alice said very humbly; `I won't interrupt +again. I dare say there may be ONE.' + + `One, indeed!' said the Dormouse indignantly. However, he +consented to go on. `And so these three little sisters--they +were learning to draw, you know--' + + `What did they draw?' said Alice, quite forgetting her promise. + + `Treacle,' said the Dormouse, without considering at all this +time. + + `I want a clean cup,' interrupted the Hatter: `let's all move +one place on.' + + He moved on as he spoke, and the Dormouse followed him: the +March Hare moved into the Dormouse's place, and Alice rather +unwillingly took the place of the March Hare. The Hatter was the +only one who got any advantage from the change: and Alice was a +good deal worse off than before, as the March Hare had just upset +the milk-jug into his plate. + + Alice did not wish to offend the Dormouse again, so she began +very cautiously: `But I don't understand. Where did they draw +the treacle from?' + + `You can draw water out of a water-well,' said the Hatter; `so +I should think you could draw treacle out of a treacle-well--eh, +stupid?' + + `But they were IN the well,' Alice said to the Dormouse, not +choosing to notice this last remark. + + `Of course they were', said the Dormouse; `--well in.' + + This answer so confused poor Alice, that she let the Dormouse +go on for some time without interrupting it. + + `They were learning to draw,' the Dormouse went on, yawning and +rubbing its eyes, for it was getting very sleepy; `and they drew +all manner of things--everything that begins with an M--' + + `Why with an M?' said Alice. + + `Why not?' said the March Hare. + + Alice was silent. + + The Dormouse had closed its eyes by this time, and was going +off into a doze; but, on being pinched by the Hatter, it woke up +again with a little shriek, and went on: `--that begins with an +M, such as mouse-traps, and the moon, and memory, and muchness-- +you know you say things are "much of a muchness"--did you ever +see such a thing as a drawing of a muchness?' + + `Really, now you ask me,' said Alice, very much confused, `I +don't think--' + + `Then you shouldn't talk,' said the Hatter. + + This piece of rudeness was more than Alice could bear: she got +up in great disgust, and walked off; the Dormouse fell asleep +instantly, and neither of the others took the least notice of her +going, though she looked back once or twice, half hoping that +they would call after her: the last time she saw them, they were +trying to put the Dormouse into the teapot. + + `At any rate I'll never go THERE again!' said Alice as she +picked her way through the wood. `It's the stupidest tea-party I +ever was at in all my life!' + + Just as she said this, she noticed that one of the trees had a +door leading right into it. `That's very curious!' she thought. +`But everything's curious today. I think I may as well go in at +once.' And in she went. + + Once more she found herself in the long hall, and close to the +little glass table. `Now, I'll manage better this time,' she +said to herself, and began by taking the little golden key, and +unlocking the door that led into the garden. Then she went to +work nibbling at the mushroom (she had kept a piece of it in her +pocked) till she was about a foot high: then she walked down the +little passage: and THEN--she found herself at last in the +beautiful garden, among the bright flower-beds and the cool +fountains. + + + + CHAPTER VIII + + The Queen's Croquet-Ground + + + A large rose-tree stood near the entrance of the garden: the +roses growing on it were white, but there were three gardeners at +it, busily painting them red. Alice thought this a very curious +thing, and she went nearer to watch them, and just as she came up +to them she heard one of them say, `Look out now, Five! Don't go +splashing paint over me like that!' + + `I couldn't help it,' said Five, in a sulky tone; `Seven jogged +my elbow.' + + On which Seven looked up and said, `That's right, Five! Always +lay the blame on others!' + + `YOU'D better not talk!' said Five. `I heard the Queen say only +yesterday you deserved to be beheaded!' + + `What for?' said the one who had spoken first. + + `That's none of YOUR business, Two!' said Seven. + + `Yes, it IS his business!' said Five, `and I'll tell him--it +was for bringing the cook tulip-roots instead of onions.' + + Seven flung down his brush, and had just begun `Well, of all +the unjust things--' when his eye chanced to fall upon Alice, as +she stood watching them, and he checked himself suddenly: the +others looked round also, and all of them bowed low. + + `Would you tell me,' said Alice, a little timidly, `why you are +painting those roses?' + + Five and Seven said nothing, but looked at Two. Two began in a +low voice, `Why the fact is, you see, Miss, this here ought to +have been a RED rose-tree, and we put a white one in by mistake; +and if the Queen was to find it out, we should all have our heads +cut off, you know. So you see, Miss, we're doing our best, afore +she comes, to--' At this moment Five, who had been anxiously +looking across the garden, called out `The Queen! The Queen!' +and the three gardeners instantly threw themselves flat upon +their faces. There was a sound of many footsteps, and Alice +looked round, eager to see the Queen. + + First came ten soldiers carrying clubs; these were all shaped +like the three gardeners, oblong and flat, with their hands and +feet at the corners: next the ten courtiers; these were +ornamented all over with diamonds, and walked two and two, as the +soldiers did. After these came the royal children; there were +ten of them, and the little dears came jumping merrily along hand +in hand, in couples: they were all ornamented with hearts. Next +came the guests, mostly Kings and Queens, and among them Alice +recognised the White Rabbit: it was talking in a hurried nervous +manner, smiling at everything that was said, and went by without +noticing her. Then followed the Knave of Hearts, carrying the +King's crown on a crimson velvet cushion; and, last of all this +grand procession, came THE KING AND QUEEN OF HEARTS. + + Alice was rather doubtful whether she ought not to lie down on +her face like the three gardeners, but she could not remember +every having heard of such a rule at processions; `and besides, +what would be the use of a procession,' thought she, `if people +had all to lie down upon their faces, so that they couldn't see +it?' So she stood still where she was, and waited. + + When the procession came opposite to Alice, they all stopped +and looked at her, and the Queen said severely `Who is this?' +She said it to the Knave of Hearts, who only bowed and smiled in +reply. + + `Idiot!' said the Queen, tossing her head impatiently; and, +turning to Alice, she went on, `What's your name, child?' + + `My name is Alice, so please your Majesty,' said Alice very +politely; but she added, to herself, `Why, they're only a pack of +cards, after all. I needn't be afraid of them!' + + `And who are THESE?' said the Queen, pointing to the three +gardeners who were lying round the rosetree; for, you see, as +they were lying on their faces, and the pattern on their backs +was the same as the rest of the pack, she could not tell whether +they were gardeners, or soldiers, or courtiers, or three of her +own children. + + `How should I know?' said Alice, surprised at her own courage. +`It's no business of MINE.' + + The Queen turned crimson with fury, and, after glaring at her +for a moment like a wild beast, screamed `Off with her head! +Off--' + + `Nonsense!' said Alice, very loudly and decidedly, and the +Queen was silent. + + The King laid his hand upon her arm, and timidly said +`Consider, my dear: she is only a child!' + + The Queen turned angrily away from him, and said to the Knave +`Turn them over!' + + The Knave did so, very carefully, with one foot. + + `Get up!' said the Queen, in a shrill, loud voice, and the +three gardeners instantly jumped up, and began bowing to the +King, the Queen, the royal children, and everybody else. + + `Leave off that!' screamed the Queen. `You make me giddy.' +And then, turning to the rose-tree, she went on, `What HAVE you +been doing here?' + + `May it please your Majesty,' said Two, in a very humble tone, +going down on one knee as he spoke, `we were trying--' + + `I see!' said the Queen, who had meanwhile been examining the +roses. `Off with their heads!' and the procession moved on, +three of the soldiers remaining behind to execute the unfortunate +gardeners, who ran to Alice for protection. + + `You shan't be beheaded!' said Alice, and she put them into a +large flower-pot that stood near. The three soldiers wandered +about for a minute or two, looking for them, and then quietly +marched off after the others. + + `Are their heads off?' shouted the Queen. + + `Their heads are gone, if it please your Majesty!' the soldiers +shouted in reply. + + `That's right!' shouted the Queen. `Can you play croquet?' + + The soldiers were silent, and looked at Alice, as the question +was evidently meant for her. + + `Yes!' shouted Alice. + + `Come on, then!' roared the Queen, and Alice joined the +procession, wondering very much what would happen next. + + `It's--it's a very fine day!' said a timid voice at her side. +She was walking by the White Rabbit, who was peeping anxiously +into her face. + + `Very,' said Alice: `--where's the Duchess?' + + `Hush! Hush!' said the Rabbit in a low, hurried tone. He +looked anxiously over his shoulder as he spoke, and then raised +himself upon tiptoe, put his mouth close to her ear, and +whispered `She's under sentence of execution.' + + `What for?' said Alice. + + `Did you say "What a pity!"?' the Rabbit asked. + + `No, I didn't,' said Alice: `I don't think it's at all a pity. +I said "What for?"' + + `She boxed the Queen's ears--' the Rabbit began. Alice gave a +little scream of laughter. `Oh, hush!' the Rabbit whispered in a +frightened tone. `The Queen will hear you! You see, she came +rather late, and the Queen said--' + + `Get to your places!' shouted the Queen in a voice of thunder, +and people began running about in all directions, tumbling up +against each other; however, they got settled down in a minute or +two, and the game began. Alice thought she had never seen such a +curious croquet-ground in her life; it was all ridges and +furrows; the balls were live hedgehogs, the mallets live +flamingoes, and the soldiers had to double themselves up and to +stand on their hands and feet, to make the arches. + + The chief difficulty Alice found at first was in managing her +flamingo: she succeeded in getting its body tucked away, +comfortably enough, under her arm, with its legs hanging down, +but generally, just as she had got its neck nicely straightened +out, and was going to give the hedgehog a blow with its head, it +WOULD twist itself round and look up in her face, with such a +puzzled expression that she could not help bursting out laughing: +and when she had got its head down, and was going to begin again, +it was very provoking to find that the hedgehog had unrolled +itself, and was in the act of crawling away: besides all this, +there was generally a ridge or furrow in the way wherever she +wanted to send the hedgehog to, and, as the doubled-up soldiers +were always getting up and walking off to other parts of the +ground, Alice soon came to the conclusion that it was a very +difficult game indeed. + + The players all played at once without waiting for turns, +quarrelling all the while, and fighting for the hedgehogs; and in +a very short time the Queen was in a furious passion, and went +stamping about, and shouting `Off with his head!' or `Off with +her head!' about once in a minute. + + Alice began to feel very uneasy: to be sure, she had not as +yet had any dispute with the Queen, but she knew that it might +happen any minute, `and then,' thought she, `what would become of +me? They're dreadfully fond of beheading people here; the great +wonder is, that there's any one left alive!' + + She was looking about for some way of escape, and wondering +whether she could get away without being seen, when she noticed a +curious appearance in the air: it puzzled her very much at +first, but, after watching it a minute or two, she made it out to +be a grin, and she said to herself `It's the Cheshire Cat: now I +shall have somebody to talk to.' + + `How are you getting on?' said the Cat, as soon as there was +mouth enough for it to speak with. + + Alice waited till the eyes appeared, and then nodded. `It's no +use speaking to it,' she thought, `till its ears have come, or at +least one of them.' In another minute the whole head appeared, +and then Alice put down her flamingo, and began an account of the +game, feeling very glad she had someone to listen to her. The +Cat seemed to think that there was enough of it now in sight, and +no more of it appeared. + + `I don't think they play at all fairly,' Alice began, in rather +a complaining tone, `and they all quarrel so dreadfully one can't +hear oneself speak--and they don't seem to have any rules in +particular; at least, if there are, nobody attends to them--and +you've no idea how confusing it is all the things being alive; +for instance, there's the arch I've got to go through next +walking about at the other end of the ground--and I should have +croqueted the Queen's hedgehog just now, only it ran away when it +saw mine coming!' + + `How do you like the Queen?' said the Cat in a low voice. + + `Not at all,' said Alice: `she's so extremely--' Just then +she noticed that the Queen was close behind her, listening: so +she went on, `--likely to win, that it's hardly worth while +finishing the game.' + + The Queen smiled and passed on. + + `Who ARE you talking to?' said the King, going up to Alice, and +looking at the Cat's head with great curiosity. + + `It's a friend of mine--a Cheshire Cat,' said Alice: `allow me +to introduce it.' + + `I don't like the look of it at all,' said the King: `however, +it may kiss my hand if it likes.' + + `I'd rather not,' the Cat remarked. + + `Don't be impertinent,' said the King, `and don't look at me +like that!' He got behind Alice as he spoke. + + `A cat may look at a king,' said Alice. `I've read that in +some book, but I don't remember where.' + + `Well, it must be removed,' said the King very decidedly, and +he called the Queen, who was passing at the moment, `My dear! I +wish you would have this cat removed!' + + The Queen had only one way of settling all difficulties, great +or small. `Off with his head!' she said, without even looking +round. + + `I'll fetch the executioner myself,' said the King eagerly, and +he hurried off. + + Alice thought she might as well go back, and see how the game +was going on, as she heard the Queen's voice in the distance, +screaming with passion. She had already heard her sentence three +of the players to be executed for having missed their turns, and +she did not like the look of things at all, as the game was in +such confusion that she never knew whether it was her turn or +not. So she went in search of her hedgehog. + + The hedgehog was engaged in a fight with another hedgehog, +which seemed to Alice an excellent opportunity for croqueting one +of them with the other: the only difficulty was, that her +flamingo was gone across to the other side of the garden, where +Alice could see it trying in a helpless sort of way to fly up +into a tree. + + By the time she had caught the flamingo and brought it back, +the fight was over, and both the hedgehogs were out of sight: +`but it doesn't matter much,' thought Alice, `as all the arches +are gone from this side of the ground.' So she tucked it away +under her arm, that it might not escape again, and went back for +a little more conversation with her friend. + + When she got back to the Cheshire Cat, she was surprised to +find quite a large crowd collected round it: there was a dispute +going on between the executioner, the King, and the Queen, who +were all talking at once, while all the rest were quite silent, +and looked very uncomfortable. + + The moment Alice appeared, she was appealed to by all three to +settle the question, and they repeated their arguments to her, +though, as they all spoke at once, she found it very hard indeed +to make out exactly what they said. + + The executioner's argument was, that you couldn't cut off a +head unless there was a body to cut it off from: that he had +never had to do such a thing before, and he wasn't going to begin +at HIS time of life. + + The King's argument was, that anything that had a head could be +beheaded, and that you weren't to talk nonsense. + + The Queen's argument was, that if something wasn't done about +it in less than no time she'd have everybody executed, all round. +(It was this last remark that had made the whole party look so +grave and anxious.) + + Alice could think of nothing else to say but `It belongs to the +Duchess: you'd better ask HER about it.' + + `She's in prison,' the Queen said to the executioner: `fetch +her here.' And the executioner went off like an arrow. + + The Cat's head began fading away the moment he was gone, and, +by the time he had come back with the Dutchess, it had entirely +disappeared; so the King and the executioner ran wildly up and +down looking for it, while the rest of the party went back to the game. + + + + CHAPTER IX + + The Mock Turtle's Story + + + `You can't think how glad I am to see you again, you dear old +thing!' said the Duchess, as she tucked her arm affectionately +into Alice's, and they walked off together. + + Alice was very glad to find her in such a pleasant temper, and +thought to herself that perhaps it was only the pepper that had +made her so savage when they met in the kitchen. + + `When I'M a Duchess,' she said to herself, (not in a very +hopeful tone though), `I won't have any pepper in my kitchen AT +ALL. Soup does very well without--Maybe it's always pepper that +makes people hot-tempered,' she went on, very much pleased at +having found out a new kind of rule, `and vinegar that makes them +sour--and camomile that makes them bitter--and--and barley-sugar +and such things that make children sweet-tempered. I only wish +people knew that: then they wouldn't be so stingy about it, you +know--' + + She had quite forgotten the Duchess by this time, and was a +little startled when she heard her voice close to her ear. +`You're thinking about something, my dear, and that makes you +forget to talk. I can't tell you just now what the moral of that +is, but I shall remember it in a bit.' + + `Perhaps it hasn't one,' Alice ventured to remark. + + `Tut, tut, child!' said the Duchess. `Everything's got a +moral, if only you can find it.' And she squeezed herself up +closer to Alice's side as she spoke. + + Alice did not much like keeping so close to her: first, +because the Duchess was VERY ugly; and secondly, because she was +exactly the right height to rest her chin upon Alice's shoulder, +and it was an uncomfortably sharp chin. However, she did not +like to be rude, so she bore it as well as she could. + + `The game's going on rather better now,' she said, by way of +keeping up the conversation a little. + + `'Tis so,' said the Duchess: `and the moral of that is--"Oh, +'tis love, 'tis love, that makes the world go round!"' + + `Somebody said,' Alice whispered, `that it's done by everybody +minding their own business!' + + `Ah, well! It means much the same thing,' said the Duchess, +digging her sharp little chin into Alice's shoulder as she added, +`and the moral of THAT is--"Take care of the sense, and the +sounds will take care of themselves."' + + `How fond she is of finding morals in things!' Alice thought to +herself. + + `I dare say you're wondering why I don't put my arm round your +waist,' the Duchess said after a pause: `the reason is, that I'm +doubtful about the temper of your flamingo. Shall I try the +experiment?' + + `HE might bite,' Alice cautiously replied, not feeling at all +anxious to have the experiment tried. + + `Very true,' said the Duchess: `flamingoes and mustard both +bite. And the moral of that is--"Birds of a feather flock +together."' + + `Only mustard isn't a bird,' Alice remarked. + + `Right, as usual,' said the Duchess: `what a clear way you +have of putting things!' + + `It's a mineral, I THINK,' said Alice. + + `Of course it is,' said the Duchess, who seemed ready to agree +to everything that Alice said; `there's a large mustard-mine near +here. And the moral of that is--"The more there is of mine, the +less there is of yours."' + + `Oh, I know!' exclaimed Alice, who had not attended to this +last remark, `it's a vegetable. It doesn't look like one, but it +is.' + + `I quite agree with you,' said the Duchess; `and the moral of +that is--"Be what you would seem to be"--or if you'd like it put +more simply--"Never imagine yourself not to be otherwise than +what it might appear to others that what you were or might have +been was not otherwise than what you had been would have appeared +to them to be otherwise."' + + `I think I should understand that better,' Alice said very +politely, `if I had it written down: but I can't quite follow it +as you say it.' + + `That's nothing to what I could say if I chose,' the Duchess +replied, in a pleased tone. + + `Pray don't trouble yourself to say it any longer than that,' +said Alice. + + `Oh, don't talk about trouble!' said the Duchess. `I make you +a present of everything I've said as yet.' + + `A cheap sort of present!' thought Alice. `I'm glad they don't +give birthday presents like that!' But she did not venture to +say it out loud. + + `Thinking again?' the Duchess asked, with another dig of her +sharp little chin. + + `I've a right to think,' said Alice sharply, for she was +beginning to feel a little worried. + + `Just about as much right,' said the Duchess, `as pigs have to +fly; and the m--' + + But here, to Alice's great surprise, the Duchess's voice died +away, even in the middle of her favourite word `moral,' and the +arm that was linked into hers began to tremble. Alice looked up, +and there stood the Queen in front of them, with her arms folded, +frowning like a thunderstorm. + + `A fine day, your Majesty!' the Duchess began in a low, weak +voice. + + `Now, I give you fair warning,' shouted the Queen, stamping on +the ground as she spoke; `either you or your head must be off, +and that in about half no time! Take your choice!' + + The Duchess took her choice, and was gone in a moment. + + `Let's go on with the game,' the Queen said to Alice; and Alice +was too much frightened to say a word, but slowly followed her +back to the croquet-ground. + + The other guests had taken advantage of the Queen's absence, +and were resting in the shade: however, the moment they saw her, +they hurried back to the game, the Queen merely remarking that a +moment's delay would cost them their lives. + + All the time they were playing the Queen never left off +quarrelling with the other players, and shouting `Off with his +head!' or `Off with her head!' Those whom she sentenced were +taken into custody by the soldiers, who of course had to leave +off being arches to do this, so that by the end of half an hour +or so there were no arches left, and all the players, except the +King, the Queen, and Alice, were in custody and under sentence of +execution. + + Then the Queen left off, quite out of breath, and said to +Alice, `Have you seen the Mock Turtle yet?' + + `No,' said Alice. `I don't even know what a Mock Turtle is.' + + `It's the thing Mock Turtle Soup is made from,' said the Queen. + + `I never saw one, or heard of one,' said Alice. + + `Come on, then,' said the Queen, `and he shall tell you his +history,' + + As they walked off together, Alice heard the King say in a low +voice, to the company generally, `You are all pardoned.' `Come, +THAT'S a good thing!' she said to herself, for she had felt quite +unhappy at the number of executions the Queen had ordered. + + They very soon came upon a Gryphon, lying fast asleep in the +sun. (IF you don't know what a Gryphon is, look at the picture.) +`Up, lazy thing!' said the Queen, `and take this young lady to +see the Mock Turtle, and to hear his history. I must go back and +see after some executions I have ordered'; and she walked off, +leaving Alice alone with the Gryphon. Alice did not quite like +the look of the creature, but on the whole she thought it would +be quite as safe to stay with it as to go after that savage +Queen: so she waited. + + The Gryphon sat up and rubbed its eyes: then it watched the +Queen till she was out of sight: then it chuckled. `What fun!' +said the Gryphon, half to itself, half to Alice. + + `What IS the fun?' said Alice. + + `Why, SHE,' said the Gryphon. `It's all her fancy, that: they +never executes nobody, you know. Come on!' + + `Everybody says "come on!" here,' thought Alice, as she went +slowly after it: `I never was so ordered about in all my life, +never!' + + They had not gone far before they saw the Mock Turtle in the +distance, sitting sad and lonely on a little ledge of rock, and, +as they came nearer, Alice could hear him sighing as if his heart +would break. She pitied him deeply. `What is his sorrow?' she +asked the Gryphon, and the Gryphon answered, very nearly in the +same words as before, `It's all his fancy, that: he hasn't got +no sorrow, you know. Come on!' + + So they went up to the Mock Turtle, who looked at them with +large eyes full of tears, but said nothing. + + `This here young lady,' said the Gryphon, `she wants for to +know your history, she do.' + + `I'll tell it her,' said the Mock Turtle in a deep, hollow +tone: `sit down, both of you, and don't speak a word till I've +finished.' + + So they sat down, and nobody spoke for some minutes. Alice +thought to herself, `I don't see how he can EVEN finish, if he +doesn't begin.' But she waited patiently. + + `Once,' said the Mock Turtle at last, with a deep sigh, `I was +a real Turtle.' + + These words were followed by a very long silence, broken only +by an occasional exclamation of `Hjckrrh!' from the Gryphon, and +the constant heavy sobbing of the Mock Turtle. Alice was very +nearly getting up and saying, `Thank you, sir, for your +interesting story,' but she could not help thinking there MUST be +more to come, so she sat still and said nothing. + + `When we were little,' the Mock Turtle went on at last, more +calmly, though still sobbing a little now and then, `we went to +school in the sea. The master was an old Turtle--we used to call +him Tortoise--' + + `Why did you call him Tortoise, if he wasn't one?' Alice asked. + + `We called him Tortoise because he taught us,' said the Mock +Turtle angrily: `really you are very dull!' + + `You ought to be ashamed of yourself for asking such a simple +question,' added the Gryphon; and then they both sat silent and +looked at poor Alice, who felt ready to sink into the earth. At +last the Gryphon said to the Mock Turtle, `Drive on, old fellow! +Don't be all day about it!' and he went on in these words: + + `Yes, we went to school in the sea, though you mayn't believe +it--' + + `I never said I didn't!' interrupted Alice. + + `You did,' said the Mock Turtle. + + `Hold your tongue!' added the Gryphon, before Alice could speak +again. The Mock Turtle went on. + + `We had the best of educations--in fact, we went to school +every day--' + + `I'VE been to a day-school, too,' said Alice; `you needn't be +so proud as all that.' + + `With extras?' asked the Mock Turtle a little anxiously. + + `Yes,' said Alice, `we learned French and music.' + + `And washing?' said the Mock Turtle. + + `Certainly not!' said Alice indignantly. + + `Ah! then yours wasn't a really good school,' said the Mock +Turtle in a tone of great relief. `Now at OURS they had at the +end of the bill, "French, music, AND WASHING--extra."' + + `You couldn't have wanted it much,' said Alice; `living at the +bottom of the sea.' + + `I couldn't afford to learn it.' said the Mock Turtle with a +sigh. `I only took the regular course.' + + `What was that?' inquired Alice. + + `Reeling and Writhing, of course, to begin with,' the Mock +Turtle replied; `and then the different branches of Arithmetic-- +Ambition, Distraction, Uglification, and Derision.' + + `I never heard of "Uglification,"' Alice ventured to say. `What +is it?' + + The Gryphon lifted up both its paws in surprise. `What! Never +heard of uglifying!' it exclaimed. `You know what to beautify +is, I suppose?' + + `Yes,' said Alice doubtfully: `it means--to--make--anything-- +prettier.' + + `Well, then,' the Gryphon went on, `if you don't know what to +uglify is, you ARE a simpleton.' + + Alice did not feel encouraged to ask any more questions about +it, so she turned to the Mock Turtle, and said `What else had you +to learn?' + + `Well, there was Mystery,' the Mock Turtle replied, counting +off the subjects on his flappers, `--Mystery, ancient and modern, +with Seaography: then Drawling--the Drawling-master was an old +conger-eel, that used to come once a week: HE taught us +Drawling, Stretching, and Fainting in Coils.' + + `What was THAT like?' said Alice. + + `Well, I can't show it you myself,' the Mock Turtle said: `I'm +too stiff. And the Gryphon never learnt it.' + + `Hadn't time,' said the Gryphon: `I went to the Classics +master, though. He was an old crab, HE was.' + + `I never went to him,' the Mock Turtle said with a sigh: `he +taught Laughing and Grief, they used to say.' + + `So he did, so he did,' said the Gryphon, sighing in his turn; +and both creatures hid their faces in their paws. + + `And how many hours a day did you do lessons?' said Alice, in a +hurry to change the subject. + + `Ten hours the first day,' said the Mock Turtle: `nine the +next, and so on.' + + `What a curious plan!' exclaimed Alice. + + `That's the reason they're called lessons,' the Gryphon +remarked: `because they lessen from day to day.' + + This was quite a new idea to Alice, and she thought it over a +little before she made her next remark. `Then the eleventh day +must have been a holiday?' + + `Of course it was,' said the Mock Turtle. + + `And how did you manage on the twelfth?' Alice went on eagerly. + + `That's enough about lessons,' the Gryphon interrupted in a +very decided tone: `tell her something about the games now.' + + + + CHAPTER X + + The Lobster Quadrille + + + The Mock Turtle sighed deeply, and drew the back of one flapper +across his eyes. He looked at Alice, and tried to speak, but for +a minute or two sobs choked his voice. `Same as if he had a bone +in his throat,' said the Gryphon: and it set to work shaking him +and punching him in the back. At last the Mock Turtle recovered +his voice, and, with tears running down his cheeks, he went on +again:-- + + `You may not have lived much under the sea--' (`I haven't,' +said Alice)--`and perhaps you were never even introduced to a lobster--' +(Alice began to say `I once tasted--' but checked herself hastily, +and said `No, never') `--so you can have no idea what a delightful +thing a Lobster Quadrille is!' + + `No, indeed,' said Alice. `What sort of a dance is it?' + + `Why,' said the Gryphon, `you first form into a line along the +sea-shore--' + + `Two lines!' cried the Mock Turtle. `Seals, turtles, salmon, +and so on; then, when you've cleared all the jelly-fish out of +the way--' + + `THAT generally takes some time,' interrupted the Gryphon. + + `--you advance twice--' + + `Each with a lobster as a partner!' cried the Gryphon. + + `Of course,' the Mock Turtle said: `advance twice, set to +partners--' + + `--change lobsters, and retire in same order,' continued the +Gryphon. + + `Then, you know,' the Mock Turtle went on, `you throw the--' + + `The lobsters!' shouted the Gryphon, with a bound into the air. + + `--as far out to sea as you can--' + + `Swim after them!' screamed the Gryphon. + + `Turn a somersault in the sea!' cried the Mock Turtle, +capering wildly about. + + `Back to land again, and that's all the first figure,' said the +Mock Turtle, suddenly dropping his voice; and the two creatures, +who had been jumping about like mad things all this time, sat +down again very sadly and quietly, and looked at Alice. + + `It must be a very pretty dance,' said Alice timidly. + + `Would you like to see a little of it?' said the Mock Turtle. + + `Very much indeed,' said Alice. + + `Come, let's try the first figure!' said the Mock Turtle to the +Gryphon. `We can do without lobsters, you know. Which shall +sing?' + + `Oh, YOU sing,' said the Gryphon. `I've forgotten the words.' + + So they began solemnly dancing round and round Alice, every now +and then treading on her toes when they passed too close, and +waving their forepaws to mark the time, while the Mock Turtle +sang this, very slowly and sadly:-- + + +`"Will you walk a little faster?" said a whiting to a snail. +"There's a porpoise close behind us, and he's treading on my + tail. +See how eagerly the lobsters and the turtles all advance! +They are waiting on the shingle--will you come and join the +dance? + +Will you, won't you, will you, won't you, will you join the +dance? +Will you, won't you, will you, won't you, won't you join the +dance? + + +"You can really have no notion how delightful it will be +When they take us up and throw us, with the lobsters, out to + sea!" +But the snail replied "Too far, too far!" and gave a look + askance-- +Said he thanked the whiting kindly, but he would not join the + dance. + Would not, could not, would not, could not, would not join + the dance. + Would not, could not, would not, could not, could not join + the dance. + +`"What matters it how far we go?" his scaly friend replied. +"There is another shore, you know, upon the other side. +The further off from England the nearer is to France-- +Then turn not pale, beloved snail, but come and join the dance. + + Will you, won't you, will you, won't you, will you join the + dance? + Will you, won't you, will you, won't you, won't you join the + dance?"' + + + + `Thank you, it's a very interesting dance to watch,' said +Alice, feeling very glad that it was over at last: `and I do so +like that curious song about the whiting!' + + `Oh, as to the whiting,' said the Mock Turtle, `they--you've +seen them, of course?' + + `Yes,' said Alice, `I've often seen them at dinn--' she +checked herself hastily. + + `I don't know where Dinn may be,' said the Mock Turtle, `but +if you've seen them so often, of course you know what they're +like.' + + `I believe so,' Alice replied thoughtfully. `They have their +tails in their mouths--and they're all over crumbs.' + + `You're wrong about the crumbs,' said the Mock Turtle: +`crumbs would all wash off in the sea. But they HAVE their tails +in their mouths; and the reason is--' here the Mock Turtle +yawned and shut his eyes.--`Tell her about the reason and all +that,' he said to the Gryphon. + + `The reason is,' said the Gryphon, `that they WOULD go with +the lobsters to the dance. So they got thrown out to sea. So +they had to fall a long way. So they got their tails fast in +their mouths. So they couldn't get them out again. That's all.' + + `Thank you,' said Alice, `it's very interesting. I never knew +so much about a whiting before.' + + `I can tell you more than that, if you like,' said the +Gryphon. `Do you know why it's called a whiting?' + + `I never thought about it,' said Alice. `Why?' + + `IT DOES THE BOOTS AND SHOES.' the Gryphon replied very +solemnly. + + Alice was thoroughly puzzled. `Does the boots and shoes!' she +repeated in a wondering tone. + + `Why, what are YOUR shoes done with?' said the Gryphon. `I +mean, what makes them so shiny?' + + Alice looked down at them, and considered a little before she +gave her answer. `They're done with blacking, I believe.' + + `Boots and shoes under the sea,' the Gryphon went on in a deep +voice, `are done with a whiting. Now you know.' + + `And what are they made of?' Alice asked in a tone of great +curiosity. + + `Soles and eels, of course,' the Gryphon replied rather +impatiently: `any shrimp could have told you that.' + + `If I'd been the whiting,' said Alice, whose thoughts were +still running on the song, `I'd have said to the porpoise, "Keep +back, please: we don't want YOU with us!"' + + `They were obliged to have him with them,' the Mock Turtle +said: `no wise fish would go anywhere without a porpoise.' + + `Wouldn't it really?' said Alice in a tone of great surprise. + + `Of course not,' said the Mock Turtle: `why, if a fish came +to ME, and told me he was going a journey, I should say "With +what porpoise?"' + + `Don't you mean "purpose"?' said Alice. + + `I mean what I say,' the Mock Turtle replied in an offended +tone. And the Gryphon added `Come, let's hear some of YOUR +adventures.' + + `I could tell you my adventures--beginning from this morning,' +said Alice a little timidly: `but it's no use going back to +yesterday, because I was a different person then.' + + `Explain all that,' said the Mock Turtle. + + `No, no! The adventures first,' said the Gryphon in an +impatient tone: `explanations take such a dreadful time.' + + So Alice began telling them her adventures from the time when +she first saw the White Rabbit. She was a little nervous about +it just at first, the two creatures got so close to her, one on +each side, and opened their eyes and mouths so VERY wide, but she +gained courage as she went on. Her listeners were perfectly +quiet till she got to the part about her repeating `YOU ARE OLD, +FATHER WILLIAM,' to the Caterpillar, and the words all coming +different, and then the Mock Turtle drew a long breath, and said +`That's very curious.' + + `It's all about as curious as it can be,' said the Gryphon. + + `It all came different!' the Mock Turtle repeated +thoughtfully. `I should like to hear her try and repeat +something now. Tell her to begin.' He looked at the Gryphon as +if he thought it had some kind of authority over Alice. + + `Stand up and repeat "'TIS THE VOICE OF THE SLUGGARD,"' said +the Gryphon. + + `How the creatures order one about, and make one repeat +lessons!' thought Alice; `I might as well be at school at once.' +However, she got up, and began to repeat it, but her head was so +full of the Lobster Quadrille, that she hardly knew what she was +saying, and the words came very queer indeed:-- + + `'Tis the voice of the Lobster; I heard him declare, + "You have baked me too brown, I must sugar my hair." + As a duck with its eyelids, so he with his nose + Trims his belt and his buttons, and turns out his toes.' + + [later editions continued as follows + When the sands are all dry, he is gay as a lark, + And will talk in contemptuous tones of the Shark, + But, when the tide rises and sharks are around, + His voice has a timid and tremulous sound.] + + `That's different from what I used to say when I was a child,' +said the Gryphon. + + `Well, I never heard it before,' said the Mock Turtle; `but it +sounds uncommon nonsense.' + + Alice said nothing; she had sat down with her face in her +hands, wondering if anything would EVER happen in a natural way +again. + + `I should like to have it explained,' said the Mock Turtle. + + `She can't explain it,' said the Gryphon hastily. `Go on with +the next verse.' + + `But about his toes?' the Mock Turtle persisted. `How COULD +he turn them out with his nose, you know?' + + `It's the first position in dancing.' Alice said; but was +dreadfully puzzled by the whole thing, and longed to change the +subject. + + `Go on with the next verse,' the Gryphon repeated impatiently: +`it begins "I passed by his garden."' + + Alice did not dare to disobey, though she felt sure it would +all come wrong, and she went on in a trembling voice:-- + + `I passed by his garden, and marked, with one eye, + How the Owl and the Panther were sharing a pie--' + + [later editions continued as follows + The Panther took pie-crust, and gravy, and meat, + While the Owl had the dish as its share of the treat. + When the pie was all finished, the Owl, as a boon, + Was kindly permitted to pocket the spoon: + While the Panther received knife and fork with a growl, + And concluded the banquet--] + + `What IS the use of repeating all that stuff,' the Mock Turtle +interrupted, `if you don't explain it as you go on? It's by far +the most confusing thing I ever heard!' + + `Yes, I think you'd better leave off,' said the Gryphon: and +Alice was only too glad to do so. + + `Shall we try another figure of the Lobster Quadrille?' the +Gryphon went on. `Or would you like the Mock Turtle to sing you +a song?' + + `Oh, a song, please, if the Mock Turtle would be so kind,' +Alice replied, so eagerly that the Gryphon said, in a rather +offended tone, `Hm! No accounting for tastes! Sing her "Turtle +Soup," will you, old fellow?' + + The Mock Turtle sighed deeply, and began, in a voice sometimes +choked with sobs, to sing this:-- + + + `Beautiful Soup, so rich and green, + Waiting in a hot tureen! + Who for such dainties would not stoop? + Soup of the evening, beautiful Soup! + Soup of the evening, beautiful Soup! + Beau--ootiful Soo--oop! + Beau--ootiful Soo--oop! + Soo--oop of the e--e--evening, + Beautiful, beautiful Soup! + + `Beautiful Soup! Who cares for fish, + Game, or any other dish? + Who would not give all else for two p + ennyworth only of beautiful Soup? + Pennyworth only of beautiful Soup? + Beau--ootiful Soo--oop! + Beau--ootiful Soo--oop! + Soo--oop of the e--e--evening, + Beautiful, beauti--FUL SOUP!' + + `Chorus again!' cried the Gryphon, and the Mock Turtle had +just begun to repeat it, when a cry of `The trial's beginning!' +was heard in the distance. + + `Come on!' cried the Gryphon, and, taking Alice by the hand, +it hurried off, without waiting for the end of the song. + + `What trial is it?' Alice panted as she ran; but the Gryphon +only answered `Come on!' and ran the faster, while more and more +faintly came, carried on the breeze that followed them, the +melancholy words:-- + + `Soo--oop of the e--e--evening, + Beautiful, beautiful Soup!' + + + + CHAPTER XI + + Who Stole the Tarts? + + + The King and Queen of Hearts were seated on their throne when +they arrived, with a great crowd assembled about them--all sorts +of little birds and beasts, as well as the whole pack of cards: +the Knave was standing before them, in chains, with a soldier on +each side to guard him; and near the King was the White Rabbit, +with a trumpet in one hand, and a scroll of parchment in the +other. In the very middle of the court was a table, with a large +dish of tarts upon it: they looked so good, that it made Alice +quite hungry to look at them--`I wish they'd get the trial done,' +she thought, `and hand round the refreshments!' But there seemed +to be no chance of this, so she began looking at everything about +her, to pass away the time. + + Alice had never been in a court of justice before, but she had +read about them in books, and she was quite pleased to find that +she knew the name of nearly everything there. `That's the +judge,' she said to herself, `because of his great wig.' + + The judge, by the way, was the King; and as he wore his crown +over the wig, (look at the frontispiece if you want to see how he +did it,) he did not look at all comfortable, and it was certainly +not becoming. + + `And that's the jury-box,' thought Alice, `and those twelve +creatures,' (she was obliged to say `creatures,' you see, because +some of them were animals, and some were birds,) `I suppose they +are the jurors.' She said this last word two or three times over +to herself, being rather proud of it: for she thought, and +rightly too, that very few little girls of her age knew the +meaning of it at all. However, `jury-men' would have done just +as well. + + The twelve jurors were all writing very busily on slates. +`What are they doing?' Alice whispered to the Gryphon. `They +can't have anything to put down yet, before the trial's begun.' + + `They're putting down their names,' the Gryphon whispered in +reply, `for fear they should forget them before the end of the +trial.' + + `Stupid things!' Alice began in a loud, indignant voice, but +she stopped hastily, for the White Rabbit cried out, `Silence in +the court!' and the King put on his spectacles and looked +anxiously round, to make out who was talking. + + Alice could see, as well as if she were looking over their +shoulders, that all the jurors were writing down `stupid things!' +on their slates, and she could even make out that one of them +didn't know how to spell `stupid,' and that he had to ask his +neighbour to tell him. `A nice muddle their slates'll be in +before the trial's over!' thought Alice. + + One of the jurors had a pencil that squeaked. This of course, +Alice could not stand, and she went round the court and got +behind him, and very soon found an opportunity of taking it +away. She did it so quickly that the poor little juror (it was +Bill, the Lizard) could not make out at all what had become of +it; so, after hunting all about for it, he was obliged to write +with one finger for the rest of the day; and this was of very +little use, as it left no mark on the slate. + + `Herald, read the accusation!' said the King. + + On this the White Rabbit blew three blasts on the trumpet, and +then unrolled the parchment scroll, and read as follows:-- + + `The Queen of Hearts, she made some tarts, + All on a summer day: + The Knave of Hearts, he stole those tarts, + And took them quite away!' + + `Consider your verdict,' the King said to the jury. + + `Not yet, not yet!' the Rabbit hastily interrupted. `There's +a great deal to come before that!' + + `Call the first witness,' said the King; and the White Rabbit +blew three blasts on the trumpet, and called out, `First +witness!' + + The first witness was the Hatter. He came in with a teacup in +one hand and a piece of bread-and-butter in the other. `I beg +pardon, your Majesty,' he began, `for bringing these in: but I +hadn't quite finished my tea when I was sent for.' + + `You ought to have finished,' said the King. `When did you +begin?' + + The Hatter looked at the March Hare, who had followed him into +the court, arm-in-arm with the Dormouse. `Fourteenth of March, I +think it was,' he said. + + `Fifteenth,' said the March Hare. + + `Sixteenth,' added the Dormouse. + + `Write that down,' the King said to the jury, and the jury +eagerly wrote down all three dates on their slates, and then +added them up, and reduced the answer to shillings and pence. + + `Take off your hat,' the King said to the Hatter. + + `It isn't mine,' said the Hatter. + + `Stolen!' the King exclaimed, turning to the jury, who +instantly made a memorandum of the fact. + + `I keep them to sell,' the Hatter added as an explanation; +`I've none of my own. I'm a hatter.' + + Here the Queen put on her spectacles, and began staring at the +Hatter, who turned pale and fidgeted. + + `Give your evidence,' said the King; `and don't be nervous, or +I'll have you executed on the spot.' + + This did not seem to encourage the witness at all: he kept +shifting from one foot to the other, looking uneasily at the +Queen, and in his confusion he bit a large piece out of his +teacup instead of the bread-and-butter. + + Just at this moment Alice felt a very curious sensation, which +puzzled her a good deal until she made out what it was: she was +beginning to grow larger again, and she thought at first she +would get up and leave the court; but on second thoughts she +decided to remain where she was as long as there was room for +her. + + `I wish you wouldn't squeeze so.' said the Dormouse, who was +sitting next to her. `I can hardly breathe.' + + `I can't help it,' said Alice very meekly: `I'm growing.' + + `You've no right to grow here,' said the Dormouse. + + `Don't talk nonsense,' said Alice more boldly: `you know +you're growing too.' + + `Yes, but I grow at a reasonable pace,' said the Dormouse: +`not in that ridiculous fashion.' And he got up very sulkily +and crossed over to the other side of the court. + + All this time the Queen had never left off staring at the +Hatter, and, just as the Dormouse crossed the court, she said to +one of the officers of the court, `Bring me the list of the +singers in the last concert!' on which the wretched Hatter +trembled so, that he shook both his shoes off. + + `Give your evidence,' the King repeated angrily, `or I'll have +you executed, whether you're nervous or not.' + + `I'm a poor man, your Majesty,' the Hatter began, in a +trembling voice, `--and I hadn't begun my tea--not above a week +or so--and what with the bread-and-butter getting so thin--and +the twinkling of the tea--' + + `The twinkling of the what?' said the King. + + `It began with the tea,' the Hatter replied. + + `Of course twinkling begins with a T!' said the King sharply. +`Do you take me for a dunce? Go on!' + + `I'm a poor man,' the Hatter went on, `and most things +twinkled after that--only the March Hare said--' + + `I didn't!' the March Hare interrupted in a great hurry. + + `You did!' said the Hatter. + + `I deny it!' said the March Hare. + + `He denies it,' said the King: `leave out that part.' + + `Well, at any rate, the Dormouse said--' the Hatter went on, +looking anxiously round to see if he would deny it too: but the +Dormouse denied nothing, being fast asleep. + + `After that,' continued the Hatter, `I cut some more bread- +and-butter--' + + `But what did the Dormouse say?' one of the jury asked. + + `That I can't remember,' said the Hatter. + + `You MUST remember,' remarked the King, `or I'll have you +executed.' + + The miserable Hatter dropped his teacup and bread-and-butter, +and went down on one knee. `I'm a poor man, your Majesty,' he +began. + + `You're a very poor speaker,' said the King. + + Here one of the guinea-pigs cheered, and was immediately +suppressed by the officers of the court. (As that is rather a +hard word, I will just explain to you how it was done. They had +a large canvas bag, which tied up at the mouth with strings: +into this they slipped the guinea-pig, head first, and then sat +upon it.) + + `I'm glad I've seen that done,' thought Alice. `I've so often +read in the newspapers, at the end of trials, "There was some +attempts at applause, which was immediately suppressed by the +officers of the court," and I never understood what it meant +till now.' + + `If that's all you know about it, you may stand down,' +continued the King. + + `I can't go no lower,' said the Hatter: `I'm on the floor, as +it is.' + + `Then you may SIT down,' the King replied. + + Here the other guinea-pig cheered, and was suppressed. + + `Come, that finished the guinea-pigs!' thought Alice. `Now we +shall get on better.' + + `I'd rather finish my tea,' said the Hatter, with an anxious +look at the Queen, who was reading the list of singers. + + `You may go,' said the King, and the Hatter hurriedly left the +court, without even waiting to put his shoes on. + + `--and just take his head off outside,' the Queen added to one +of the officers: but the Hatter was out of sight before the +officer could get to the door. + + `Call the next witness!' said the King. + + The next witness was the Duchess's cook. She carried the +pepper-box in her hand, and Alice guessed who it was, even before +she got into the court, by the way the people near the door began +sneezing all at once. + + `Give your evidence,' said the King. + + `Shan't,' said the cook. + + The King looked anxiously at the White Rabbit, who said in a +low voice, `Your Majesty must cross-examine THIS witness.' + + `Well, if I must, I must,' the King said, with a melancholy +air, and, after folding his arms and frowning at the cook till +his eyes were nearly out of sight, he said in a deep voice, `What +are tarts made of?' + + `Pepper, mostly,' said the cook. + + `Treacle,' said a sleepy voice behind her. + + `Collar that Dormouse,' the Queen shrieked out. `Behead that +Dormouse! Turn that Dormouse out of court! Suppress him! Pinch +him! Off with his whiskers!' + + For some minutes the whole court was in confusion, getting the +Dormouse turned out, and, by the time they had settled down +again, the cook had disappeared. + + `Never mind!' said the King, with an air of great relief. +`Call the next witness.' And he added in an undertone to the +Queen, `Really, my dear, YOU must cross-examine the next witness. +It quite makes my forehead ache!' + + Alice watched the White Rabbit as he fumbled over the list, +feeling very curious to see what the next witness would be like, +`--for they haven't got much evidence YET,' she said to herself. +Imagine her surprise, when the White Rabbit read out, at the top +of his shrill little voice, the name `Alice!' + + + + CHAPTER XII + + Alice's Evidence + + + `Here!' cried Alice, quite forgetting in the flurry of the +moment how large she had grown in the last few minutes, and she +jumped up in such a hurry that she tipped over the jury-box with +the edge of her skirt, upsetting all the jurymen on to the heads +of the crowd below, and there they lay sprawling about, reminding +her very much of a globe of goldfish she had accidentally upset +the week before. + + `Oh, I BEG your pardon!' she exclaimed in a tone of great +dismay, and began picking them up again as quickly as she could, +for the accident of the goldfish kept running in her head, and +she had a vague sort of idea that they must be collected at once +and put back into the jury-box, or they would die. + + `The trial cannot proceed,' said the King in a very grave +voice, `until all the jurymen are back in their proper places-- +ALL,' he repeated with great emphasis, looking hard at Alice as +he said do. + + Alice looked at the jury-box, and saw that, in her haste, she +had put the Lizard in head downwards, and the poor little thing +was waving its tail about in a melancholy way, being quite unable +to move. She soon got it out again, and put it right; `not that +it signifies much,' she said to herself; `I should think it +would be QUITE as much use in the trial one way up as the other.' + + As soon as the jury had a little recovered from the shock of +being upset, and their slates and pencils had been found and +handed back to them, they set to work very diligently to write +out a history of the accident, all except the Lizard, who seemed +too much overcome to do anything but sit with its mouth open, +gazing up into the roof of the court. + + `What do you know about this business?' the King said to +Alice. + + `Nothing,' said Alice. + + `Nothing WHATEVER?' persisted the King. + + `Nothing whatever,' said Alice. + + `That's very important,' the King said, turning to the jury. +They were just beginning to write this down on their slates, when +the White Rabbit interrupted: `UNimportant, your Majesty means, +of course,' he said in a very respectful tone, but frowning and +making faces at him as he spoke. + + `UNimportant, of course, I meant,' the King hastily said, and +went on to himself in an undertone, `important--unimportant-- +unimportant--important--' as if he were trying which word +sounded best. + + Some of the jury wrote it down `important,' and some +`unimportant.' Alice could see this, as she was near enough to +look over their slates; `but it doesn't matter a bit,' she +thought to herself. + + At this moment the King, who had been for some time busily +writing in his note-book, cackled out `Silence!' and read out +from his book, `Rule Forty-two. ALL PERSONS MORE THAN A MILE +HIGH TO LEAVE THE COURT.' + + Everybody looked at Alice. + + `I'M not a mile high,' said Alice. + + `You are,' said the King. + + `Nearly two miles high,' added the Queen. + + `Well, I shan't go, at any rate,' said Alice: `besides, +that's not a regular rule: you invented it just now.' + + `It's the oldest rule in the book,' said the King. + + `Then it ought to be Number One,' said Alice. + + The King turned pale, and shut his note-book hastily. +`Consider your verdict,' he said to the jury, in a low, trembling +voice. + + `There's more evidence to come yet, please your Majesty,' said +the White Rabbit, jumping up in a great hurry; `this paper has +just been picked up.' + + `What's in it?' said the Queen. + + `I haven't opened it yet,' said the White Rabbit, `but it seems +to be a letter, written by the prisoner to--to somebody.' + + `It must have been that,' said the King, `unless it was +written to nobody, which isn't usual, you know.' + + `Who is it directed to?' said one of the jurymen. + + `It isn't directed at all,' said the White Rabbit; `in fact, +there's nothing written on the OUTSIDE.' He unfolded the paper +as he spoke, and added `It isn't a letter, after all: it's a set +of verses.' + + `Are they in the prisoner's handwriting?' asked another of +they jurymen. + + `No, they're not,' said the White Rabbit, `and that's the +queerest thing about it.' (The jury all looked puzzled.) + + `He must have imitated somebody else's hand,' said the King. +(The jury all brightened up again.) + + `Please your Majesty,' said the Knave, `I didn't write it, and +they can't prove I did: there's no name signed at the end.' + + `If you didn't sign it,' said the King, `that only makes the +matter worse. You MUST have meant some mischief, or else you'd +have signed your name like an honest man.' + + There was a general clapping of hands at this: it was the +first really clever thing the King had said that day. + + `That PROVES his guilt,' said the Queen. + + `It proves nothing of the sort!' said Alice. `Why, you don't +even know what they're about!' + + `Read them,' said the King. + + The White Rabbit put on his spectacles. `Where shall I begin, +please your Majesty?' he asked. + + `Begin at the beginning,' the King said gravely, `and go on +till you come to the end: then stop.' + + These were the verses the White Rabbit read:-- + + `They told me you had been to her, + And mentioned me to him: + She gave me a good character, + But said I could not swim. + + He sent them word I had not gone + (We know it to be true): + If she should push the matter on, + What would become of you? + + I gave her one, they gave him two, + You gave us three or more; + They all returned from him to you, + Though they were mine before. + + If I or she should chance to be + Involved in this affair, + He trusts to you to set them free, + Exactly as we were. + + My notion was that you had been + (Before she had this fit) + An obstacle that came between + Him, and ourselves, and it. + + Don't let him know she liked them best, + For this must ever be + A secret, kept from all the rest, + Between yourself and me.' + + `That's the most important piece of evidence we've heard yet,' +said the King, rubbing his hands; `so now let the jury--' + + `If any one of them can explain it,' said Alice, (she had +grown so large in the last few minutes that she wasn't a bit +afraid of interrupting him,) `I'll give him sixpence. _I_ don't +believe there's an atom of meaning in it.' + + The jury all wrote down on their slates, `SHE doesn't believe +there's an atom of meaning in it,' but none of them attempted to +explain the paper. + + `If there's no meaning in it,' said the King, `that saves a +world of trouble, you know, as we needn't try to find any. And +yet I don't know,' he went on, spreading out the verses on his +knee, and looking at them with one eye; `I seem to see some +meaning in them, after all. "--SAID I COULD NOT SWIM--" you +can't swim, can you?' he added, turning to the Knave. + + The Knave shook his head sadly. `Do I look like it?' he said. +(Which he certainly did NOT, being made entirely of cardboard.) + + `All right, so far,' said the King, and he went on muttering +over the verses to himself: `"WE KNOW IT TO BE TRUE--" that's +the jury, of course-- "I GAVE HER ONE, THEY GAVE HIM TWO--" why, +that must be what he did with the tarts, you know--' + + `But, it goes on "THEY ALL RETURNED FROM HIM TO YOU,"' said +Alice. + + `Why, there they are!' said the King triumphantly, pointing to +the tarts on the table. `Nothing can be clearer than THAT. +Then again--"BEFORE SHE HAD THIS FIT--" you never had fits, my +dear, I think?' he said to the Queen. + + `Never!' said the Queen furiously, throwing an inkstand at the +Lizard as she spoke. (The unfortunate little Bill had left off +writing on his slate with one finger, as he found it made no +mark; but he now hastily began again, using the ink, that was +trickling down his face, as long as it lasted.) + + `Then the words don't FIT you,' said the King, looking round +the court with a smile. There was a dead silence. + + `It's a pun!' the King added in an offended tone, and +everybody laughed, `Let the jury consider their verdict,' the +King said, for about the twentieth time that day. + + `No, no!' said the Queen. `Sentence first--verdict afterwards.' + + `Stuff and nonsense!' said Alice loudly. `The idea of having +the sentence first!' + + `Hold your tongue!' said the Queen, turning purple. + + `I won't!' said Alice. + + `Off with her head!' the Queen shouted at the top of her voice. +Nobody moved. + + `Who cares for you?' said Alice, (she had grown to her full +size by this time.) `You're nothing but a pack of cards!' + + At this the whole pack rose up into the air, and came flying +down upon her: she gave a little scream, half of fright and half +of anger, and tried to beat them off, and found herself lying on +the bank, with her head in the lap of her sister, who was gently +brushing away some dead leaves that had fluttered down from the +trees upon her face. + + `Wake up, Alice dear!' said her sister; `Why, what a long +sleep you've had!' + + `Oh, I've had such a curious dream!' said Alice, and she told +her sister, as well as she could remember them, all these strange +Adventures of hers that you have just been reading about; and +when she had finished, her sister kissed her, and said, `It WAS a +curious dream, dear, certainly: but now run in to your tea; it's +getting late.' So Alice got up and ran off, thinking while she +ran, as well she might, what a wonderful dream it had been. + + But her sister sat still just as she left her, leaning her +head on her hand, watching the setting sun, and thinking of +little Alice and all her wonderful Adventures, till she too began +dreaming after a fashion, and this was her dream:-- + + First, she dreamed of little Alice herself, and once again the +tiny hands were clasped upon her knee, and the bright eager eyes +were looking up into hers--she could hear the very tones of her +voice, and see that queer little toss of her head to keep back +the wandering hair that WOULD always get into her eyes--and +still as she listened, or seemed to listen, the whole place +around her became alive the strange creatures of her little +sister's dream. + + The long grass rustled at her feet as the White Rabbit hurried +by--the frightened Mouse splashed his way through the +neighbouring pool--she could hear the rattle of the teacups as +the March Hare and his friends shared their never-ending meal, +and the shrill voice of the Queen ordering off her unfortunate +guests to execution--once more the pig-baby was sneezing on the +Duchess's knee, while plates and dishes crashed around it--once +more the shriek of the Gryphon, the squeaking of the Lizard's +slate-pencil, and the choking of the suppressed guinea-pigs, +filled the air, mixed up with the distant sobs of the miserable +Mock Turtle. + + So she sat on, with closed eyes, and half believed herself in +Wonderland, though she knew she had but to open them again, and +all would change to dull reality--the grass would be only +rustling in the wind, and the pool rippling to the waving of the +reeds--the rattling teacups would change to tinkling sheep- +bells, and the Queen's shrill cries to the voice of the shepherd +boy--and the sneeze of the baby, the shriek of the Gryphon, and +all thy other queer noises, would change (she knew) to the +confused clamour of the busy farm-yard--while the lowing of the +cattle in the distance would take the place of the Mock Turtle's +heavy sobs. + + Lastly, she pictured to herself how this same little sister of +hers would, in the after-time, be herself a grown woman; and how +she would keep, through all her riper years, the simple and +loving heart of her childhood: and how she would gather about +her other little children, and make THEIR eyes bright and eager +with many a strange tale, perhaps even with the dream of +Wonderland of long ago: and how she would feel with all their +simple sorrows, and find a pleasure in all their simple joys, +remembering her own child-life, and the happy summer days. + + THE END + \ No newline at end of file diff --git a/snappy/snappy-1.0.5/testdata/asyoulik.txt b/snappy/snappy-1.0.5/testdata/asyoulik.txt new file mode 100644 index 00000000..88dc7b60 --- /dev/null +++ b/snappy/snappy-1.0.5/testdata/asyoulik.txt @@ -0,0 +1,4122 @@ + AS YOU LIKE IT + + + DRAMATIS PERSONAE + + +DUKE SENIOR living in banishment. + +DUKE FREDERICK his brother, an usurper of his dominions. + + +AMIENS | + | lords attending on the banished duke. +JAQUES | + + +LE BEAU a courtier attending upon Frederick. + +CHARLES wrestler to Frederick. + + +OLIVER | + | +JAQUES (JAQUES DE BOYS:) | sons of Sir Rowland de Boys. + | +ORLANDO | + + +ADAM | + | servants to Oliver. +DENNIS | + + +TOUCHSTONE a clown. + +SIR OLIVER MARTEXT a vicar. + + +CORIN | + | shepherds. +SILVIUS | + + +WILLIAM a country fellow in love with Audrey. + + A person representing HYMEN. (HYMEN:) + +ROSALIND daughter to the banished duke. + +CELIA daughter to Frederick. + +PHEBE a shepherdess. + +AUDREY a country wench. + + Lords, pages, and attendants, &c. + (Forester:) + (A Lord:) + (First Lord:) + (Second Lord:) + (First Page:) + (Second Page:) + + +SCENE Oliver's house; Duke Frederick's court; and the + Forest of Arden. + + + + + AS YOU LIKE IT + + +ACT I + + + +SCENE I Orchard of Oliver's house. + + + [Enter ORLANDO and ADAM] + +ORLANDO As I remember, Adam, it was upon this fashion + bequeathed me by will but poor a thousand crowns, + and, as thou sayest, charged my brother, on his + blessing, to breed me well: and there begins my + sadness. My brother Jaques he keeps at school, and + report speaks goldenly of his profit: for my part, + he keeps me rustically at home, or, to speak more + properly, stays me here at home unkept; for call you + that keeping for a gentleman of my birth, that + differs not from the stalling of an ox? His horses + are bred better; for, besides that they are fair + with their feeding, they are taught their manage, + and to that end riders dearly hired: but I, his + brother, gain nothing under him but growth; for the + which his animals on his dunghills are as much + bound to him as I. Besides this nothing that he so + plentifully gives me, the something that nature gave + me his countenance seems to take from me: he lets + me feed with his hinds, bars me the place of a + brother, and, as much as in him lies, mines my + gentility with my education. This is it, Adam, that + grieves me; and the spirit of my father, which I + think is within me, begins to mutiny against this + servitude: I will no longer endure it, though yet I + know no wise remedy how to avoid it. + +ADAM Yonder comes my master, your brother. + +ORLANDO Go apart, Adam, and thou shalt hear how he will + shake me up. + + [Enter OLIVER] + +OLIVER Now, sir! what make you here? + +ORLANDO Nothing: I am not taught to make any thing. + +OLIVER What mar you then, sir? + +ORLANDO Marry, sir, I am helping you to mar that which God + made, a poor unworthy brother of yours, with idleness. + +OLIVER Marry, sir, be better employed, and be naught awhile. + +ORLANDO Shall I keep your hogs and eat husks with them? + What prodigal portion have I spent, that I should + come to such penury? + +OLIVER Know you where your are, sir? + +ORLANDO O, sir, very well; here in your orchard. + +OLIVER Know you before whom, sir? + +ORLANDO Ay, better than him I am before knows me. I know + you are my eldest brother; and, in the gentle + condition of blood, you should so know me. The + courtesy of nations allows you my better, in that + you are the first-born; but the same tradition + takes not away my blood, were there twenty brothers + betwixt us: I have as much of my father in me as + you; albeit, I confess, your coming before me is + nearer to his reverence. + +OLIVER What, boy! + +ORLANDO Come, come, elder brother, you are too young in this. + +OLIVER Wilt thou lay hands on me, villain? + +ORLANDO I am no villain; I am the youngest son of Sir + Rowland de Boys; he was my father, and he is thrice + a villain that says such a father begot villains. + Wert thou not my brother, I would not take this hand + from thy throat till this other had pulled out thy + tongue for saying so: thou hast railed on thyself. + +ADAM Sweet masters, be patient: for your father's + remembrance, be at accord. + +OLIVER Let me go, I say. + +ORLANDO I will not, till I please: you shall hear me. My + father charged you in his will to give me good + education: you have trained me like a peasant, + obscuring and hiding from me all gentleman-like + qualities. The spirit of my father grows strong in + me, and I will no longer endure it: therefore allow + me such exercises as may become a gentleman, or + give me the poor allottery my father left me by + testament; with that I will go buy my fortunes. + +OLIVER And what wilt thou do? beg, when that is spent? + Well, sir, get you in: I will not long be troubled + with you; you shall have some part of your will: I + pray you, leave me. + +ORLANDO I will no further offend you than becomes me for my good. + +OLIVER Get you with him, you old dog. + +ADAM Is 'old dog' my reward? Most true, I have lost my + teeth in your service. God be with my old master! + he would not have spoke such a word. + + [Exeunt ORLANDO and ADAM] + +OLIVER Is it even so? begin you to grow upon me? I will + physic your rankness, and yet give no thousand + crowns neither. Holla, Dennis! + + [Enter DENNIS] + +DENNIS Calls your worship? + +OLIVER Was not Charles, the duke's wrestler, here to speak with me? + +DENNIS So please you, he is here at the door and importunes + access to you. + +OLIVER Call him in. + + [Exit DENNIS] + + 'Twill be a good way; and to-morrow the wrestling is. + + [Enter CHARLES] + +CHARLES Good morrow to your worship. + +OLIVER Good Monsieur Charles, what's the new news at the + new court? + +CHARLES There's no news at the court, sir, but the old news: + that is, the old duke is banished by his younger + brother the new duke; and three or four loving lords + have put themselves into voluntary exile with him, + whose lands and revenues enrich the new duke; + therefore he gives them good leave to wander. + +OLIVER Can you tell if Rosalind, the duke's daughter, be + banished with her father? + +CHARLES O, no; for the duke's daughter, her cousin, so loves + her, being ever from their cradles bred together, + that she would have followed her exile, or have died + to stay behind her. She is at the court, and no + less beloved of her uncle than his own daughter; and + never two ladies loved as they do. + +OLIVER Where will the old duke live? + +CHARLES They say he is already in the forest of Arden, and + a many merry men with him; and there they live like + the old Robin Hood of England: they say many young + gentlemen flock to him every day, and fleet the time + carelessly, as they did in the golden world. + +OLIVER What, you wrestle to-morrow before the new duke? + +CHARLES Marry, do I, sir; and I came to acquaint you with a + matter. I am given, sir, secretly to understand + that your younger brother Orlando hath a disposition + to come in disguised against me to try a fall. + To-morrow, sir, I wrestle for my credit; and he that + escapes me without some broken limb shall acquit him + well. Your brother is but young and tender; and, + for your love, I would be loath to foil him, as I + must, for my own honour, if he come in: therefore, + out of my love to you, I came hither to acquaint you + withal, that either you might stay him from his + intendment or brook such disgrace well as he shall + run into, in that it is a thing of his own search + and altogether against my will. + +OLIVER Charles, I thank thee for thy love to me, which + thou shalt find I will most kindly requite. I had + myself notice of my brother's purpose herein and + have by underhand means laboured to dissuade him from + it, but he is resolute. I'll tell thee, Charles: + it is the stubbornest young fellow of France, full + of ambition, an envious emulator of every man's + good parts, a secret and villanous contriver against + me his natural brother: therefore use thy + discretion; I had as lief thou didst break his neck + as his finger. And thou wert best look to't; for if + thou dost him any slight disgrace or if he do not + mightily grace himself on thee, he will practise + against thee by poison, entrap thee by some + treacherous device and never leave thee till he + hath ta'en thy life by some indirect means or other; + for, I assure thee, and almost with tears I speak + it, there is not one so young and so villanous this + day living. I speak but brotherly of him; but + should I anatomize him to thee as he is, I must + blush and weep and thou must look pale and wonder. + +CHARLES I am heartily glad I came hither to you. If he come + to-morrow, I'll give him his payment: if ever he go + alone again, I'll never wrestle for prize more: and + so God keep your worship! + +OLIVER Farewell, good Charles. + + [Exit CHARLES] + + Now will I stir this gamester: I hope I shall see + an end of him; for my soul, yet I know not why, + hates nothing more than he. Yet he's gentle, never + schooled and yet learned, full of noble device, of + all sorts enchantingly beloved, and indeed so much + in the heart of the world, and especially of my own + people, who best know him, that I am altogether + misprised: but it shall not be so long; this + wrestler shall clear all: nothing remains but that + I kindle the boy thither; which now I'll go about. + + [Exit] + + + + + AS YOU LIKE IT + + +ACT I + + + +SCENE II Lawn before the Duke's palace. + + + [Enter CELIA and ROSALIND] + +CELIA I pray thee, Rosalind, sweet my coz, be merry. + +ROSALIND Dear Celia, I show more mirth than I am mistress of; + and would you yet I were merrier? Unless you could + teach me to forget a banished father, you must not + learn me how to remember any extraordinary pleasure. + +CELIA Herein I see thou lovest me not with the full weight + that I love thee. If my uncle, thy banished father, + had banished thy uncle, the duke my father, so thou + hadst been still with me, I could have taught my + love to take thy father for mine: so wouldst thou, + if the truth of thy love to me were so righteously + tempered as mine is to thee. + +ROSALIND Well, I will forget the condition of my estate, to + rejoice in yours. + +CELIA You know my father hath no child but I, nor none is + like to have: and, truly, when he dies, thou shalt + be his heir, for what he hath taken away from thy + father perforce, I will render thee again in + affection; by mine honour, I will; and when I break + that oath, let me turn monster: therefore, my + sweet Rose, my dear Rose, be merry. + +ROSALIND From henceforth I will, coz, and devise sports. Let + me see; what think you of falling in love? + +CELIA Marry, I prithee, do, to make sport withal: but + love no man in good earnest; nor no further in sport + neither than with safety of a pure blush thou mayst + in honour come off again. + +ROSALIND What shall be our sport, then? + +CELIA Let us sit and mock the good housewife Fortune from + her wheel, that her gifts may henceforth be bestowed equally. + +ROSALIND I would we could do so, for her benefits are + mightily misplaced, and the bountiful blind woman + doth most mistake in her gifts to women. + +CELIA 'Tis true; for those that she makes fair she scarce + makes honest, and those that she makes honest she + makes very ill-favouredly. + +ROSALIND Nay, now thou goest from Fortune's office to + Nature's: Fortune reigns in gifts of the world, + not in the lineaments of Nature. + + [Enter TOUCHSTONE] + +CELIA No? when Nature hath made a fair creature, may she + not by Fortune fall into the fire? Though Nature + hath given us wit to flout at Fortune, hath not + Fortune sent in this fool to cut off the argument? + +ROSALIND Indeed, there is Fortune too hard for Nature, when + Fortune makes Nature's natural the cutter-off of + Nature's wit. + +CELIA Peradventure this is not Fortune's work neither, but + Nature's; who perceiveth our natural wits too dull + to reason of such goddesses and hath sent this + natural for our whetstone; for always the dulness of + the fool is the whetstone of the wits. How now, + wit! whither wander you? + +TOUCHSTONE Mistress, you must come away to your father. + +CELIA Were you made the messenger? + +TOUCHSTONE No, by mine honour, but I was bid to come for you. + +ROSALIND Where learned you that oath, fool? + +TOUCHSTONE Of a certain knight that swore by his honour they + were good pancakes and swore by his honour the + mustard was naught: now I'll stand to it, the + pancakes were naught and the mustard was good, and + yet was not the knight forsworn. + +CELIA How prove you that, in the great heap of your + knowledge? + +ROSALIND Ay, marry, now unmuzzle your wisdom. + +TOUCHSTONE Stand you both forth now: stroke your chins, and + swear by your beards that I am a knave. + +CELIA By our beards, if we had them, thou art. + +TOUCHSTONE By my knavery, if I had it, then I were; but if you + swear by that that is not, you are not forsworn: no + more was this knight swearing by his honour, for he + never had any; or if he had, he had sworn it away + before ever he saw those pancakes or that mustard. + +CELIA Prithee, who is't that thou meanest? + +TOUCHSTONE One that old Frederick, your father, loves. + +CELIA My father's love is enough to honour him: enough! + speak no more of him; you'll be whipped for taxation + one of these days. + +TOUCHSTONE The more pity, that fools may not speak wisely what + wise men do foolishly. + +CELIA By my troth, thou sayest true; for since the little + wit that fools have was silenced, the little foolery + that wise men have makes a great show. Here comes + Monsieur Le Beau. + +ROSALIND With his mouth full of news. + +CELIA Which he will put on us, as pigeons feed their young. + +ROSALIND Then shall we be news-crammed. + +CELIA All the better; we shall be the more marketable. + + [Enter LE BEAU] + + Bon jour, Monsieur Le Beau: what's the news? + +LE BEAU Fair princess, you have lost much good sport. + +CELIA Sport! of what colour? + +LE BEAU What colour, madam! how shall I answer you? + +ROSALIND As wit and fortune will. + +TOUCHSTONE Or as the Destinies decree. + +CELIA Well said: that was laid on with a trowel. + +TOUCHSTONE Nay, if I keep not my rank,-- + +ROSALIND Thou losest thy old smell. + +LE BEAU You amaze me, ladies: I would have told you of good + wrestling, which you have lost the sight of. + +ROSALIND You tell us the manner of the wrestling. + +LE BEAU I will tell you the beginning; and, if it please + your ladyships, you may see the end; for the best is + yet to do; and here, where you are, they are coming + to perform it. + +CELIA Well, the beginning, that is dead and buried. + +LE BEAU There comes an old man and his three sons,-- + +CELIA I could match this beginning with an old tale. + +LE BEAU Three proper young men, of excellent growth and presence. + +ROSALIND With bills on their necks, 'Be it known unto all men + by these presents.' + +LE BEAU The eldest of the three wrestled with Charles, the + duke's wrestler; which Charles in a moment threw him + and broke three of his ribs, that there is little + hope of life in him: so he served the second, and + so the third. Yonder they lie; the poor old man, + their father, making such pitiful dole over them + that all the beholders take his part with weeping. + +ROSALIND Alas! + +TOUCHSTONE But what is the sport, monsieur, that the ladies + have lost? + +LE BEAU Why, this that I speak of. + +TOUCHSTONE Thus men may grow wiser every day: it is the first + time that ever I heard breaking of ribs was sport + for ladies. + +CELIA Or I, I promise thee. + +ROSALIND But is there any else longs to see this broken music + in his sides? is there yet another dotes upon + rib-breaking? Shall we see this wrestling, cousin? + +LE BEAU You must, if you stay here; for here is the place + appointed for the wrestling, and they are ready to + perform it. + +CELIA Yonder, sure, they are coming: let us now stay and see it. + + [Flourish. Enter DUKE FREDERICK, Lords, ORLANDO, + CHARLES, and Attendants] + +DUKE FREDERICK Come on: since the youth will not be entreated, his + own peril on his forwardness. + +ROSALIND Is yonder the man? + +LE BEAU Even he, madam. + +CELIA Alas, he is too young! yet he looks successfully. + +DUKE FREDERICK How now, daughter and cousin! are you crept hither + to see the wrestling? + +ROSALIND Ay, my liege, so please you give us leave. + +DUKE FREDERICK You will take little delight in it, I can tell you; + there is such odds in the man. In pity of the + challenger's youth I would fain dissuade him, but he + will not be entreated. Speak to him, ladies; see if + you can move him. + +CELIA Call him hither, good Monsieur Le Beau. + +DUKE FREDERICK Do so: I'll not be by. + +LE BEAU Monsieur the challenger, the princesses call for you. + +ORLANDO I attend them with all respect and duty. + +ROSALIND Young man, have you challenged Charles the wrestler? + +ORLANDO No, fair princess; he is the general challenger: I + come but in, as others do, to try with him the + strength of my youth. + +CELIA Young gentleman, your spirits are too bold for your + years. You have seen cruel proof of this man's + strength: if you saw yourself with your eyes or + knew yourself with your judgment, the fear of your + adventure would counsel you to a more equal + enterprise. We pray you, for your own sake, to + embrace your own safety and give over this attempt. + +ROSALIND Do, young sir; your reputation shall not therefore + be misprised: we will make it our suit to the duke + that the wrestling might not go forward. + +ORLANDO I beseech you, punish me not with your hard + thoughts; wherein I confess me much guilty, to deny + so fair and excellent ladies any thing. But let + your fair eyes and gentle wishes go with me to my + trial: wherein if I be foiled, there is but one + shamed that was never gracious; if killed, but one + dead that was willing to be so: I shall do my + friends no wrong, for I have none to lament me, the + world no injury, for in it I have nothing; only in + the world I fill up a place, which may be better + supplied when I have made it empty. + +ROSALIND The little strength that I have, I would it were with you. + +CELIA And mine, to eke out hers. + +ROSALIND Fare you well: pray heaven I be deceived in you! + +CELIA Your heart's desires be with you! + +CHARLES Come, where is this young gallant that is so + desirous to lie with his mother earth? + +ORLANDO Ready, sir; but his will hath in it a more modest working. + +DUKE FREDERICK You shall try but one fall. + +CHARLES No, I warrant your grace, you shall not entreat him + to a second, that have so mightily persuaded him + from a first. + +ORLANDO An you mean to mock me after, you should not have + mocked me before: but come your ways. + +ROSALIND Now Hercules be thy speed, young man! + +CELIA I would I were invisible, to catch the strong + fellow by the leg. + + [They wrestle] + +ROSALIND O excellent young man! + +CELIA If I had a thunderbolt in mine eye, I can tell who + should down. + + [Shout. CHARLES is thrown] + +DUKE FREDERICK No more, no more. + +ORLANDO Yes, I beseech your grace: I am not yet well breathed. + +DUKE FREDERICK How dost thou, Charles? + +LE BEAU He cannot speak, my lord. + +DUKE FREDERICK Bear him away. What is thy name, young man? + +ORLANDO Orlando, my liege; the youngest son of Sir Rowland de Boys. + +DUKE FREDERICK I would thou hadst been son to some man else: + The world esteem'd thy father honourable, + But I did find him still mine enemy: + Thou shouldst have better pleased me with this deed, + Hadst thou descended from another house. + But fare thee well; thou art a gallant youth: + I would thou hadst told me of another father. + + [Exeunt DUKE FREDERICK, train, and LE BEAU] + +CELIA Were I my father, coz, would I do this? + +ORLANDO I am more proud to be Sir Rowland's son, + His youngest son; and would not change that calling, + To be adopted heir to Frederick. + +ROSALIND My father loved Sir Rowland as his soul, + And all the world was of my father's mind: + Had I before known this young man his son, + I should have given him tears unto entreaties, + Ere he should thus have ventured. + +CELIA Gentle cousin, + Let us go thank him and encourage him: + My father's rough and envious disposition + Sticks me at heart. Sir, you have well deserved: + If you do keep your promises in love + But justly, as you have exceeded all promise, + Your mistress shall be happy. + +ROSALIND Gentleman, + + [Giving him a chain from her neck] + + Wear this for me, one out of suits with fortune, + That could give more, but that her hand lacks means. + Shall we go, coz? + +CELIA Ay. Fare you well, fair gentleman. + +ORLANDO Can I not say, I thank you? My better parts + Are all thrown down, and that which here stands up + Is but a quintain, a mere lifeless block. + +ROSALIND He calls us back: my pride fell with my fortunes; + I'll ask him what he would. Did you call, sir? + Sir, you have wrestled well and overthrown + More than your enemies. + +CELIA Will you go, coz? + +ROSALIND Have with you. Fare you well. + + [Exeunt ROSALIND and CELIA] + +ORLANDO What passion hangs these weights upon my tongue? + I cannot speak to her, yet she urged conference. + O poor Orlando, thou art overthrown! + Or Charles or something weaker masters thee. + + [Re-enter LE BEAU] + +LE BEAU Good sir, I do in friendship counsel you + To leave this place. Albeit you have deserved + High commendation, true applause and love, + Yet such is now the duke's condition + That he misconstrues all that you have done. + The duke is humorous; what he is indeed, + More suits you to conceive than I to speak of. + +ORLANDO I thank you, sir: and, pray you, tell me this: + Which of the two was daughter of the duke + That here was at the wrestling? + +LE BEAU Neither his daughter, if we judge by manners; + But yet indeed the lesser is his daughter + The other is daughter to the banish'd duke, + And here detain'd by her usurping uncle, + To keep his daughter company; whose loves + Are dearer than the natural bond of sisters. + But I can tell you that of late this duke + Hath ta'en displeasure 'gainst his gentle niece, + Grounded upon no other argument + But that the people praise her for her virtues + And pity her for her good father's sake; + And, on my life, his malice 'gainst the lady + Will suddenly break forth. Sir, fare you well: + Hereafter, in a better world than this, + I shall desire more love and knowledge of you. + +ORLANDO I rest much bounden to you: fare you well. + + [Exit LE BEAU] + + Thus must I from the smoke into the smother; + From tyrant duke unto a tyrant brother: + But heavenly Rosalind! + + [Exit] + + + + + AS YOU LIKE IT + + +ACT I + + + +SCENE III A room in the palace. + + + [Enter CELIA and ROSALIND] + +CELIA Why, cousin! why, Rosalind! Cupid have mercy! not a word? + +ROSALIND Not one to throw at a dog. + +CELIA No, thy words are too precious to be cast away upon + curs; throw some of them at me; come, lame me with reasons. + +ROSALIND Then there were two cousins laid up; when the one + should be lamed with reasons and the other mad + without any. + +CELIA But is all this for your father? + +ROSALIND No, some of it is for my child's father. O, how + full of briers is this working-day world! + +CELIA They are but burs, cousin, thrown upon thee in + holiday foolery: if we walk not in the trodden + paths our very petticoats will catch them. + +ROSALIND I could shake them off my coat: these burs are in my heart. + +CELIA Hem them away. + +ROSALIND I would try, if I could cry 'hem' and have him. + +CELIA Come, come, wrestle with thy affections. + +ROSALIND O, they take the part of a better wrestler than myself! + +CELIA O, a good wish upon you! you will try in time, in + despite of a fall. But, turning these jests out of + service, let us talk in good earnest: is it + possible, on such a sudden, you should fall into so + strong a liking with old Sir Rowland's youngest son? + +ROSALIND The duke my father loved his father dearly. + +CELIA Doth it therefore ensue that you should love his son + dearly? By this kind of chase, I should hate him, + for my father hated his father dearly; yet I hate + not Orlando. + +ROSALIND No, faith, hate him not, for my sake. + +CELIA Why should I not? doth he not deserve well? + +ROSALIND Let me love him for that, and do you love him + because I do. Look, here comes the duke. + +CELIA With his eyes full of anger. + + [Enter DUKE FREDERICK, with Lords] + +DUKE FREDERICK Mistress, dispatch you with your safest haste + And get you from our court. + +ROSALIND Me, uncle? + +DUKE FREDERICK You, cousin + Within these ten days if that thou be'st found + So near our public court as twenty miles, + Thou diest for it. + +ROSALIND I do beseech your grace, + Let me the knowledge of my fault bear with me: + If with myself I hold intelligence + Or have acquaintance with mine own desires, + If that I do not dream or be not frantic,-- + As I do trust I am not--then, dear uncle, + Never so much as in a thought unborn + Did I offend your highness. + +DUKE FREDERICK Thus do all traitors: + If their purgation did consist in words, + They are as innocent as grace itself: + Let it suffice thee that I trust thee not. + +ROSALIND Yet your mistrust cannot make me a traitor: + Tell me whereon the likelihood depends. + +DUKE FREDERICK Thou art thy father's daughter; there's enough. + +ROSALIND So was I when your highness took his dukedom; + So was I when your highness banish'd him: + Treason is not inherited, my lord; + Or, if we did derive it from our friends, + What's that to me? my father was no traitor: + Then, good my liege, mistake me not so much + To think my poverty is treacherous. + +CELIA Dear sovereign, hear me speak. + +DUKE FREDERICK Ay, Celia; we stay'd her for your sake, + Else had she with her father ranged along. + +CELIA I did not then entreat to have her stay; + It was your pleasure and your own remorse: + I was too young that time to value her; + But now I know her: if she be a traitor, + Why so am I; we still have slept together, + Rose at an instant, learn'd, play'd, eat together, + And wheresoever we went, like Juno's swans, + Still we went coupled and inseparable. + +DUKE FREDERICK She is too subtle for thee; and her smoothness, + Her very silence and her patience + Speak to the people, and they pity her. + Thou art a fool: she robs thee of thy name; + And thou wilt show more bright and seem more virtuous + When she is gone. Then open not thy lips: + Firm and irrevocable is my doom + Which I have pass'd upon her; she is banish'd. + +CELIA Pronounce that sentence then on me, my liege: + I cannot live out of her company. + +DUKE FREDERICK You are a fool. You, niece, provide yourself: + If you outstay the time, upon mine honour, + And in the greatness of my word, you die. + + [Exeunt DUKE FREDERICK and Lords] + +CELIA O my poor Rosalind, whither wilt thou go? + Wilt thou change fathers? I will give thee mine. + I charge thee, be not thou more grieved than I am. + +ROSALIND I have more cause. + +CELIA Thou hast not, cousin; + Prithee be cheerful: know'st thou not, the duke + Hath banish'd me, his daughter? + +ROSALIND That he hath not. + +CELIA No, hath not? Rosalind lacks then the love + Which teacheth thee that thou and I am one: + Shall we be sunder'd? shall we part, sweet girl? + No: let my father seek another heir. + Therefore devise with me how we may fly, + Whither to go and what to bear with us; + And do not seek to take your change upon you, + To bear your griefs yourself and leave me out; + For, by this heaven, now at our sorrows pale, + Say what thou canst, I'll go along with thee. + +ROSALIND Why, whither shall we go? + +CELIA To seek my uncle in the forest of Arden. + +ROSALIND Alas, what danger will it be to us, + Maids as we are, to travel forth so far! + Beauty provoketh thieves sooner than gold. + +CELIA I'll put myself in poor and mean attire + And with a kind of umber smirch my face; + The like do you: so shall we pass along + And never stir assailants. + +ROSALIND Were it not better, + Because that I am more than common tall, + That I did suit me all points like a man? + A gallant curtle-axe upon my thigh, + A boar-spear in my hand; and--in my heart + Lie there what hidden woman's fear there will-- + We'll have a swashing and a martial outside, + As many other mannish cowards have + That do outface it with their semblances. + +CELIA What shall I call thee when thou art a man? + +ROSALIND I'll have no worse a name than Jove's own page; + And therefore look you call me Ganymede. + But what will you be call'd? + +CELIA Something that hath a reference to my state + No longer Celia, but Aliena. + +ROSALIND But, cousin, what if we assay'd to steal + The clownish fool out of your father's court? + Would he not be a comfort to our travel? + +CELIA He'll go along o'er the wide world with me; + Leave me alone to woo him. Let's away, + And get our jewels and our wealth together, + Devise the fittest time and safest way + To hide us from pursuit that will be made + After my flight. Now go we in content + To liberty and not to banishment. + + [Exeunt] + + + + + AS YOU LIKE IT + + +ACT II + + + +SCENE I The Forest of Arden. + + + [Enter DUKE SENIOR, AMIENS, and two or three Lords, + like foresters] + +DUKE SENIOR Now, my co-mates and brothers in exile, + Hath not old custom made this life more sweet + Than that of painted pomp? Are not these woods + More free from peril than the envious court? + Here feel we but the penalty of Adam, + The seasons' difference, as the icy fang + And churlish chiding of the winter's wind, + Which, when it bites and blows upon my body, + Even till I shrink with cold, I smile and say + 'This is no flattery: these are counsellors + That feelingly persuade me what I am.' + Sweet are the uses of adversity, + Which, like the toad, ugly and venomous, + Wears yet a precious jewel in his head; + And this our life exempt from public haunt + Finds tongues in trees, books in the running brooks, + Sermons in stones and good in every thing. + I would not change it. + +AMIENS Happy is your grace, + That can translate the stubbornness of fortune + Into so quiet and so sweet a style. + +DUKE SENIOR Come, shall we go and kill us venison? + And yet it irks me the poor dappled fools, + Being native burghers of this desert city, + Should in their own confines with forked heads + Have their round haunches gored. + +First Lord Indeed, my lord, + The melancholy Jaques grieves at that, + And, in that kind, swears you do more usurp + Than doth your brother that hath banish'd you. + To-day my Lord of Amiens and myself + Did steal behind him as he lay along + Under an oak whose antique root peeps out + Upon the brook that brawls along this wood: + To the which place a poor sequester'd stag, + That from the hunter's aim had ta'en a hurt, + Did come to languish, and indeed, my lord, + The wretched animal heaved forth such groans + That their discharge did stretch his leathern coat + Almost to bursting, and the big round tears + Coursed one another down his innocent nose + In piteous chase; and thus the hairy fool + Much marked of the melancholy Jaques, + Stood on the extremest verge of the swift brook, + Augmenting it with tears. + +DUKE SENIOR But what said Jaques? + Did he not moralize this spectacle? + +First Lord O, yes, into a thousand similes. + First, for his weeping into the needless stream; + 'Poor deer,' quoth he, 'thou makest a testament + As worldlings do, giving thy sum of more + To that which had too much:' then, being there alone, + Left and abandon'd of his velvet friends, + ''Tis right:' quoth he; 'thus misery doth part + The flux of company:' anon a careless herd, + Full of the pasture, jumps along by him + And never stays to greet him; 'Ay' quoth Jaques, + 'Sweep on, you fat and greasy citizens; + 'Tis just the fashion: wherefore do you look + Upon that poor and broken bankrupt there?' + Thus most invectively he pierceth through + The body of the country, city, court, + Yea, and of this our life, swearing that we + Are mere usurpers, tyrants and what's worse, + To fright the animals and to kill them up + In their assign'd and native dwelling-place. + +DUKE SENIOR And did you leave him in this contemplation? + +Second Lord We did, my lord, weeping and commenting + Upon the sobbing deer. + +DUKE SENIOR Show me the place: + I love to cope him in these sullen fits, + For then he's full of matter. + +First Lord I'll bring you to him straight. + + [Exeunt] + + + + + AS YOU LIKE IT + + +ACT II + + + +SCENE II A room in the palace. + + + [Enter DUKE FREDERICK, with Lords] + +DUKE FREDERICK Can it be possible that no man saw them? + It cannot be: some villains of my court + Are of consent and sufferance in this. + +First Lord I cannot hear of any that did see her. + The ladies, her attendants of her chamber, + Saw her abed, and in the morning early + They found the bed untreasured of their mistress. + +Second Lord My lord, the roynish clown, at whom so oft + Your grace was wont to laugh, is also missing. + Hisperia, the princess' gentlewoman, + Confesses that she secretly o'erheard + Your daughter and her cousin much commend + The parts and graces of the wrestler + That did but lately foil the sinewy Charles; + And she believes, wherever they are gone, + That youth is surely in their company. + +DUKE FREDERICK Send to his brother; fetch that gallant hither; + If he be absent, bring his brother to me; + I'll make him find him: do this suddenly, + And let not search and inquisition quail + To bring again these foolish runaways. + + [Exeunt] + + + + + AS YOU LIKE IT + + +ACT II + + + +SCENE III Before OLIVER'S house. + + + [Enter ORLANDO and ADAM, meeting] + +ORLANDO Who's there? + +ADAM What, my young master? O, my gentle master! + O my sweet master! O you memory + Of old Sir Rowland! why, what make you here? + Why are you virtuous? why do people love you? + And wherefore are you gentle, strong and valiant? + Why would you be so fond to overcome + The bonny priser of the humorous duke? + Your praise is come too swiftly home before you. + Know you not, master, to some kind of men + Their graces serve them but as enemies? + No more do yours: your virtues, gentle master, + Are sanctified and holy traitors to you. + O, what a world is this, when what is comely + Envenoms him that bears it! + +ORLANDO Why, what's the matter? + +ADAM O unhappy youth! + Come not within these doors; within this roof + The enemy of all your graces lives: + Your brother--no, no brother; yet the son-- + Yet not the son, I will not call him son + Of him I was about to call his father-- + Hath heard your praises, and this night he means + To burn the lodging where you use to lie + And you within it: if he fail of that, + He will have other means to cut you off. + I overheard him and his practises. + This is no place; this house is but a butchery: + Abhor it, fear it, do not enter it. + +ORLANDO Why, whither, Adam, wouldst thou have me go? + +ADAM No matter whither, so you come not here. + +ORLANDO What, wouldst thou have me go and beg my food? + Or with a base and boisterous sword enforce + A thievish living on the common road? + This I must do, or know not what to do: + Yet this I will not do, do how I can; + I rather will subject me to the malice + Of a diverted blood and bloody brother. + +ADAM But do not so. I have five hundred crowns, + The thrifty hire I saved under your father, + Which I did store to be my foster-nurse + When service should in my old limbs lie lame + And unregarded age in corners thrown: + Take that, and He that doth the ravens feed, + Yea, providently caters for the sparrow, + Be comfort to my age! Here is the gold; + And all this I give you. Let me be your servant: + Though I look old, yet I am strong and lusty; + For in my youth I never did apply + Hot and rebellious liquors in my blood, + Nor did not with unbashful forehead woo + The means of weakness and debility; + Therefore my age is as a lusty winter, + Frosty, but kindly: let me go with you; + I'll do the service of a younger man + In all your business and necessities. + +ORLANDO O good old man, how well in thee appears + The constant service of the antique world, + When service sweat for duty, not for meed! + Thou art not for the fashion of these times, + Where none will sweat but for promotion, + And having that, do choke their service up + Even with the having: it is not so with thee. + But, poor old man, thou prunest a rotten tree, + That cannot so much as a blossom yield + In lieu of all thy pains and husbandry + But come thy ways; well go along together, + And ere we have thy youthful wages spent, + We'll light upon some settled low content. + +ADAM Master, go on, and I will follow thee, + To the last gasp, with truth and loyalty. + From seventeen years till now almost fourscore + Here lived I, but now live here no more. + At seventeen years many their fortunes seek; + But at fourscore it is too late a week: + Yet fortune cannot recompense me better + Than to die well and not my master's debtor. + + [Exeunt] + + + + + AS YOU LIKE IT + + +ACT II + + + +SCENE IV The Forest of Arden. + + + [Enter ROSALIND for Ganymede, CELIA for Aliena, + and TOUCHSTONE] + +ROSALIND O Jupiter, how weary are my spirits! + +TOUCHSTONE I care not for my spirits, if my legs were not weary. + +ROSALIND I could find in my heart to disgrace my man's + apparel and to cry like a woman; but I must comfort + the weaker vessel, as doublet and hose ought to show + itself courageous to petticoat: therefore courage, + good Aliena! + +CELIA I pray you, bear with me; I cannot go no further. + +TOUCHSTONE For my part, I had rather bear with you than bear + you; yet I should bear no cross if I did bear you, + for I think you have no money in your purse. + +ROSALIND Well, this is the forest of Arden. + +TOUCHSTONE Ay, now am I in Arden; the more fool I; when I was + at home, I was in a better place: but travellers + must be content. + +ROSALIND Ay, be so, good Touchstone. + + [Enter CORIN and SILVIUS] + + Look you, who comes here; a young man and an old in + solemn talk. + +CORIN That is the way to make her scorn you still. + +SILVIUS O Corin, that thou knew'st how I do love her! + +CORIN I partly guess; for I have loved ere now. + +SILVIUS No, Corin, being old, thou canst not guess, + Though in thy youth thou wast as true a lover + As ever sigh'd upon a midnight pillow: + But if thy love were ever like to mine-- + As sure I think did never man love so-- + How many actions most ridiculous + Hast thou been drawn to by thy fantasy? + +CORIN Into a thousand that I have forgotten. + +SILVIUS O, thou didst then ne'er love so heartily! + If thou remember'st not the slightest folly + That ever love did make thee run into, + Thou hast not loved: + Or if thou hast not sat as I do now, + Wearying thy hearer in thy mistress' praise, + Thou hast not loved: + Or if thou hast not broke from company + Abruptly, as my passion now makes me, + Thou hast not loved. + O Phebe, Phebe, Phebe! + + [Exit] + +ROSALIND Alas, poor shepherd! searching of thy wound, + I have by hard adventure found mine own. + +TOUCHSTONE And I mine. I remember, when I was in love I broke + my sword upon a stone and bid him take that for + coming a-night to Jane Smile; and I remember the + kissing of her batlet and the cow's dugs that her + pretty chopt hands had milked; and I remember the + wooing of a peascod instead of her, from whom I took + two cods and, giving her them again, said with + weeping tears 'Wear these for my sake.' We that are + true lovers run into strange capers; but as all is + mortal in nature, so is all nature in love mortal in folly. + +ROSALIND Thou speakest wiser than thou art ware of. + +TOUCHSTONE Nay, I shall ne'er be ware of mine own wit till I + break my shins against it. + +ROSALIND Jove, Jove! this shepherd's passion + Is much upon my fashion. + +TOUCHSTONE And mine; but it grows something stale with me. + +CELIA I pray you, one of you question yond man + If he for gold will give us any food: + I faint almost to death. + +TOUCHSTONE Holla, you clown! + +ROSALIND Peace, fool: he's not thy kinsman. + +CORIN Who calls? + +TOUCHSTONE Your betters, sir. + +CORIN Else are they very wretched. + +ROSALIND Peace, I say. Good even to you, friend. + +CORIN And to you, gentle sir, and to you all. + +ROSALIND I prithee, shepherd, if that love or gold + Can in this desert place buy entertainment, + Bring us where we may rest ourselves and feed: + Here's a young maid with travel much oppress'd + And faints for succor. + +CORIN Fair sir, I pity her + And wish, for her sake more than for mine own, + My fortunes were more able to relieve her; + But I am shepherd to another man + And do not shear the fleeces that I graze: + My master is of churlish disposition + And little recks to find the way to heaven + By doing deeds of hospitality: + Besides, his cote, his flocks and bounds of feed + Are now on sale, and at our sheepcote now, + By reason of his absence, there is nothing + That you will feed on; but what is, come see. + And in my voice most welcome shall you be. + +ROSALIND What is he that shall buy his flock and pasture? + +CORIN That young swain that you saw here but erewhile, + That little cares for buying any thing. + +ROSALIND I pray thee, if it stand with honesty, + Buy thou the cottage, pasture and the flock, + And thou shalt have to pay for it of us. + +CELIA And we will mend thy wages. I like this place. + And willingly could waste my time in it. + +CORIN Assuredly the thing is to be sold: + Go with me: if you like upon report + The soil, the profit and this kind of life, + I will your very faithful feeder be + And buy it with your gold right suddenly. + + [Exeunt] + + + + + AS YOU LIKE IT + + +ACT II + + + +SCENE V The Forest. + + + [Enter AMIENS, JAQUES, and others] + + SONG. +AMIENS Under the greenwood tree + Who loves to lie with me, + And turn his merry note + Unto the sweet bird's throat, + Come hither, come hither, come hither: + Here shall he see No enemy + But winter and rough weather. + +JAQUES More, more, I prithee, more. + +AMIENS It will make you melancholy, Monsieur Jaques. + +JAQUES I thank it. More, I prithee, more. I can suck + melancholy out of a song, as a weasel sucks eggs. + More, I prithee, more. + +AMIENS My voice is ragged: I know I cannot please you. + +JAQUES I do not desire you to please me; I do desire you to + sing. Come, more; another stanzo: call you 'em stanzos? + +AMIENS What you will, Monsieur Jaques. + +JAQUES Nay, I care not for their names; they owe me + nothing. Will you sing? + +AMIENS More at your request than to please myself. + +JAQUES Well then, if ever I thank any man, I'll thank you; + but that they call compliment is like the encounter + of two dog-apes, and when a man thanks me heartily, + methinks I have given him a penny and he renders me + the beggarly thanks. Come, sing; and you that will + not, hold your tongues. + +AMIENS Well, I'll end the song. Sirs, cover the while; the + duke will drink under this tree. He hath been all + this day to look you. + +JAQUES And I have been all this day to avoid him. He is + too disputable for my company: I think of as many + matters as he, but I give heaven thanks and make no + boast of them. Come, warble, come. + + SONG. + Who doth ambition shun + + [All together here] + + And loves to live i' the sun, + Seeking the food he eats + And pleased with what he gets, + Come hither, come hither, come hither: + Here shall he see No enemy + But winter and rough weather. + +JAQUES I'll give you a verse to this note that I made + yesterday in despite of my invention. + +AMIENS And I'll sing it. + +JAQUES Thus it goes:-- + + If it do come to pass + That any man turn ass, + Leaving his wealth and ease, + A stubborn will to please, + Ducdame, ducdame, ducdame: + Here shall he see + Gross fools as he, + An if he will come to me. + +AMIENS What's that 'ducdame'? + +JAQUES 'Tis a Greek invocation, to call fools into a + circle. I'll go sleep, if I can; if I cannot, I'll + rail against all the first-born of Egypt. + +AMIENS And I'll go seek the duke: his banquet is prepared. + + [Exeunt severally] + + + + + AS YOU LIKE IT + + +ACT II + + + +SCENE VI The forest. + + + [Enter ORLANDO and ADAM] + +ADAM Dear master, I can go no further. O, I die for food! + Here lie I down, and measure out my grave. Farewell, + kind master. + +ORLANDO Why, how now, Adam! no greater heart in thee? Live + a little; comfort a little; cheer thyself a little. + If this uncouth forest yield any thing savage, I + will either be food for it or bring it for food to + thee. Thy conceit is nearer death than thy powers. + For my sake be comfortable; hold death awhile at + the arm's end: I will here be with thee presently; + and if I bring thee not something to eat, I will + give thee leave to die: but if thou diest before I + come, thou art a mocker of my labour. Well said! + thou lookest cheerly, and I'll be with thee quickly. + Yet thou liest in the bleak air: come, I will bear + thee to some shelter; and thou shalt not die for + lack of a dinner, if there live any thing in this + desert. Cheerly, good Adam! + + [Exeunt] + + + + + AS YOU LIKE IT + + +ACT II + + + +SCENE VII The forest. + + + [A table set out. Enter DUKE SENIOR, AMIENS, and + Lords like outlaws] + +DUKE SENIOR I think he be transform'd into a beast; + For I can no where find him like a man. + +First Lord My lord, he is but even now gone hence: + Here was he merry, hearing of a song. + +DUKE SENIOR If he, compact of jars, grow musical, + We shall have shortly discord in the spheres. + Go, seek him: tell him I would speak with him. + + [Enter JAQUES] + +First Lord He saves my labour by his own approach. + +DUKE SENIOR Why, how now, monsieur! what a life is this, + That your poor friends must woo your company? + What, you look merrily! + +JAQUES A fool, a fool! I met a fool i' the forest, + A motley fool; a miserable world! + As I do live by food, I met a fool + Who laid him down and bask'd him in the sun, + And rail'd on Lady Fortune in good terms, + In good set terms and yet a motley fool. + 'Good morrow, fool,' quoth I. 'No, sir,' quoth he, + 'Call me not fool till heaven hath sent me fortune:' + And then he drew a dial from his poke, + And, looking on it with lack-lustre eye, + Says very wisely, 'It is ten o'clock: + Thus we may see,' quoth he, 'how the world wags: + 'Tis but an hour ago since it was nine, + And after one hour more 'twill be eleven; + And so, from hour to hour, we ripe and ripe, + And then, from hour to hour, we rot and rot; + And thereby hangs a tale.' When I did hear + The motley fool thus moral on the time, + My lungs began to crow like chanticleer, + That fools should be so deep-contemplative, + And I did laugh sans intermission + An hour by his dial. O noble fool! + A worthy fool! Motley's the only wear. + +DUKE SENIOR What fool is this? + +JAQUES O worthy fool! One that hath been a courtier, + And says, if ladies be but young and fair, + They have the gift to know it: and in his brain, + Which is as dry as the remainder biscuit + After a voyage, he hath strange places cramm'd + With observation, the which he vents + In mangled forms. O that I were a fool! + I am ambitious for a motley coat. + +DUKE SENIOR Thou shalt have one. + +JAQUES It is my only suit; + Provided that you weed your better judgments + Of all opinion that grows rank in them + That I am wise. I must have liberty + Withal, as large a charter as the wind, + To blow on whom I please; for so fools have; + And they that are most galled with my folly, + They most must laugh. And why, sir, must they so? + The 'why' is plain as way to parish church: + He that a fool doth very wisely hit + Doth very foolishly, although he smart, + Not to seem senseless of the bob: if not, + The wise man's folly is anatomized + Even by the squandering glances of the fool. + Invest me in my motley; give me leave + To speak my mind, and I will through and through + Cleanse the foul body of the infected world, + If they will patiently receive my medicine. + +DUKE SENIOR Fie on thee! I can tell what thou wouldst do. + +JAQUES What, for a counter, would I do but good? + +DUKE SENIOR Most mischievous foul sin, in chiding sin: + For thou thyself hast been a libertine, + As sensual as the brutish sting itself; + And all the embossed sores and headed evils, + That thou with licence of free foot hast caught, + Wouldst thou disgorge into the general world. + +JAQUES Why, who cries out on pride, + That can therein tax any private party? + Doth it not flow as hugely as the sea, + Till that the weary very means do ebb? + What woman in the city do I name, + When that I say the city-woman bears + The cost of princes on unworthy shoulders? + Who can come in and say that I mean her, + When such a one as she such is her neighbour? + Or what is he of basest function + That says his bravery is not of my cost, + Thinking that I mean him, but therein suits + His folly to the mettle of my speech? + There then; how then? what then? Let me see wherein + My tongue hath wrong'd him: if it do him right, + Then he hath wrong'd himself; if he be free, + Why then my taxing like a wild-goose flies, + Unclaim'd of any man. But who comes here? + + [Enter ORLANDO, with his sword drawn] + +ORLANDO Forbear, and eat no more. + +JAQUES Why, I have eat none yet. + +ORLANDO Nor shalt not, till necessity be served. + +JAQUES Of what kind should this cock come of? + +DUKE SENIOR Art thou thus bolden'd, man, by thy distress, + Or else a rude despiser of good manners, + That in civility thou seem'st so empty? + +ORLANDO You touch'd my vein at first: the thorny point + Of bare distress hath ta'en from me the show + Of smooth civility: yet am I inland bred + And know some nurture. But forbear, I say: + He dies that touches any of this fruit + Till I and my affairs are answered. + +JAQUES An you will not be answered with reason, I must die. + +DUKE SENIOR What would you have? Your gentleness shall force + More than your force move us to gentleness. + +ORLANDO I almost die for food; and let me have it. + +DUKE SENIOR Sit down and feed, and welcome to our table. + +ORLANDO Speak you so gently? Pardon me, I pray you: + I thought that all things had been savage here; + And therefore put I on the countenance + Of stern commandment. But whate'er you are + That in this desert inaccessible, + Under the shade of melancholy boughs, + Lose and neglect the creeping hours of time + If ever you have look'd on better days, + If ever been where bells have knoll'd to church, + If ever sat at any good man's feast, + If ever from your eyelids wiped a tear + And know what 'tis to pity and be pitied, + Let gentleness my strong enforcement be: + In the which hope I blush, and hide my sword. + +DUKE SENIOR True is it that we have seen better days, + And have with holy bell been knoll'd to church + And sat at good men's feasts and wiped our eyes + Of drops that sacred pity hath engender'd: + And therefore sit you down in gentleness + And take upon command what help we have + That to your wanting may be minister'd. + +ORLANDO Then but forbear your food a little while, + Whiles, like a doe, I go to find my fawn + And give it food. There is an old poor man, + Who after me hath many a weary step + Limp'd in pure love: till he be first sufficed, + Oppress'd with two weak evils, age and hunger, + I will not touch a bit. + +DUKE SENIOR Go find him out, + And we will nothing waste till you return. + +ORLANDO I thank ye; and be blest for your good comfort! + + [Exit] + +DUKE SENIOR Thou seest we are not all alone unhappy: + This wide and universal theatre + Presents more woeful pageants than the scene + Wherein we play in. + +JAQUES All the world's a stage, + And all the men and women merely players: + They have their exits and their entrances; + And one man in his time plays many parts, + His acts being seven ages. At first the infant, + Mewling and puking in the nurse's arms. + And then the whining school-boy, with his satchel + And shining morning face, creeping like snail + Unwillingly to school. And then the lover, + Sighing like furnace, with a woeful ballad + Made to his mistress' eyebrow. Then a soldier, + Full of strange oaths and bearded like the pard, + Jealous in honour, sudden and quick in quarrel, + Seeking the bubble reputation + Even in the cannon's mouth. And then the justice, + In fair round belly with good capon lined, + With eyes severe and beard of formal cut, + Full of wise saws and modern instances; + And so he plays his part. The sixth age shifts + Into the lean and slipper'd pantaloon, + With spectacles on nose and pouch on side, + His youthful hose, well saved, a world too wide + For his shrunk shank; and his big manly voice, + Turning again toward childish treble, pipes + And whistles in his sound. Last scene of all, + That ends this strange eventful history, + Is second childishness and mere oblivion, + Sans teeth, sans eyes, sans taste, sans everything. + + [Re-enter ORLANDO, with ADAM] + +DUKE SENIOR Welcome. Set down your venerable burthen, + And let him feed. + +ORLANDO I thank you most for him. + +ADAM So had you need: + I scarce can speak to thank you for myself. + +DUKE SENIOR Welcome; fall to: I will not trouble you + As yet, to question you about your fortunes. + Give us some music; and, good cousin, sing. + + SONG. +AMIENS Blow, blow, thou winter wind. + Thou art not so unkind + As man's ingratitude; + Thy tooth is not so keen, + Because thou art not seen, + Although thy breath be rude. + Heigh-ho! sing, heigh-ho! unto the green holly: + Most friendship is feigning, most loving mere folly: + Then, heigh-ho, the holly! + This life is most jolly. + Freeze, freeze, thou bitter sky, + That dost not bite so nigh + As benefits forgot: + Though thou the waters warp, + Thy sting is not so sharp + As friend remember'd not. + Heigh-ho! sing, &c. + +DUKE SENIOR If that you were the good Sir Rowland's son, + As you have whisper'd faithfully you were, + And as mine eye doth his effigies witness + Most truly limn'd and living in your face, + Be truly welcome hither: I am the duke + That loved your father: the residue of your fortune, + Go to my cave and tell me. Good old man, + Thou art right welcome as thy master is. + Support him by the arm. Give me your hand, + And let me all your fortunes understand. + + [Exeunt] + + + + + AS YOU LIKE IT + + +ACT III + + + +SCENE I A room in the palace. + + + [Enter DUKE FREDERICK, Lords, and OLIVER] + +DUKE FREDERICK Not see him since? Sir, sir, that cannot be: + But were I not the better part made mercy, + I should not seek an absent argument + Of my revenge, thou present. But look to it: + Find out thy brother, wheresoe'er he is; + Seek him with candle; bring him dead or living + Within this twelvemonth, or turn thou no more + To seek a living in our territory. + Thy lands and all things that thou dost call thine + Worth seizure do we seize into our hands, + Till thou canst quit thee by thy brothers mouth + Of what we think against thee. + +OLIVER O that your highness knew my heart in this! + I never loved my brother in my life. + +DUKE FREDERICK More villain thou. Well, push him out of doors; + And let my officers of such a nature + Make an extent upon his house and lands: + Do this expediently and turn him going. + + [Exeunt] + + + + + AS YOU LIKE IT + + +ACT III + + + +SCENE II The forest. + + + [Enter ORLANDO, with a paper] + +ORLANDO Hang there, my verse, in witness of my love: + And thou, thrice-crowned queen of night, survey + With thy chaste eye, from thy pale sphere above, + Thy huntress' name that my full life doth sway. + O Rosalind! these trees shall be my books + And in their barks my thoughts I'll character; + That every eye which in this forest looks + Shall see thy virtue witness'd every where. + Run, run, Orlando; carve on every tree + The fair, the chaste and unexpressive she. + + [Exit] + + [Enter CORIN and TOUCHSTONE] + +CORIN And how like you this shepherd's life, Master Touchstone? + +TOUCHSTONE Truly, shepherd, in respect of itself, it is a good + life, but in respect that it is a shepherd's life, + it is naught. In respect that it is solitary, I + like it very well; but in respect that it is + private, it is a very vile life. Now, in respect it + is in the fields, it pleaseth me well; but in + respect it is not in the court, it is tedious. As + is it a spare life, look you, it fits my humour well; + but as there is no more plenty in it, it goes much + against my stomach. Hast any philosophy in thee, shepherd? + +CORIN No more but that I know the more one sickens the + worse at ease he is; and that he that wants money, + means and content is without three good friends; + that the property of rain is to wet and fire to + burn; that good pasture makes fat sheep, and that a + great cause of the night is lack of the sun; that + he that hath learned no wit by nature nor art may + complain of good breeding or comes of a very dull kindred. + +TOUCHSTONE Such a one is a natural philosopher. Wast ever in + court, shepherd? + +CORIN No, truly. + +TOUCHSTONE Then thou art damned. + +CORIN Nay, I hope. + +TOUCHSTONE Truly, thou art damned like an ill-roasted egg, all + on one side. + +CORIN For not being at court? Your reason. + +TOUCHSTONE Why, if thou never wast at court, thou never sawest + good manners; if thou never sawest good manners, + then thy manners must be wicked; and wickedness is + sin, and sin is damnation. Thou art in a parlous + state, shepherd. + +CORIN Not a whit, Touchstone: those that are good manners + at the court are as ridiculous in the country as the + behavior of the country is most mockable at the + court. You told me you salute not at the court, but + you kiss your hands: that courtesy would be + uncleanly, if courtiers were shepherds. + +TOUCHSTONE Instance, briefly; come, instance. + +CORIN Why, we are still handling our ewes, and their + fells, you know, are greasy. + +TOUCHSTONE Why, do not your courtier's hands sweat? and is not + the grease of a mutton as wholesome as the sweat of + a man? Shallow, shallow. A better instance, I say; come. + +CORIN Besides, our hands are hard. + +TOUCHSTONE Your lips will feel them the sooner. Shallow again. + A more sounder instance, come. + +CORIN And they are often tarred over with the surgery of + our sheep: and would you have us kiss tar? The + courtier's hands are perfumed with civet. + +TOUCHSTONE Most shallow man! thou worms-meat, in respect of a + good piece of flesh indeed! Learn of the wise, and + perpend: civet is of a baser birth than tar, the + very uncleanly flux of a cat. Mend the instance, shepherd. + +CORIN You have too courtly a wit for me: I'll rest. + +TOUCHSTONE Wilt thou rest damned? God help thee, shallow man! + God make incision in thee! thou art raw. + +CORIN Sir, I am a true labourer: I earn that I eat, get + that I wear, owe no man hate, envy no man's + happiness, glad of other men's good, content with my + harm, and the greatest of my pride is to see my ewes + graze and my lambs suck. + +TOUCHSTONE That is another simple sin in you, to bring the ewes + and the rams together and to offer to get your + living by the copulation of cattle; to be bawd to a + bell-wether, and to betray a she-lamb of a + twelvemonth to a crooked-pated, old, cuckoldly ram, + out of all reasonable match. If thou beest not + damned for this, the devil himself will have no + shepherds; I cannot see else how thou shouldst + 'scape. + +CORIN Here comes young Master Ganymede, my new mistress's brother. + + [Enter ROSALIND, with a paper, reading] + +ROSALIND From the east to western Ind, + No jewel is like Rosalind. + Her worth, being mounted on the wind, + Through all the world bears Rosalind. + All the pictures fairest lined + Are but black to Rosalind. + Let no fair be kept in mind + But the fair of Rosalind. + +TOUCHSTONE I'll rhyme you so eight years together, dinners and + suppers and sleeping-hours excepted: it is the + right butter-women's rank to market. + +ROSALIND Out, fool! + +TOUCHSTONE For a taste: + If a hart do lack a hind, + Let him seek out Rosalind. + If the cat will after kind, + So be sure will Rosalind. + Winter garments must be lined, + So must slender Rosalind. + They that reap must sheaf and bind; + Then to cart with Rosalind. + Sweetest nut hath sourest rind, + Such a nut is Rosalind. + He that sweetest rose will find + Must find love's prick and Rosalind. + This is the very false gallop of verses: why do you + infect yourself with them? + +ROSALIND Peace, you dull fool! I found them on a tree. + +TOUCHSTONE Truly, the tree yields bad fruit. + +ROSALIND I'll graff it with you, and then I shall graff it + with a medlar: then it will be the earliest fruit + i' the country; for you'll be rotten ere you be half + ripe, and that's the right virtue of the medlar. + +TOUCHSTONE You have said; but whether wisely or no, let the + forest judge. + + [Enter CELIA, with a writing] + +ROSALIND Peace! Here comes my sister, reading: stand aside. + +CELIA [Reads] + + Why should this a desert be? + For it is unpeopled? No: + Tongues I'll hang on every tree, + That shall civil sayings show: + Some, how brief the life of man + Runs his erring pilgrimage, + That the stretching of a span + Buckles in his sum of age; + Some, of violated vows + 'Twixt the souls of friend and friend: + But upon the fairest boughs, + Or at every sentence end, + Will I Rosalinda write, + Teaching all that read to know + The quintessence of every sprite + Heaven would in little show. + Therefore Heaven Nature charged + That one body should be fill'd + With all graces wide-enlarged: + Nature presently distill'd + Helen's cheek, but not her heart, + Cleopatra's majesty, + Atalanta's better part, + Sad Lucretia's modesty. + Thus Rosalind of many parts + By heavenly synod was devised, + Of many faces, eyes and hearts, + To have the touches dearest prized. + Heaven would that she these gifts should have, + And I to live and die her slave. + +ROSALIND O most gentle pulpiter! what tedious homily of love + have you wearied your parishioners withal, and never + cried 'Have patience, good people!' + +CELIA How now! back, friends! Shepherd, go off a little. + Go with him, sirrah. + +TOUCHSTONE Come, shepherd, let us make an honourable retreat; + though not with bag and baggage, yet with scrip and scrippage. + + [Exeunt CORIN and TOUCHSTONE] + +CELIA Didst thou hear these verses? + +ROSALIND O, yes, I heard them all, and more too; for some of + them had in them more feet than the verses would bear. + +CELIA That's no matter: the feet might bear the verses. + +ROSALIND Ay, but the feet were lame and could not bear + themselves without the verse and therefore stood + lamely in the verse. + +CELIA But didst thou hear without wondering how thy name + should be hanged and carved upon these trees? + +ROSALIND I was seven of the nine days out of the wonder + before you came; for look here what I found on a + palm-tree. I was never so be-rhymed since + Pythagoras' time, that I was an Irish rat, which I + can hardly remember. + +CELIA Trow you who hath done this? + +ROSALIND Is it a man? + +CELIA And a chain, that you once wore, about his neck. + Change you colour? + +ROSALIND I prithee, who? + +CELIA O Lord, Lord! it is a hard matter for friends to + meet; but mountains may be removed with earthquakes + and so encounter. + +ROSALIND Nay, but who is it? + +CELIA Is it possible? + +ROSALIND Nay, I prithee now with most petitionary vehemence, + tell me who it is. + +CELIA O wonderful, wonderful, and most wonderful + wonderful! and yet again wonderful, and after that, + out of all hooping! + +ROSALIND Good my complexion! dost thou think, though I am + caparisoned like a man, I have a doublet and hose in + my disposition? One inch of delay more is a + South-sea of discovery; I prithee, tell me who is it + quickly, and speak apace. I would thou couldst + stammer, that thou mightst pour this concealed man + out of thy mouth, as wine comes out of a narrow- + mouthed bottle, either too much at once, or none at + all. I prithee, take the cork out of thy mouth that + may drink thy tidings. + +CELIA So you may put a man in your belly. + +ROSALIND Is he of God's making? What manner of man? Is his + head worth a hat, or his chin worth a beard? + +CELIA Nay, he hath but a little beard. + +ROSALIND Why, God will send more, if the man will be + thankful: let me stay the growth of his beard, if + thou delay me not the knowledge of his chin. + +CELIA It is young Orlando, that tripped up the wrestler's + heels and your heart both in an instant. + +ROSALIND Nay, but the devil take mocking: speak, sad brow and + true maid. + +CELIA I' faith, coz, 'tis he. + +ROSALIND Orlando? + +CELIA Orlando. + +ROSALIND Alas the day! what shall I do with my doublet and + hose? What did he when thou sawest him? What said + he? How looked he? Wherein went he? What makes + him here? Did he ask for me? Where remains he? + How parted he with thee? and when shalt thou see + him again? Answer me in one word. + +CELIA You must borrow me Gargantua's mouth first: 'tis a + word too great for any mouth of this age's size. To + say ay and no to these particulars is more than to + answer in a catechism. + +ROSALIND But doth he know that I am in this forest and in + man's apparel? Looks he as freshly as he did the + day he wrestled? + +CELIA It is as easy to count atomies as to resolve the + propositions of a lover; but take a taste of my + finding him, and relish it with good observance. + I found him under a tree, like a dropped acorn. + +ROSALIND It may well be called Jove's tree, when it drops + forth such fruit. + +CELIA Give me audience, good madam. + +ROSALIND Proceed. + +CELIA There lay he, stretched along, like a wounded knight. + +ROSALIND Though it be pity to see such a sight, it well + becomes the ground. + +CELIA Cry 'holla' to thy tongue, I prithee; it curvets + unseasonably. He was furnished like a hunter. + +ROSALIND O, ominous! he comes to kill my heart. + +CELIA I would sing my song without a burden: thou bringest + me out of tune. + +ROSALIND Do you not know I am a woman? when I think, I must + speak. Sweet, say on. + +CELIA You bring me out. Soft! comes he not here? + + [Enter ORLANDO and JAQUES] + +ROSALIND 'Tis he: slink by, and note him. + +JAQUES I thank you for your company; but, good faith, I had + as lief have been myself alone. + +ORLANDO And so had I; but yet, for fashion sake, I thank you + too for your society. + +JAQUES God be wi' you: let's meet as little as we can. + +ORLANDO I do desire we may be better strangers. + +JAQUES I pray you, mar no more trees with writing + love-songs in their barks. + +ORLANDO I pray you, mar no more of my verses with reading + them ill-favouredly. + +JAQUES Rosalind is your love's name? + +ORLANDO Yes, just. + +JAQUES I do not like her name. + +ORLANDO There was no thought of pleasing you when she was + christened. + +JAQUES What stature is she of? + +ORLANDO Just as high as my heart. + +JAQUES You are full of pretty answers. Have you not been + acquainted with goldsmiths' wives, and conned them + out of rings? + +ORLANDO Not so; but I answer you right painted cloth, from + whence you have studied your questions. + +JAQUES You have a nimble wit: I think 'twas made of + Atalanta's heels. Will you sit down with me? and + we two will rail against our mistress the world and + all our misery. + +ORLANDO I will chide no breather in the world but myself, + against whom I know most faults. + +JAQUES The worst fault you have is to be in love. + +ORLANDO 'Tis a fault I will not change for your best virtue. + I am weary of you. + +JAQUES By my troth, I was seeking for a fool when I found + you. + +ORLANDO He is drowned in the brook: look but in, and you + shall see him. + +JAQUES There I shall see mine own figure. + +ORLANDO Which I take to be either a fool or a cipher. + +JAQUES I'll tarry no longer with you: farewell, good + Signior Love. + +ORLANDO I am glad of your departure: adieu, good Monsieur + Melancholy. + + [Exit JAQUES] + +ROSALIND [Aside to CELIA] I will speak to him, like a saucy + lackey and under that habit play the knave with him. + Do you hear, forester? + +ORLANDO Very well: what would you? + +ROSALIND I pray you, what is't o'clock? + +ORLANDO You should ask me what time o' day: there's no clock + in the forest. + +ROSALIND Then there is no true lover in the forest; else + sighing every minute and groaning every hour would + detect the lazy foot of Time as well as a clock. + +ORLANDO And why not the swift foot of Time? had not that + been as proper? + +ROSALIND By no means, sir: Time travels in divers paces with + divers persons. I'll tell you who Time ambles + withal, who Time trots withal, who Time gallops + withal and who he stands still withal. + +ORLANDO I prithee, who doth he trot withal? + +ROSALIND Marry, he trots hard with a young maid between the + contract of her marriage and the day it is + solemnized: if the interim be but a se'nnight, + Time's pace is so hard that it seems the length of + seven year. + +ORLANDO Who ambles Time withal? + +ROSALIND With a priest that lacks Latin and a rich man that + hath not the gout, for the one sleeps easily because + he cannot study, and the other lives merrily because + he feels no pain, the one lacking the burden of lean + and wasteful learning, the other knowing no burden + of heavy tedious penury; these Time ambles withal. + +ORLANDO Who doth he gallop withal? + +ROSALIND With a thief to the gallows, for though he go as + softly as foot can fall, he thinks himself too soon there. + +ORLANDO Who stays it still withal? + +ROSALIND With lawyers in the vacation, for they sleep between + term and term and then they perceive not how Time moves. + +ORLANDO Where dwell you, pretty youth? + +ROSALIND With this shepherdess, my sister; here in the + skirts of the forest, like fringe upon a petticoat. + +ORLANDO Are you native of this place? + +ROSALIND As the cony that you see dwell where she is kindled. + +ORLANDO Your accent is something finer than you could + purchase in so removed a dwelling. + +ROSALIND I have been told so of many: but indeed an old + religious uncle of mine taught me to speak, who was + in his youth an inland man; one that knew courtship + too well, for there he fell in love. I have heard + him read many lectures against it, and I thank God + I am not a woman, to be touched with so many + giddy offences as he hath generally taxed their + whole sex withal. + +ORLANDO Can you remember any of the principal evils that he + laid to the charge of women? + +ROSALIND There were none principal; they were all like one + another as half-pence are, every one fault seeming + monstrous till his fellow fault came to match it. + +ORLANDO I prithee, recount some of them. + +ROSALIND No, I will not cast away my physic but on those that + are sick. There is a man haunts the forest, that + abuses our young plants with carving 'Rosalind' on + their barks; hangs odes upon hawthorns and elegies + on brambles, all, forsooth, deifying the name of + Rosalind: if I could meet that fancy-monger I would + give him some good counsel, for he seems to have the + quotidian of love upon him. + +ORLANDO I am he that is so love-shaked: I pray you tell me + your remedy. + +ROSALIND There is none of my uncle's marks upon you: he + taught me how to know a man in love; in which cage + of rushes I am sure you are not prisoner. + +ORLANDO What were his marks? + +ROSALIND A lean cheek, which you have not, a blue eye and + sunken, which you have not, an unquestionable + spirit, which you have not, a beard neglected, + which you have not; but I pardon you for that, for + simply your having in beard is a younger brother's + revenue: then your hose should be ungartered, your + bonnet unbanded, your sleeve unbuttoned, your shoe + untied and every thing about you demonstrating a + careless desolation; but you are no such man; you + are rather point-device in your accoutrements as + loving yourself than seeming the lover of any other. + +ORLANDO Fair youth, I would I could make thee believe I love. + +ROSALIND Me believe it! you may as soon make her that you + love believe it; which, I warrant, she is apter to + do than to confess she does: that is one of the + points in the which women still give the lie to + their consciences. But, in good sooth, are you he + that hangs the verses on the trees, wherein Rosalind + is so admired? + +ORLANDO I swear to thee, youth, by the white hand of + Rosalind, I am that he, that unfortunate he. + +ROSALIND But are you so much in love as your rhymes speak? + +ORLANDO Neither rhyme nor reason can express how much. + +ROSALIND Love is merely a madness, and, I tell you, deserves + as well a dark house and a whip as madmen do: and + the reason why they are not so punished and cured + is, that the lunacy is so ordinary that the whippers + are in love too. Yet I profess curing it by counsel. + +ORLANDO Did you ever cure any so? + +ROSALIND Yes, one, and in this manner. He was to imagine me + his love, his mistress; and I set him every day to + woo me: at which time would I, being but a moonish + youth, grieve, be effeminate, changeable, longing + and liking, proud, fantastical, apish, shallow, + inconstant, full of tears, full of smiles, for every + passion something and for no passion truly any + thing, as boys and women are for the most part + cattle of this colour; would now like him, now loathe + him; then entertain him, then forswear him; now weep + for him, then spit at him; that I drave my suitor + from his mad humour of love to a living humour of + madness; which was, to forswear the full stream of + the world, and to live in a nook merely monastic. + And thus I cured him; and this way will I take upon + me to wash your liver as clean as a sound sheep's + heart, that there shall not be one spot of love in't. + +ORLANDO I would not be cured, youth. + +ROSALIND I would cure you, if you would but call me Rosalind + and come every day to my cote and woo me. + +ORLANDO Now, by the faith of my love, I will: tell me + where it is. + +ROSALIND Go with me to it and I'll show it you and by the way + you shall tell me where in the forest you live. + Will you go? + +ORLANDO With all my heart, good youth. + +ROSALIND Nay you must call me Rosalind. Come, sister, will you go? + + [Exeunt] + + + + + AS YOU LIKE IT + + +ACT III + + + +SCENE III The forest. + + + [Enter TOUCHSTONE and AUDREY; JAQUES behind] + +TOUCHSTONE Come apace, good Audrey: I will fetch up your + goats, Audrey. And how, Audrey? am I the man yet? + doth my simple feature content you? + +AUDREY Your features! Lord warrant us! what features! + +TOUCHSTONE I am here with thee and thy goats, as the most + capricious poet, honest Ovid, was among the Goths. + +JAQUES [Aside] O knowledge ill-inhabited, worse than Jove + in a thatched house! + +TOUCHSTONE When a man's verses cannot be understood, nor a + man's good wit seconded with the forward child + Understanding, it strikes a man more dead than a + great reckoning in a little room. Truly, I would + the gods had made thee poetical. + +AUDREY I do not know what 'poetical' is: is it honest in + deed and word? is it a true thing? + +TOUCHSTONE No, truly; for the truest poetry is the most + feigning; and lovers are given to poetry, and what + they swear in poetry may be said as lovers they do feign. + +AUDREY Do you wish then that the gods had made me poetical? + +TOUCHSTONE I do, truly; for thou swearest to me thou art + honest: now, if thou wert a poet, I might have some + hope thou didst feign. + +AUDREY Would you not have me honest? + +TOUCHSTONE No, truly, unless thou wert hard-favoured; for + honesty coupled to beauty is to have honey a sauce to sugar. + +JAQUES [Aside] A material fool! + +AUDREY Well, I am not fair; and therefore I pray the gods + make me honest. + +TOUCHSTONE Truly, and to cast away honesty upon a foul slut + were to put good meat into an unclean dish. + +AUDREY I am not a slut, though I thank the gods I am foul. + +TOUCHSTONE Well, praised be the gods for thy foulness! + sluttishness may come hereafter. But be it as it may + be, I will marry thee, and to that end I have been + with Sir Oliver Martext, the vicar of the next + village, who hath promised to meet me in this place + of the forest and to couple us. + +JAQUES [Aside] I would fain see this meeting. + +AUDREY Well, the gods give us joy! + +TOUCHSTONE Amen. A man may, if he were of a fearful heart, + stagger in this attempt; for here we have no temple + but the wood, no assembly but horn-beasts. But what + though? Courage! As horns are odious, they are + necessary. It is said, 'many a man knows no end of + his goods:' right; many a man has good horns, and + knows no end of them. Well, that is the dowry of + his wife; 'tis none of his own getting. Horns? + Even so. Poor men alone? No, no; the noblest deer + hath them as huge as the rascal. Is the single man + therefore blessed? No: as a walled town is more + worthier than a village, so is the forehead of a + married man more honourable than the bare brow of a + bachelor; and by how much defence is better than no + skill, by so much is a horn more precious than to + want. Here comes Sir Oliver. + + [Enter SIR OLIVER MARTEXT] + + Sir Oliver Martext, you are well met: will you + dispatch us here under this tree, or shall we go + with you to your chapel? + +SIR OLIVER MARTEXT Is there none here to give the woman? + +TOUCHSTONE I will not take her on gift of any man. + +SIR OLIVER MARTEXT Truly, she must be given, or the marriage is not lawful. + +JAQUES [Advancing] + + Proceed, proceed I'll give her. + +TOUCHSTONE Good even, good Master What-ye-call't: how do you, + sir? You are very well met: God 'ild you for your + last company: I am very glad to see you: even a + toy in hand here, sir: nay, pray be covered. + +JAQUES Will you be married, motley? + +TOUCHSTONE As the ox hath his bow, sir, the horse his curb and + the falcon her bells, so man hath his desires; and + as pigeons bill, so wedlock would be nibbling. + +JAQUES And will you, being a man of your breeding, be + married under a bush like a beggar? Get you to + church, and have a good priest that can tell you + what marriage is: this fellow will but join you + together as they join wainscot; then one of you will + prove a shrunk panel and, like green timber, warp, warp. + +TOUCHSTONE [Aside] I am not in the mind but I were better to be + married of him than of another: for he is not like + to marry me well; and not being well married, it + will be a good excuse for me hereafter to leave my wife. + +JAQUES Go thou with me, and let me counsel thee. + +TOUCHSTONE 'Come, sweet Audrey: + We must be married, or we must live in bawdry. + Farewell, good Master Oliver: not,-- + O sweet Oliver, + O brave Oliver, + Leave me not behind thee: but,-- + Wind away, + Begone, I say, + I will not to wedding with thee. + + [Exeunt JAQUES, TOUCHSTONE and AUDREY] + +SIR OLIVER MARTEXT 'Tis no matter: ne'er a fantastical knave of them + all shall flout me out of my calling. + + [Exit] + + + + + AS YOU LIKE IT + + +ACT III + + + +SCENE IV The forest. + + + [Enter ROSALIND and CELIA] + +ROSALIND Never talk to me; I will weep. + +CELIA Do, I prithee; but yet have the grace to consider + that tears do not become a man. + +ROSALIND But have I not cause to weep? + +CELIA As good cause as one would desire; therefore weep. + +ROSALIND His very hair is of the dissembling colour. + +CELIA Something browner than Judas's marry, his kisses are + Judas's own children. + +ROSALIND I' faith, his hair is of a good colour. + +CELIA An excellent colour: your chestnut was ever the only colour. + +ROSALIND And his kissing is as full of sanctity as the touch + of holy bread. + +CELIA He hath bought a pair of cast lips of Diana: a nun + of winter's sisterhood kisses not more religiously; + the very ice of chastity is in them. + +ROSALIND But why did he swear he would come this morning, and + comes not? + +CELIA Nay, certainly, there is no truth in him. + +ROSALIND Do you think so? + +CELIA Yes; I think he is not a pick-purse nor a + horse-stealer, but for his verity in love, I do + think him as concave as a covered goblet or a + worm-eaten nut. + +ROSALIND Not true in love? + +CELIA Yes, when he is in; but I think he is not in. + +ROSALIND You have heard him swear downright he was. + +CELIA 'Was' is not 'is:' besides, the oath of a lover is + no stronger than the word of a tapster; they are + both the confirmer of false reckonings. He attends + here in the forest on the duke your father. + +ROSALIND I met the duke yesterday and had much question with + him: he asked me of what parentage I was; I told + him, of as good as he; so he laughed and let me go. + But what talk we of fathers, when there is such a + man as Orlando? + +CELIA O, that's a brave man! he writes brave verses, + speaks brave words, swears brave oaths and breaks + them bravely, quite traverse, athwart the heart of + his lover; as a puisny tilter, that spurs his horse + but on one side, breaks his staff like a noble + goose: but all's brave that youth mounts and folly + guides. Who comes here? + + [Enter CORIN] + +CORIN Mistress and master, you have oft inquired + After the shepherd that complain'd of love, + Who you saw sitting by me on the turf, + Praising the proud disdainful shepherdess + That was his mistress. + +CELIA Well, and what of him? + +CORIN If you will see a pageant truly play'd, + Between the pale complexion of true love + And the red glow of scorn and proud disdain, + Go hence a little and I shall conduct you, + If you will mark it. + +ROSALIND O, come, let us remove: + The sight of lovers feedeth those in love. + Bring us to this sight, and you shall say + I'll prove a busy actor in their play. + + [Exeunt] + + + + + AS YOU LIKE IT + + +ACT III + + + +SCENE V Another part of the forest. + + + [Enter SILVIUS and PHEBE] + +SILVIUS Sweet Phebe, do not scorn me; do not, Phebe; + Say that you love me not, but say not so + In bitterness. The common executioner, + Whose heart the accustom'd sight of death makes hard, + Falls not the axe upon the humbled neck + But first begs pardon: will you sterner be + Than he that dies and lives by bloody drops? + + [Enter ROSALIND, CELIA, and CORIN, behind] + +PHEBE I would not be thy executioner: + I fly thee, for I would not injure thee. + Thou tell'st me there is murder in mine eye: + 'Tis pretty, sure, and very probable, + That eyes, that are the frail'st and softest things, + Who shut their coward gates on atomies, + Should be call'd tyrants, butchers, murderers! + Now I do frown on thee with all my heart; + And if mine eyes can wound, now let them kill thee: + Now counterfeit to swoon; why now fall down; + Or if thou canst not, O, for shame, for shame, + Lie not, to say mine eyes are murderers! + Now show the wound mine eye hath made in thee: + Scratch thee but with a pin, and there remains + Some scar of it; lean but upon a rush, + The cicatrice and capable impressure + Thy palm some moment keeps; but now mine eyes, + Which I have darted at thee, hurt thee not, + Nor, I am sure, there is no force in eyes + That can do hurt. + +SILVIUS O dear Phebe, + If ever,--as that ever may be near,-- + You meet in some fresh cheek the power of fancy, + Then shall you know the wounds invisible + That love's keen arrows make. + +PHEBE But till that time + Come not thou near me: and when that time comes, + Afflict me with thy mocks, pity me not; + As till that time I shall not pity thee. + +ROSALIND And why, I pray you? Who might be your mother, + That you insult, exult, and all at once, + Over the wretched? What though you have no beauty,-- + As, by my faith, I see no more in you + Than without candle may go dark to bed-- + Must you be therefore proud and pitiless? + Why, what means this? Why do you look on me? + I see no more in you than in the ordinary + Of nature's sale-work. 'Od's my little life, + I think she means to tangle my eyes too! + No, faith, proud mistress, hope not after it: + 'Tis not your inky brows, your black silk hair, + Your bugle eyeballs, nor your cheek of cream, + That can entame my spirits to your worship. + You foolish shepherd, wherefore do you follow her, + Like foggy south puffing with wind and rain? + You are a thousand times a properer man + Than she a woman: 'tis such fools as you + That makes the world full of ill-favour'd children: + 'Tis not her glass, but you, that flatters her; + And out of you she sees herself more proper + Than any of her lineaments can show her. + But, mistress, know yourself: down on your knees, + And thank heaven, fasting, for a good man's love: + For I must tell you friendly in your ear, + Sell when you can: you are not for all markets: + Cry the man mercy; love him; take his offer: + Foul is most foul, being foul to be a scoffer. + So take her to thee, shepherd: fare you well. + +PHEBE Sweet youth, I pray you, chide a year together: + I had rather hear you chide than this man woo. + +ROSALIND He's fallen in love with your foulness and she'll + fall in love with my anger. If it be so, as fast as + she answers thee with frowning looks, I'll sauce her + with bitter words. Why look you so upon me? + +PHEBE For no ill will I bear you. + +ROSALIND I pray you, do not fall in love with me, + For I am falser than vows made in wine: + Besides, I like you not. If you will know my house, + 'Tis at the tuft of olives here hard by. + Will you go, sister? Shepherd, ply her hard. + Come, sister. Shepherdess, look on him better, + And be not proud: though all the world could see, + None could be so abused in sight as he. + Come, to our flock. + + [Exeunt ROSALIND, CELIA and CORIN] + +PHEBE Dead Shepherd, now I find thy saw of might, + 'Who ever loved that loved not at first sight?' + +SILVIUS Sweet Phebe,-- + +PHEBE Ha, what say'st thou, Silvius? + +SILVIUS Sweet Phebe, pity me. + +PHEBE Why, I am sorry for thee, gentle Silvius. + +SILVIUS Wherever sorrow is, relief would be: + If you do sorrow at my grief in love, + By giving love your sorrow and my grief + Were both extermined. + +PHEBE Thou hast my love: is not that neighbourly? + +SILVIUS I would have you. + +PHEBE Why, that were covetousness. + Silvius, the time was that I hated thee, + And yet it is not that I bear thee love; + But since that thou canst talk of love so well, + Thy company, which erst was irksome to me, + I will endure, and I'll employ thee too: + But do not look for further recompense + Than thine own gladness that thou art employ'd. + +SILVIUS So holy and so perfect is my love, + And I in such a poverty of grace, + That I shall think it a most plenteous crop + To glean the broken ears after the man + That the main harvest reaps: loose now and then + A scatter'd smile, and that I'll live upon. + +PHEBE Know'st now the youth that spoke to me erewhile? + +SILVIUS Not very well, but I have met him oft; + And he hath bought the cottage and the bounds + That the old carlot once was master of. + +PHEBE Think not I love him, though I ask for him: + 'Tis but a peevish boy; yet he talks well; + But what care I for words? yet words do well + When he that speaks them pleases those that hear. + It is a pretty youth: not very pretty: + But, sure, he's proud, and yet his pride becomes him: + He'll make a proper man: the best thing in him + Is his complexion; and faster than his tongue + Did make offence his eye did heal it up. + He is not very tall; yet for his years he's tall: + His leg is but so so; and yet 'tis well: + There was a pretty redness in his lip, + A little riper and more lusty red + Than that mix'd in his cheek; 'twas just the difference + Between the constant red and mingled damask. + There be some women, Silvius, had they mark'd him + In parcels as I did, would have gone near + To fall in love with him; but, for my part, + I love him not nor hate him not; and yet + I have more cause to hate him than to love him: + For what had he to do to chide at me? + He said mine eyes were black and my hair black: + And, now I am remember'd, scorn'd at me: + I marvel why I answer'd not again: + But that's all one; omittance is no quittance. + I'll write to him a very taunting letter, + And thou shalt bear it: wilt thou, Silvius? + +SILVIUS Phebe, with all my heart. + +PHEBE I'll write it straight; + The matter's in my head and in my heart: + I will be bitter with him and passing short. + Go with me, Silvius. + + [Exeunt] + + + + + AS YOU LIKE IT + + +ACT IV + + + +SCENE I The forest. + + + [Enter ROSALIND, CELIA, and JAQUES] + +JAQUES I prithee, pretty youth, let me be better acquainted + with thee. + +ROSALIND They say you are a melancholy fellow. + +JAQUES I am so; I do love it better than laughing. + +ROSALIND Those that are in extremity of either are abominable + fellows and betray themselves to every modern + censure worse than drunkards. + +JAQUES Why, 'tis good to be sad and say nothing. + +ROSALIND Why then, 'tis good to be a post. + +JAQUES I have neither the scholar's melancholy, which is + emulation, nor the musician's, which is fantastical, + nor the courtier's, which is proud, nor the + soldier's, which is ambitious, nor the lawyer's, + which is politic, nor the lady's, which is nice, nor + the lover's, which is all these: but it is a + melancholy of mine own, compounded of many simples, + extracted from many objects, and indeed the sundry's + contemplation of my travels, in which my often + rumination wraps me m a most humorous sadness. + +ROSALIND A traveller! By my faith, you have great reason to + be sad: I fear you have sold your own lands to see + other men's; then, to have seen much and to have + nothing, is to have rich eyes and poor hands. + +JAQUES Yes, I have gained my experience. + +ROSALIND And your experience makes you sad: I had rather have + a fool to make me merry than experience to make me + sad; and to travel for it too! + + [Enter ORLANDO] + +ORLANDO Good day and happiness, dear Rosalind! + +JAQUES Nay, then, God be wi' you, an you talk in blank verse. + + [Exit] + +ROSALIND Farewell, Monsieur Traveller: look you lisp and + wear strange suits, disable all the benefits of your + own country, be out of love with your nativity and + almost chide God for making you that countenance you + are, or I will scarce think you have swam in a + gondola. Why, how now, Orlando! where have you been + all this while? You a lover! An you serve me such + another trick, never come in my sight more. + +ORLANDO My fair Rosalind, I come within an hour of my promise. + +ROSALIND Break an hour's promise in love! He that will + divide a minute into a thousand parts and break but + a part of the thousandth part of a minute in the + affairs of love, it may be said of him that Cupid + hath clapped him o' the shoulder, but I'll warrant + him heart-whole. + +ORLANDO Pardon me, dear Rosalind. + +ROSALIND Nay, an you be so tardy, come no more in my sight: I + had as lief be wooed of a snail. + +ORLANDO Of a snail? + +ROSALIND Ay, of a snail; for though he comes slowly, he + carries his house on his head; a better jointure, + I think, than you make a woman: besides he brings + his destiny with him. + +ORLANDO What's that? + +ROSALIND Why, horns, which such as you are fain to be + beholding to your wives for: but he comes armed in + his fortune and prevents the slander of his wife. + +ORLANDO Virtue is no horn-maker; and my Rosalind is virtuous. + +ROSALIND And I am your Rosalind. + +CELIA It pleases him to call you so; but he hath a + Rosalind of a better leer than you. + +ROSALIND Come, woo me, woo me, for now I am in a holiday + humour and like enough to consent. What would you + say to me now, an I were your very very Rosalind? + +ORLANDO I would kiss before I spoke. + +ROSALIND Nay, you were better speak first, and when you were + gravelled for lack of matter, you might take + occasion to kiss. Very good orators, when they are + out, they will spit; and for lovers lacking--God + warn us!--matter, the cleanliest shift is to kiss. + +ORLANDO How if the kiss be denied? + +ROSALIND Then she puts you to entreaty, and there begins new matter. + +ORLANDO Who could be out, being before his beloved mistress? + +ROSALIND Marry, that should you, if I were your mistress, or + I should think my honesty ranker than my wit. + +ORLANDO What, of my suit? + +ROSALIND Not out of your apparel, and yet out of your suit. + Am not I your Rosalind? + +ORLANDO I take some joy to say you are, because I would be + talking of her. + +ROSALIND Well in her person I say I will not have you. + +ORLANDO Then in mine own person I die. + +ROSALIND No, faith, die by attorney. The poor world is + almost six thousand years old, and in all this time + there was not any man died in his own person, + videlicit, in a love-cause. Troilus had his brains + dashed out with a Grecian club; yet he did what he + could to die before, and he is one of the patterns + of love. Leander, he would have lived many a fair + year, though Hero had turned nun, if it had not been + for a hot midsummer night; for, good youth, he went + but forth to wash him in the Hellespont and being + taken with the cramp was drowned and the foolish + coroners of that age found it was 'Hero of Sestos.' + But these are all lies: men have died from time to + time and worms have eaten them, but not for love. + +ORLANDO I would not have my right Rosalind of this mind, + for, I protest, her frown might kill me. + +ROSALIND By this hand, it will not kill a fly. But come, now + I will be your Rosalind in a more coming-on + disposition, and ask me what you will. I will grant + it. + +ORLANDO Then love me, Rosalind. + +ROSALIND Yes, faith, will I, Fridays and Saturdays and all. + +ORLANDO And wilt thou have me? + +ROSALIND Ay, and twenty such. + +ORLANDO What sayest thou? + +ROSALIND Are you not good? + +ORLANDO I hope so. + +ROSALIND Why then, can one desire too much of a good thing? + Come, sister, you shall be the priest and marry us. + Give me your hand, Orlando. What do you say, sister? + +ORLANDO Pray thee, marry us. + +CELIA I cannot say the words. + +ROSALIND You must begin, 'Will you, Orlando--' + +CELIA Go to. Will you, Orlando, have to wife this Rosalind? + +ORLANDO I will. + +ROSALIND Ay, but when? + +ORLANDO Why now; as fast as she can marry us. + +ROSALIND Then you must say 'I take thee, Rosalind, for wife.' + +ORLANDO I take thee, Rosalind, for wife. + +ROSALIND I might ask you for your commission; but I do take + thee, Orlando, for my husband: there's a girl goes + before the priest; and certainly a woman's thought + runs before her actions. + +ORLANDO So do all thoughts; they are winged. + +ROSALIND Now tell me how long you would have her after you + have possessed her. + +ORLANDO For ever and a day. + +ROSALIND Say 'a day,' without the 'ever.' No, no, Orlando; + men are April when they woo, December when they wed: + maids are May when they are maids, but the sky + changes when they are wives. I will be more jealous + of thee than a Barbary cock-pigeon over his hen, + more clamorous than a parrot against rain, more + new-fangled than an ape, more giddy in my desires + than a monkey: I will weep for nothing, like Diana + in the fountain, and I will do that when you are + disposed to be merry; I will laugh like a hyen, and + that when thou art inclined to sleep. + +ORLANDO But will my Rosalind do so? + +ROSALIND By my life, she will do as I do. + +ORLANDO O, but she is wise. + +ROSALIND Or else she could not have the wit to do this: the + wiser, the waywarder: make the doors upon a woman's + wit and it will out at the casement; shut that and + 'twill out at the key-hole; stop that, 'twill fly + with the smoke out at the chimney. + +ORLANDO A man that had a wife with such a wit, he might say + 'Wit, whither wilt?' + +ROSALIND Nay, you might keep that cheque for it till you met + your wife's wit going to your neighbour's bed. + +ORLANDO And what wit could wit have to excuse that? + +ROSALIND Marry, to say she came to seek you there. You shall + never take her without her answer, unless you take + her without her tongue. O, that woman that cannot + make her fault her husband's occasion, let her + never nurse her child herself, for she will breed + it like a fool! + +ORLANDO For these two hours, Rosalind, I will leave thee. + +ROSALIND Alas! dear love, I cannot lack thee two hours. + +ORLANDO I must attend the duke at dinner: by two o'clock I + will be with thee again. + +ROSALIND Ay, go your ways, go your ways; I knew what you + would prove: my friends told me as much, and I + thought no less: that flattering tongue of yours + won me: 'tis but one cast away, and so, come, + death! Two o'clock is your hour? + +ORLANDO Ay, sweet Rosalind. + +ROSALIND By my troth, and in good earnest, and so God mend + me, and by all pretty oaths that are not dangerous, + if you break one jot of your promise or come one + minute behind your hour, I will think you the most + pathetical break-promise and the most hollow lover + and the most unworthy of her you call Rosalind that + may be chosen out of the gross band of the + unfaithful: therefore beware my censure and keep + your promise. + +ORLANDO With no less religion than if thou wert indeed my + Rosalind: so adieu. + +ROSALIND Well, Time is the old justice that examines all such + offenders, and let Time try: adieu. + + [Exit ORLANDO] + +CELIA You have simply misused our sex in your love-prate: + we must have your doublet and hose plucked over your + head, and show the world what the bird hath done to + her own nest. + +ROSALIND O coz, coz, coz, my pretty little coz, that thou + didst know how many fathom deep I am in love! But + it cannot be sounded: my affection hath an unknown + bottom, like the bay of Portugal. + +CELIA Or rather, bottomless, that as fast as you pour + affection in, it runs out. + +ROSALIND No, that same wicked bastard of Venus that was begot + of thought, conceived of spleen and born of madness, + that blind rascally boy that abuses every one's eyes + because his own are out, let him be judge how deep I + am in love. I'll tell thee, Aliena, I cannot be out + of the sight of Orlando: I'll go find a shadow and + sigh till he come. + +CELIA And I'll sleep. + + [Exeunt] + + + + + AS YOU LIKE IT + + +ACT IV + + + +SCENE II The forest. + + + [Enter JAQUES, Lords, and Foresters] + +JAQUES Which is he that killed the deer? + +A Lord Sir, it was I. + +JAQUES Let's present him to the duke, like a Roman + conqueror; and it would do well to set the deer's + horns upon his head, for a branch of victory. Have + you no song, forester, for this purpose? + +Forester Yes, sir. + +JAQUES Sing it: 'tis no matter how it be in tune, so it + make noise enough. + + SONG. +Forester What shall he have that kill'd the deer? + His leather skin and horns to wear. + Then sing him home; + + [The rest shall bear this burden] + + Take thou no scorn to wear the horn; + It was a crest ere thou wast born: + Thy father's father wore it, + And thy father bore it: + The horn, the horn, the lusty horn + Is not a thing to laugh to scorn. + + [Exeunt] + + + + + AS YOU LIKE IT + + +ACT IV + + + +SCENE III The forest. + + + [Enter ROSALIND and CELIA] + +ROSALIND How say you now? Is it not past two o'clock? and + here much Orlando! + +CELIA I warrant you, with pure love and troubled brain, he + hath ta'en his bow and arrows and is gone forth to + sleep. Look, who comes here. + + [Enter SILVIUS] + +SILVIUS My errand is to you, fair youth; + My gentle Phebe bid me give you this: + I know not the contents; but, as I guess + By the stern brow and waspish action + Which she did use as she was writing of it, + It bears an angry tenor: pardon me: + I am but as a guiltless messenger. + +ROSALIND Patience herself would startle at this letter + And play the swaggerer; bear this, bear all: + She says I am not fair, that I lack manners; + She calls me proud, and that she could not love me, + Were man as rare as phoenix. 'Od's my will! + Her love is not the hare that I do hunt: + Why writes she so to me? Well, shepherd, well, + This is a letter of your own device. + +SILVIUS No, I protest, I know not the contents: + Phebe did write it. + +ROSALIND Come, come, you are a fool + And turn'd into the extremity of love. + I saw her hand: she has a leathern hand. + A freestone-colour'd hand; I verily did think + That her old gloves were on, but 'twas her hands: + She has a huswife's hand; but that's no matter: + I say she never did invent this letter; + This is a man's invention and his hand. + +SILVIUS Sure, it is hers. + +ROSALIND Why, 'tis a boisterous and a cruel style. + A style for-challengers; why, she defies me, + Like Turk to Christian: women's gentle brain + Could not drop forth such giant-rude invention + Such Ethiope words, blacker in their effect + Than in their countenance. Will you hear the letter? + +SILVIUS So please you, for I never heard it yet; + Yet heard too much of Phebe's cruelty. + +ROSALIND She Phebes me: mark how the tyrant writes. + + [Reads] + + Art thou god to shepherd turn'd, + That a maiden's heart hath burn'd? + Can a woman rail thus? + +SILVIUS Call you this railing? + +ROSALIND [Reads] + + Why, thy godhead laid apart, + Warr'st thou with a woman's heart? + Did you ever hear such railing? + Whiles the eye of man did woo me, + That could do no vengeance to me. + Meaning me a beast. + If the scorn of your bright eyne + Have power to raise such love in mine, + Alack, in me what strange effect + Would they work in mild aspect! + Whiles you chid me, I did love; + How then might your prayers move! + He that brings this love to thee + Little knows this love in me: + And by him seal up thy mind; + Whether that thy youth and kind + Will the faithful offer take + Of me and all that I can make; + Or else by him my love deny, + And then I'll study how to die. + +SILVIUS Call you this chiding? + +CELIA Alas, poor shepherd! + +ROSALIND Do you pity him? no, he deserves no pity. Wilt + thou love such a woman? What, to make thee an + instrument and play false strains upon thee! not to + be endured! Well, go your way to her, for I see + love hath made thee a tame snake, and say this to + her: that if she love me, I charge her to love + thee; if she will not, I will never have her unless + thou entreat for her. If you be a true lover, + hence, and not a word; for here comes more company. + + [Exit SILVIUS] + + [Enter OLIVER] + +OLIVER Good morrow, fair ones: pray you, if you know, + Where in the purlieus of this forest stands + A sheep-cote fenced about with olive trees? + +CELIA West of this place, down in the neighbour bottom: + The rank of osiers by the murmuring stream + Left on your right hand brings you to the place. + But at this hour the house doth keep itself; + There's none within. + +OLIVER If that an eye may profit by a tongue, + Then should I know you by description; + Such garments and such years: 'The boy is fair, + Of female favour, and bestows himself + Like a ripe sister: the woman low + And browner than her brother.' Are not you + The owner of the house I did inquire for? + +CELIA It is no boast, being ask'd, to say we are. + +OLIVER Orlando doth commend him to you both, + And to that youth he calls his Rosalind + He sends this bloody napkin. Are you he? + +ROSALIND I am: what must we understand by this? + +OLIVER Some of my shame; if you will know of me + What man I am, and how, and why, and where + This handkercher was stain'd. + +CELIA I pray you, tell it. + +OLIVER When last the young Orlando parted from you + He left a promise to return again + Within an hour, and pacing through the forest, + Chewing the food of sweet and bitter fancy, + Lo, what befell! he threw his eye aside, + And mark what object did present itself: + Under an oak, whose boughs were moss'd with age + And high top bald with dry antiquity, + A wretched ragged man, o'ergrown with hair, + Lay sleeping on his back: about his neck + A green and gilded snake had wreathed itself, + Who with her head nimble in threats approach'd + The opening of his mouth; but suddenly, + Seeing Orlando, it unlink'd itself, + And with indented glides did slip away + Into a bush: under which bush's shade + A lioness, with udders all drawn dry, + Lay couching, head on ground, with catlike watch, + When that the sleeping man should stir; for 'tis + The royal disposition of that beast + To prey on nothing that doth seem as dead: + This seen, Orlando did approach the man + And found it was his brother, his elder brother. + +CELIA O, I have heard him speak of that same brother; + And he did render him the most unnatural + That lived amongst men. + +OLIVER And well he might so do, + For well I know he was unnatural. + +ROSALIND But, to Orlando: did he leave him there, + Food to the suck'd and hungry lioness? + +OLIVER Twice did he turn his back and purposed so; + But kindness, nobler ever than revenge, + And nature, stronger than his just occasion, + Made him give battle to the lioness, + Who quickly fell before him: in which hurtling + From miserable slumber I awaked. + +CELIA Are you his brother? + +ROSALIND Wast you he rescued? + +CELIA Was't you that did so oft contrive to kill him? + +OLIVER 'Twas I; but 'tis not I I do not shame + To tell you what I was, since my conversion + So sweetly tastes, being the thing I am. + +ROSALIND But, for the bloody napkin? + +OLIVER By and by. + When from the first to last betwixt us two + Tears our recountments had most kindly bathed, + As how I came into that desert place:-- + In brief, he led me to the gentle duke, + Who gave me fresh array and entertainment, + Committing me unto my brother's love; + Who led me instantly unto his cave, + There stripp'd himself, and here upon his arm + The lioness had torn some flesh away, + Which all this while had bled; and now he fainted + And cried, in fainting, upon Rosalind. + Brief, I recover'd him, bound up his wound; + And, after some small space, being strong at heart, + He sent me hither, stranger as I am, + To tell this story, that you might excuse + His broken promise, and to give this napkin + Dyed in his blood unto the shepherd youth + That he in sport doth call his Rosalind. + + [ROSALIND swoons] + +CELIA Why, how now, Ganymede! sweet Ganymede! + +OLIVER Many will swoon when they do look on blood. + +CELIA There is more in it. Cousin Ganymede! + +OLIVER Look, he recovers. + +ROSALIND I would I were at home. + +CELIA We'll lead you thither. + I pray you, will you take him by the arm? + +OLIVER Be of good cheer, youth: you a man! you lack a + man's heart. + +ROSALIND I do so, I confess it. Ah, sirrah, a body would + think this was well counterfeited! I pray you, tell + your brother how well I counterfeited. Heigh-ho! + +OLIVER This was not counterfeit: there is too great + testimony in your complexion that it was a passion + of earnest. + +ROSALIND Counterfeit, I assure you. + +OLIVER Well then, take a good heart and counterfeit to be a man. + +ROSALIND So I do: but, i' faith, I should have been a woman by right. + +CELIA Come, you look paler and paler: pray you, draw + homewards. Good sir, go with us. + +OLIVER That will I, for I must bear answer back + How you excuse my brother, Rosalind. + +ROSALIND I shall devise something: but, I pray you, commend + my counterfeiting to him. Will you go? + + [Exeunt] + + + + + AS YOU LIKE IT + + +ACT V + + + +SCENE I The forest. + + + [Enter TOUCHSTONE and AUDREY] + +TOUCHSTONE We shall find a time, Audrey; patience, gentle Audrey. + +AUDREY Faith, the priest was good enough, for all the old + gentleman's saying. + +TOUCHSTONE A most wicked Sir Oliver, Audrey, a most vile + Martext. But, Audrey, there is a youth here in the + forest lays claim to you. + +AUDREY Ay, I know who 'tis; he hath no interest in me in + the world: here comes the man you mean. + +TOUCHSTONE It is meat and drink to me to see a clown: by my + troth, we that have good wits have much to answer + for; we shall be flouting; we cannot hold. + + [Enter WILLIAM] + +WILLIAM Good even, Audrey. + +AUDREY God ye good even, William. + +WILLIAM And good even to you, sir. + +TOUCHSTONE Good even, gentle friend. Cover thy head, cover thy + head; nay, prithee, be covered. How old are you, friend? + +WILLIAM Five and twenty, sir. + +TOUCHSTONE A ripe age. Is thy name William? + +WILLIAM William, sir. + +TOUCHSTONE A fair name. Wast born i' the forest here? + +WILLIAM Ay, sir, I thank God. + +TOUCHSTONE 'Thank God;' a good answer. Art rich? + +WILLIAM Faith, sir, so so. + +TOUCHSTONE 'So so' is good, very good, very excellent good; and + yet it is not; it is but so so. Art thou wise? + +WILLIAM Ay, sir, I have a pretty wit. + +TOUCHSTONE Why, thou sayest well. I do now remember a saying, + 'The fool doth think he is wise, but the wise man + knows himself to be a fool.' The heathen + philosopher, when he had a desire to eat a grape, + would open his lips when he put it into his mouth; + meaning thereby that grapes were made to eat and + lips to open. You do love this maid? + +WILLIAM I do, sir. + +TOUCHSTONE Give me your hand. Art thou learned? + +WILLIAM No, sir. + +TOUCHSTONE Then learn this of me: to have, is to have; for it + is a figure in rhetoric that drink, being poured out + of a cup into a glass, by filling the one doth empty + the other; for all your writers do consent that ipse + is he: now, you are not ipse, for I am he. + +WILLIAM Which he, sir? + +TOUCHSTONE He, sir, that must marry this woman. Therefore, you + clown, abandon,--which is in the vulgar leave,--the + society,--which in the boorish is company,--of this + female,--which in the common is woman; which + together is, abandon the society of this female, or, + clown, thou perishest; or, to thy better + understanding, diest; or, to wit I kill thee, make + thee away, translate thy life into death, thy + liberty into bondage: I will deal in poison with + thee, or in bastinado, or in steel; I will bandy + with thee in faction; I will o'errun thee with + policy; I will kill thee a hundred and fifty ways: + therefore tremble and depart. + +AUDREY Do, good William. + +WILLIAM God rest you merry, sir. + + [Exit] + + [Enter CORIN] + +CORIN Our master and mistress seeks you; come, away, away! + +TOUCHSTONE Trip, Audrey! trip, Audrey! I attend, I attend. + + [Exeunt] + + + + + AS YOU LIKE IT + + +ACT V + + + +SCENE II The forest. + + + [Enter ORLANDO and OLIVER] + +ORLANDO Is't possible that on so little acquaintance you + should like her? that but seeing you should love + her? and loving woo? and, wooing, she should + grant? and will you persever to enjoy her? + +OLIVER Neither call the giddiness of it in question, the + poverty of her, the small acquaintance, my sudden + wooing, nor her sudden consenting; but say with me, + I love Aliena; say with her that she loves me; + consent with both that we may enjoy each other: it + shall be to your good; for my father's house and all + the revenue that was old Sir Rowland's will I + estate upon you, and here live and die a shepherd. + +ORLANDO You have my consent. Let your wedding be to-morrow: + thither will I invite the duke and all's contented + followers. Go you and prepare Aliena; for look + you, here comes my Rosalind. + + [Enter ROSALIND] + +ROSALIND God save you, brother. + +OLIVER And you, fair sister. + + [Exit] + +ROSALIND O, my dear Orlando, how it grieves me to see thee + wear thy heart in a scarf! + +ORLANDO It is my arm. + +ROSALIND I thought thy heart had been wounded with the claws + of a lion. + +ORLANDO Wounded it is, but with the eyes of a lady. + +ROSALIND Did your brother tell you how I counterfeited to + swoon when he showed me your handkerchief? + +ORLANDO Ay, and greater wonders than that. + +ROSALIND O, I know where you are: nay, 'tis true: there was + never any thing so sudden but the fight of two rams + and Caesar's thrasonical brag of 'I came, saw, and + overcame:' for your brother and my sister no sooner + met but they looked, no sooner looked but they + loved, no sooner loved but they sighed, no sooner + sighed but they asked one another the reason, no + sooner knew the reason but they sought the remedy; + and in these degrees have they made a pair of stairs + to marriage which they will climb incontinent, or + else be incontinent before marriage: they are in + the very wrath of love and they will together; clubs + cannot part them. + +ORLANDO They shall be married to-morrow, and I will bid the + duke to the nuptial. But, O, how bitter a thing it + is to look into happiness through another man's + eyes! By so much the more shall I to-morrow be at + the height of heart-heaviness, by how much I shall + think my brother happy in having what he wishes for. + +ROSALIND Why then, to-morrow I cannot serve your turn for Rosalind? + +ORLANDO I can live no longer by thinking. + +ROSALIND I will weary you then no longer with idle talking. + Know of me then, for now I speak to some purpose, + that I know you are a gentleman of good conceit: I + speak not this that you should bear a good opinion + of my knowledge, insomuch I say I know you are; + neither do I labour for a greater esteem than may in + some little measure draw a belief from you, to do + yourself good and not to grace me. Believe then, if + you please, that I can do strange things: I have, + since I was three year old, conversed with a + magician, most profound in his art and yet not + damnable. If you do love Rosalind so near the heart + as your gesture cries it out, when your brother + marries Aliena, shall you marry her: I know into + what straits of fortune she is driven; and it is + not impossible to me, if it appear not inconvenient + to you, to set her before your eyes tomorrow human + as she is and without any danger. + +ORLANDO Speakest thou in sober meanings? + +ROSALIND By my life, I do; which I tender dearly, though I + say I am a magician. Therefore, put you in your + best array: bid your friends; for if you will be + married to-morrow, you shall, and to Rosalind, if you will. + + [Enter SILVIUS and PHEBE] + + Look, here comes a lover of mine and a lover of hers. + +PHEBE Youth, you have done me much ungentleness, + To show the letter that I writ to you. + +ROSALIND I care not if I have: it is my study + To seem despiteful and ungentle to you: + You are there followed by a faithful shepherd; + Look upon him, love him; he worships you. + +PHEBE Good shepherd, tell this youth what 'tis to love. + +SILVIUS It is to be all made of sighs and tears; + And so am I for Phebe. + +PHEBE And I for Ganymede. + +ORLANDO And I for Rosalind. + +ROSALIND And I for no woman. + +SILVIUS It is to be all made of faith and service; + And so am I for Phebe. + +PHEBE And I for Ganymede. + +ORLANDO And I for Rosalind. + +ROSALIND And I for no woman. + +SILVIUS It is to be all made of fantasy, + All made of passion and all made of wishes, + All adoration, duty, and observance, + All humbleness, all patience and impatience, + All purity, all trial, all observance; + And so am I for Phebe. + +PHEBE And so am I for Ganymede. + +ORLANDO And so am I for Rosalind. + +ROSALIND And so am I for no woman. + +PHEBE If this be so, why blame you me to love you? + +SILVIUS If this be so, why blame you me to love you? + +ORLANDO If this be so, why blame you me to love you? + +ROSALIND Who do you speak to, 'Why blame you me to love you?' + +ORLANDO To her that is not here, nor doth not hear. + +ROSALIND Pray you, no more of this; 'tis like the howling + of Irish wolves against the moon. + + [To SILVIUS] + + I will help you, if I can: + + [To PHEBE] + + I would love you, if I could. To-morrow meet me all together. + + [To PHEBE] + + I will marry you, if ever I marry woman, and I'll be + married to-morrow: + + [To ORLANDO] + + I will satisfy you, if ever I satisfied man, and you + shall be married to-morrow: + + [To SILVIUS] + + I will content you, if what pleases you contents + you, and you shall be married to-morrow. + + [To ORLANDO] + + As you love Rosalind, meet: + + [To SILVIUS] + + as you love Phebe, meet: and as I love no woman, + I'll meet. So fare you well: I have left you commands. + +SILVIUS I'll not fail, if I live. + +PHEBE Nor I. + +ORLANDO Nor I. + + [Exeunt] + + + + + AS YOU LIKE IT + + +ACT V + + + +SCENE III The forest. + + + [Enter TOUCHSTONE and AUDREY] + +TOUCHSTONE To-morrow is the joyful day, Audrey; to-morrow will + we be married. + +AUDREY I do desire it with all my heart; and I hope it is + no dishonest desire to desire to be a woman of the + world. Here comes two of the banished duke's pages. + + [Enter two Pages] + +First Page Well met, honest gentleman. + +TOUCHSTONE By my troth, well met. Come, sit, sit, and a song. + +Second Page We are for you: sit i' the middle. + +First Page Shall we clap into't roundly, without hawking or + spitting or saying we are hoarse, which are the only + prologues to a bad voice? + +Second Page I'faith, i'faith; and both in a tune, like two + gipsies on a horse. + + SONG. + It was a lover and his lass, + With a hey, and a ho, and a hey nonino, + That o'er the green corn-field did pass + In the spring time, the only pretty ring time, + When birds do sing, hey ding a ding, ding: + Sweet lovers love the spring. + + Between the acres of the rye, + With a hey, and a ho, and a hey nonino + These pretty country folks would lie, + In spring time, &c. + + This carol they began that hour, + With a hey, and a ho, and a hey nonino, + How that a life was but a flower + In spring time, &c. + + And therefore take the present time, + With a hey, and a ho, and a hey nonino; + For love is crowned with the prime + In spring time, &c. + +TOUCHSTONE Truly, young gentlemen, though there was no great + matter in the ditty, yet the note was very + untuneable. + +First Page You are deceived, sir: we kept time, we lost not our time. + +TOUCHSTONE By my troth, yes; I count it but time lost to hear + such a foolish song. God be wi' you; and God mend + your voices! Come, Audrey. + + [Exeunt] + + + + + AS YOU LIKE IT + + +ACT V + + + +SCENE IV The forest. + + + [Enter DUKE SENIOR, AMIENS, JAQUES, ORLANDO, OLIVER, + and CELIA] + +DUKE SENIOR Dost thou believe, Orlando, that the boy + Can do all this that he hath promised? + +ORLANDO I sometimes do believe, and sometimes do not; + As those that fear they hope, and know they fear. + + [Enter ROSALIND, SILVIUS, and PHEBE] + +ROSALIND Patience once more, whiles our compact is urged: + You say, if I bring in your Rosalind, + You will bestow her on Orlando here? + +DUKE SENIOR That would I, had I kingdoms to give with her. + +ROSALIND And you say, you will have her, when I bring her? + +ORLANDO That would I, were I of all kingdoms king. + +ROSALIND You say, you'll marry me, if I be willing? + +PHEBE That will I, should I die the hour after. + +ROSALIND But if you do refuse to marry me, + You'll give yourself to this most faithful shepherd? + +PHEBE So is the bargain. + +ROSALIND You say, that you'll have Phebe, if she will? + +SILVIUS Though to have her and death were both one thing. + +ROSALIND I have promised to make all this matter even. + Keep you your word, O duke, to give your daughter; + You yours, Orlando, to receive his daughter: + Keep your word, Phebe, that you'll marry me, + Or else refusing me, to wed this shepherd: + Keep your word, Silvius, that you'll marry her. + If she refuse me: and from hence I go, + To make these doubts all even. + + [Exeunt ROSALIND and CELIA] + +DUKE SENIOR I do remember in this shepherd boy + Some lively touches of my daughter's favour. + +ORLANDO My lord, the first time that I ever saw him + Methought he was a brother to your daughter: + But, my good lord, this boy is forest-born, + And hath been tutor'd in the rudiments + Of many desperate studies by his uncle, + Whom he reports to be a great magician, + Obscured in the circle of this forest. + + [Enter TOUCHSTONE and AUDREY] + +JAQUES There is, sure, another flood toward, and these + couples are coming to the ark. Here comes a pair of + very strange beasts, which in all tongues are called fools. + +TOUCHSTONE Salutation and greeting to you all! + +JAQUES Good my lord, bid him welcome: this is the + motley-minded gentleman that I have so often met in + the forest: he hath been a courtier, he swears. + +TOUCHSTONE If any man doubt that, let him put me to my + purgation. I have trod a measure; I have flattered + a lady; I have been politic with my friend, smooth + with mine enemy; I have undone three tailors; I have + had four quarrels, and like to have fought one. + +JAQUES And how was that ta'en up? + +TOUCHSTONE Faith, we met, and found the quarrel was upon the + seventh cause. + +JAQUES How seventh cause? Good my lord, like this fellow. + +DUKE SENIOR I like him very well. + +TOUCHSTONE God 'ild you, sir; I desire you of the like. I + press in here, sir, amongst the rest of the country + copulatives, to swear and to forswear: according as + marriage binds and blood breaks: a poor virgin, + sir, an ill-favoured thing, sir, but mine own; a poor + humour of mine, sir, to take that that no man else + will: rich honesty dwells like a miser, sir, in a + poor house; as your pearl in your foul oyster. + +DUKE SENIOR By my faith, he is very swift and sententious. + +TOUCHSTONE According to the fool's bolt, sir, and such dulcet diseases. + +JAQUES But, for the seventh cause; how did you find the + quarrel on the seventh cause? + +TOUCHSTONE Upon a lie seven times removed:--bear your body more + seeming, Audrey:--as thus, sir. I did dislike the + cut of a certain courtier's beard: he sent me word, + if I said his beard was not cut well, he was in the + mind it was: this is called the Retort Courteous. + If I sent him word again 'it was not well cut,' he + would send me word, he cut it to please himself: + this is called the Quip Modest. If again 'it was + not well cut,' he disabled my judgment: this is + called the Reply Churlish. If again 'it was not + well cut,' he would answer, I spake not true: this + is called the Reproof Valiant. If again 'it was not + well cut,' he would say I lied: this is called the + Counter-cheque Quarrelsome: and so to the Lie + Circumstantial and the Lie Direct. + +JAQUES And how oft did you say his beard was not well cut? + +TOUCHSTONE I durst go no further than the Lie Circumstantial, + nor he durst not give me the Lie Direct; and so we + measured swords and parted. + +JAQUES Can you nominate in order now the degrees of the lie? + +TOUCHSTONE O sir, we quarrel in print, by the book; as you have + books for good manners: I will name you the degrees. + The first, the Retort Courteous; the second, the + Quip Modest; the third, the Reply Churlish; the + fourth, the Reproof Valiant; the fifth, the + Countercheque Quarrelsome; the sixth, the Lie with + Circumstance; the seventh, the Lie Direct. All + these you may avoid but the Lie Direct; and you may + avoid that too, with an If. I knew when seven + justices could not take up a quarrel, but when the + parties were met themselves, one of them thought but + of an If, as, 'If you said so, then I said so;' and + they shook hands and swore brothers. Your If is the + only peacemaker; much virtue in If. + +JAQUES Is not this a rare fellow, my lord? he's as good at + any thing and yet a fool. + +DUKE SENIOR He uses his folly like a stalking-horse and under + the presentation of that he shoots his wit. + + [Enter HYMEN, ROSALIND, and CELIA] + + [Still Music] + +HYMEN Then is there mirth in heaven, + When earthly things made even + Atone together. + Good duke, receive thy daughter + Hymen from heaven brought her, + Yea, brought her hither, + That thou mightst join her hand with his + Whose heart within his bosom is. + +ROSALIND [To DUKE SENIOR] To you I give myself, for I am yours. + + [To ORLANDO] + + To you I give myself, for I am yours. + +DUKE SENIOR If there be truth in sight, you are my daughter. + +ORLANDO If there be truth in sight, you are my Rosalind. + +PHEBE If sight and shape be true, + Why then, my love adieu! + +ROSALIND I'll have no father, if you be not he: + I'll have no husband, if you be not he: + Nor ne'er wed woman, if you be not she. + +HYMEN Peace, ho! I bar confusion: + 'Tis I must make conclusion + Of these most strange events: + Here's eight that must take hands + To join in Hymen's bands, + If truth holds true contents. + You and you no cross shall part: + You and you are heart in heart + You to his love must accord, + Or have a woman to your lord: + You and you are sure together, + As the winter to foul weather. + Whiles a wedlock-hymn we sing, + Feed yourselves with questioning; + That reason wonder may diminish, + How thus we met, and these things finish. + + SONG. + Wedding is great Juno's crown: + O blessed bond of board and bed! + 'Tis Hymen peoples every town; + High wedlock then be honoured: + Honour, high honour and renown, + To Hymen, god of every town! + +DUKE SENIOR O my dear niece, welcome thou art to me! + Even daughter, welcome, in no less degree. + +PHEBE I will not eat my word, now thou art mine; + Thy faith my fancy to thee doth combine. + + [Enter JAQUES DE BOYS] + +JAQUES DE BOYS Let me have audience for a word or two: + I am the second son of old Sir Rowland, + That bring these tidings to this fair assembly. + Duke Frederick, hearing how that every day + Men of great worth resorted to this forest, + Address'd a mighty power; which were on foot, + In his own conduct, purposely to take + His brother here and put him to the sword: + And to the skirts of this wild wood he came; + Where meeting with an old religious man, + After some question with him, was converted + Both from his enterprise and from the world, + His crown bequeathing to his banish'd brother, + And all their lands restored to them again + That were with him exiled. This to be true, + I do engage my life. + +DUKE SENIOR Welcome, young man; + Thou offer'st fairly to thy brothers' wedding: + To one his lands withheld, and to the other + A land itself at large, a potent dukedom. + First, in this forest, let us do those ends + That here were well begun and well begot: + And after, every of this happy number + That have endured shrewd days and nights with us + Shall share the good of our returned fortune, + According to the measure of their states. + Meantime, forget this new-fall'n dignity + And fall into our rustic revelry. + Play, music! And you, brides and bridegrooms all, + With measure heap'd in joy, to the measures fall. + +JAQUES Sir, by your patience. If I heard you rightly, + The duke hath put on a religious life + And thrown into neglect the pompous court? + +JAQUES DE BOYS He hath. + +JAQUES To him will I : out of these convertites + There is much matter to be heard and learn'd. + + [To DUKE SENIOR] + + You to your former honour I bequeath; + Your patience and your virtue well deserves it: + + [To ORLANDO] + + You to a love that your true faith doth merit: + + [To OLIVER] + + You to your land and love and great allies: + + [To SILVIUS] + + You to a long and well-deserved bed: + + [To TOUCHSTONE] + + And you to wrangling; for thy loving voyage + Is but for two months victuall'd. So, to your pleasures: + I am for other than for dancing measures. + +DUKE SENIOR Stay, Jaques, stay. + +JAQUES To see no pastime I what you would have + I'll stay to know at your abandon'd cave. + + [Exit] + +DUKE SENIOR Proceed, proceed: we will begin these rites, + As we do trust they'll end, in true delights. + + [A dance] + + + + + AS YOU LIKE IT + + EPILOGUE + + +ROSALIND It is not the fashion to see the lady the epilogue; + but it is no more unhandsome than to see the lord + the prologue. If it be true that good wine needs + no bush, 'tis true that a good play needs no + epilogue; yet to good wine they do use good bushes, + and good plays prove the better by the help of good + epilogues. What a case am I in then, that am + neither a good epilogue nor cannot insinuate with + you in the behalf of a good play! I am not + furnished like a beggar, therefore to beg will not + become me: my way is to conjure you; and I'll begin + with the women. I charge you, O women, for the love + you bear to men, to like as much of this play as + please you: and I charge you, O men, for the love + you bear to women--as I perceive by your simpering, + none of you hates them--that between you and the + women the play may please. If I were a woman I + would kiss as many of you as had beards that pleased + me, complexions that liked me and breaths that I + defied not: and, I am sure, as many as have good + beards or good faces or sweet breaths will, for my + kind offer, when I make curtsy, bid me farewell. + + [Exeunt] diff --git a/snappy/snappy-1.0.5/testdata/baddata1.snappy b/snappy/snappy-1.0.5/testdata/baddata1.snappy new file mode 100644 index 00000000..99d970fb Binary files /dev/null and b/snappy/snappy-1.0.5/testdata/baddata1.snappy differ diff --git a/snappy/snappy-1.0.5/testdata/baddata2.snappy b/snappy/snappy-1.0.5/testdata/baddata2.snappy new file mode 100644 index 00000000..8f5cb13e Binary files /dev/null and b/snappy/snappy-1.0.5/testdata/baddata2.snappy differ diff --git a/snappy/snappy-1.0.5/testdata/baddata3.snappy b/snappy/snappy-1.0.5/testdata/baddata3.snappy new file mode 100644 index 00000000..774aead4 Binary files /dev/null and b/snappy/snappy-1.0.5/testdata/baddata3.snappy differ diff --git a/snappy/snappy-1.0.5/testdata/cp.html b/snappy/snappy-1.0.5/testdata/cp.html new file mode 100644 index 00000000..1d0ca37e --- /dev/null +++ b/snappy/snappy-1.0.5/testdata/cp.html @@ -0,0 +1,645 @@ + +Compression Pointers + + + + + +
+

Compression Pointers

+ + + +
+ +

+Compression resources, conferences, and some research +groups and companies, are listed towards the end of this page.

+ +Use this handy form to add something to this page, or to simply say you liked this page +

+ + + + + +

+ +

What's New?

+ + +Jean-loup Gailly -- Mr. gzip, +PNG, CCR (1996-06-10) + +
+ +MPEG Pointers and Resources + +
+ +Robert M. Gray -- Signal +compression, VQ, image quality evaluation (1996-04-22) +
+ +Compression and +Classification Group -- ISL,EE,Stanford (1996-04-22) +
+ +Signal Processing +and the International Information Infrastructure -- Web sites (1996-04-22) +
+ +Valenta, Vladimir -- (1996-04-22) +
+ + +Jordan, Frederic -- Parallel Image Compression (1996-04-12) +
+Electro-Optical Technologies, Inc. -- Consultant (1996-04-12) +
+quicktime.apple.com -- Quicktime site (1996-03-11) +
+IBM Hardware -- Compression chips (1996-03-11) +
+ + + + + + + + + + + + + + + + + + + + + + + + +

+ + +

+ + +

People

+

A

+ +Adler, Mark -- Info-ZIP; Zip, UnZip, gzip and zlib co-author; PNG group +

+ +

B

+ +Baker, Matthew -- Region based video compression +

+Bamberger, Roberto H. +

+Bell, Daniel -- Region based image compression +

+Bell, Tim -- compression, computer science for children, and computers and music. +

+Bellard, Fabrice -- Author of LZEXE +

+Berghorn, Willy +

+Bhaskaran, Vasudev -- Image and Video compression +

+Bloom, Charles -- text compression, LZ methods, PPM methods... +

+Brito, Roger -- Arithmetic Coding, LZW, Text Compression +

+Budge, Scott E. -- medical/lossy image compression +

+Burnett, Ian -- Speech coding, prototype waveform techniques +

+ + +

C

+ +Chan, Christopher -- universal lossy source coding, adaptive VQ +

+Chao, Hong-yang -- Lightning strike image compressor +

+Chao, Stewart +

+Cherriman, Peter +

+Cheung, S.C. -- Scalable video compression algorithms (18th Feb 1996) +

+ +Christopoulos, Charilaos -- Image and Video compression +

+Chrysafis, Christos +

+Chung, Wilson C. -- R-D image and video coding, subband/wavelet, filter banks +

+Clark, Alan -- primary contact for V.42bis. Developed BTLZ variant of LZW +

+Cleary, John -- PPM, PPM*, K* +

+Cohn, Martin +

+ +Cormack, Gordon V. -- DMC +

+Cramer, Chris -- neural network image compression +

+ +

D

+Danskin, John -- Protocol compression, document compression (9th Feb 1996) +

+Davis, Geoff -- wavelets, image compression, medical +

+Dilger, Andreas -- fractal block coding of video sequences +

+ + +

E

+Estes, Robert +

+ + + +

F

+Fisher, Yuval -- Fractal Image Compression +

+Ford, Adrian -- Subjective and Objective Compression quality (5th Mar 1996) +

+ +

G

+Jean-loup Gailly -- +Mr. gzip, PNG, CCR (1996-06-10) +

+ +Gersho, Allen -- Vector Quantisation, Image Compression +

+Goertzel, Ben +

+Gooch, Mark -- High Performance Hardware Compression (7th Feb 1996) +

+Goyal, Vivek -- overcomplete representations, adaptive transform coding, VQ +

+Robert M. Gray -- Signal +compression, VQ, image quality evaluation +

+ +

H

+Hafner, Ullrich -- WFA image compression +

+Hirschberg, Dan -- algorithm theory, compression +

+Holland, Scott +

+Horspool, R. Nigel -- text compression, ECG compression + +

I

+Inglis, Stuart -- image compression, OCR, lossy/lossless document compression +

+ +

J

+Jones, Douglas -- splay-tree based compression and encryption +

+Jones, Simon -- Lossless compression, High Performance Hardware (7th Feb 1996) +

+Jordan, Frederic -- Parallel Image Compression (12th April 1996) +

+Jung, Robert K. -- ARJ +

+jutta +

+ + + +

K

+Kominek, John -- Fractal and spline based compression +

+Kjelso, Morten -- Main memory compression, High performance hardware +

+Kuhn, Markus -- JBIG implementation +

+Kuo, C.-C. Jay +

+Kuru, Esa +

+Kyfonidis, Theodoros +

+ +

L

+Lamparter, Bernd +

+Langdon, Glen +

+Larsson, Jesper -- algorithms and data structures, text compression +

+ + +

M

+Manber, Udi +

+Mangen, Jean-Michel -- image compression, wavelets, satellite +

+Moffat, Alistair -- text and index compression, coding methods, information retrieval, document databases +

+Montgomery, Christopher -- OggSquish, audio compression +

+Mueller, Urban Dominik -- XPK system +

+

N

+Neal, Radford +

+Nevill-Manning, Craig +

+Nicholls, Jeremy +

+Noah, Matt -- speech, ATC, ACELP and IMBE +

+Nuri, Veyis -- wavelets, data compression, DSP (speech & image) + +

O

+Oleg -- Lots of code +

+Ortega, Antonio -- Video compression, Packet video, Adaptive quantization +

+Owen, Charles +

+ +

P

+Provine, +Joseph -- Model based coding +

+ +

R

+Robinson, John -- Binary Tree Predictive Coding +

+Roelofs, Greg -- Info-ZIP; primary UnZip author; PNG group +

+Rose, Kenneth +

+Russo, Roberto Maria -- Multiplatform Data Compression +

+ +

S

+Schmidt, Bill +

+Shaw, Sandy C. +

+Sharifi, Kamran -- Video over ATM networks +

+Shende, Sunil M. +

+Silverstein, D. Amnon +

+Smoot, Steve -- MPEG +

+Storer, James A. +

+Streit, Jurgen -- Low bitrate coding +

+Strutz, Tilo -- Wavelet image compressor, demonstration execs +

+ + +

T

+Tate, Steve +

+Teahan, Bill -- PPM, PPM*, master of the Calgary Corpus +

+Thomson, Duncan -- ECG compression with ANNs +

+Tilton, James C. +

+Tomczyk, Marek +

+Turpin, Andrew -- Prefix Codes +

+ +

V

+Vetterli, Martin -- wavelets, subband coding, video compression, computational complexity +

+Vitter, Jeff +

+Voukelatos, Stathis +

+de Vries, Nico -- AIP-NL, UltraCompressor II development +

+ +

W

+ +Wareham, Paul -- Region-oriented video coding +

+Wegener, Al -- DSP, lossless audio compression and AC-2 +

+Wei, Dong -- Wavelet compression +

+Williams, Ross +

+Witten, Ian -- PPM, mg, arithmetic coding +

+Wolff, Gerry +

+Woo, Woon-Tack -- stereo image and video compression (12th Feb 1996) +

+Wu, Xiaolin -- CALIC +

+ + +

Z

+Zobel, Justin -- index compression, database compression +

+ +
+
+ + + + +

Conferences

+Data Compression Conference (DCC), Snowbird, Utah, USA.
+

+ + + +

Resources

+
+Where to get answers... +
+
International Telecommunication Union (ITU) -- standards documents (CCITT) +
+
comp.compression -- Frequently Asked Questions -- Come here 1st! +
+JPEG - Frequently Asked Questions +
+MPEG - Frequently Asked Questions +
+Standards - Frequenty Asked Questions +
+usenet newsgroup: comp.compression.research +
+
+Archive Compression Test -- Summary of all archivers +
+
+Fractal compression bibliography -- bibtex file +
+
+LZ/Complexity Seminars -- (in German) +
+
+Comparitive Compression Ratios -- Sofar...B&W, Gray Scale, Text Compression +
+
+VCN (Video, Compression, Networking) +Glossary +
+
+Digital Library -- search for compression +
+ + +
+
+Reports/Ph.D. Theses +
+Paul Howards Ph.D. thesis
+
The Design and Analysis of Efficient Lossless Data Compression Systems +
+ + + + +
+
+Source code +
+Arithmetic coding routines +
        (from Moffat, Neal and Witten, Proc. DCC, April 1995) +
+
+CACM Arithmetic coding package +
        (Witten, Neal and Cleary, CACM 30:520-541, June 1987) +
+
+JBIG Source code Includes a Q-coder +
+
Markus Kuhn's JBIG implementation +
+
+k-arithmetic coder +
+
+Lossless Data Compression toolkit 1.1 +
+
+Splay Trees Code -- by Douglas W. Jones +
+
Block compression code -- Excellent text compressor +
+ + + +
+
+Test Files +
+Test Images -- CCITT images (pbm), Lena etc. (Sun raster) +
+
+Stockholm test images -- You have to buy a CDROM, thats all I know! :-( +
         mail me at singlis@cs.waikato.ac.nz if you know anything about them. +
+
+Calgary Text Compression Corpus (Text Compression, Bell, Cleary and Witten, 1990) +
+ + +
+ + + + +

Research Projects, Standards & Companies

+ +

+

+Research/Free software Groups +
Compression and +Classification Group -- ISL,EE,Stanford (22th April 1996) + +
Voice email -- Lossless audio compression (18th Feb 1996) + + +
Electro-Optical Technologies, Inc. -- Consultant (12th April 1996) + +
quicktime.apple.com -- Quicktime site (11th Mar 1996) + +
IMAGE etc. -- Commercial image compression software (Fractals/Wavelets) (29th Feb 1996) + +
NCAR CCM Compression and Visualisation -- (18th Feb 1996) +
+
SPIHT -- Wavelet Natural Image Compressor (12th Feb 1996) +
+
Real-Time Lossless Compression Systems -- Loughborough University +
+
Web site for Multirate Signal Processing -- University of Wisconsin, Madison +
+
Info-ZIP -- free, +portable Zip and UnZip utilities +
+
CEDIS -- NASA, Maryland, Image/data compression +
+
CIC-3 Image Compression -- FBI Fingerprints +
+
Signal Compression Lab at UCSB +
+
University of +Washington compression lab -- VQ, Wavelets, Shlomo +
+ + + +

+

+Snippets +
Signal Processing +and the International Information Infrastructure -- Web sites (22th April 1996) +
Increasing Web bandwith -- comparing GIF, JPEG, Fractal compression +
+
Fractal Links on Yahoo +
+
Digital Speech Compression GSM 06.10 RPE-LTP -- DDJ +
+
CREW -- Continuous tone loss(y/less) wavelet compression +
+
CALIC -- Context-based adaptive lossless image compressor +
+
Berkeley MPEG -- MPEG tools +
+
MPEG Pointers and Resources +
+ + + + + + +

+

+Wavelets +
+ + EPIC (Efficient Pyramid Image Coder) -- by Eero Simoncelli +
+
+Tucker, Michael -- FASTWAVE, audio/image compression +
+
+HARC -- Lossy Wavelet Compression technology +
+
+UC Berkeley Wavelet Group +
+
+Khoros Wavetlet and Compression Toolbox +
+
+The Wavelet Digest +
+
+Rice DSP Publications Archive -- Wavelets, Time Frequency/Scale +
+ + +

+

+Fractals +
+Fractal Image Compression -- Software, Pointers, Conferences +
+
+Fractal Design Corporation +
+
+New Fractal Image Compression program +
+ + +

+

+Companies +
IBM Hardware -- Compression chips (11th Mar 1996) + +
Summus Wavelet Technology -- Wavelet image and video compressors (11th Mar 1996) +
Fractal Image Compression -- Mitsubishi (18th Feb 1996) + +
Terran Interactive -- Video compression for the Mac (1st Feb 1996) +
+ +
DV Mpeg -- Windows drivers (18th Feb 1996) +
+ +
Crawford Compression Services -- MPEG post-production (18th Feb 1996) +
+ +
Intelligent Compression Technologies (18th Feb 1996) +
+ +
Pegasus Imaging -- Compression software/dev. kits (12th Feb 1996) +
+
Aladdin Systems -- StuffIt compression products +
+
Stac Electronics +
+
DCP Research -- Hardware solutions +
+
Aware Inc. -- Specialised compression company +
+
IVS - INRIA Videoconferencing System +
+
Telvox Teleinformatica -- Multiplatform Data Compressor +
+
Compression Technologies, +Inc -- Canada +
+
Optivision -- MPEG +
+
PKWARE -- Makers of PKZIP +
+
Multimedia Imaging Services +
+ + +

+

+Audio compression +
Fraunhofer Institut für Integrierte Schaltungen +
+
Shorten +
+
digital speech compression +
+
Audio compression references +
+
SpeakFreely - compression +
+
SpeakFreely - Contents +
diff --git a/snappy/snappy-1.0.5/testdata/fields.c b/snappy/snappy-1.0.5/testdata/fields.c new file mode 100644 index 00000000..63cdc030 --- /dev/null +++ b/snappy/snappy-1.0.5/testdata/fields.c @@ -0,0 +1,431 @@ +#ifndef lint +static char Rcs_Id[] = + "$Id: fields.c,v 1.7 1994/01/06 05:26:37 geoff Exp $"; +#endif + +/* + * $Log: fields.c,v $ + * Revision 1.7 1994/01/06 05:26:37 geoff + * Get rid of all references to System V string routines, for portability + * (sigh). + * + * Revision 1.6 1994/01/05 20:13:43 geoff + * Add the maxf parameter + * + * Revision 1.5 1994/01/04 02:40:21 geoff + * Make the increments settable (field_line_inc and field_field_inc). + * Add support for the FLD_NOSHRINK flag. + * + * Revision 1.4 1993/09/27 17:48:02 geoff + * Fix some lint complaints and some parenthesization errors. + * + * Revision 1.3 1993/09/09 01:11:11 geoff + * Add a return value to fieldwrite. Add support for backquotes and for + * unstripped backslashes. + * + * Revision 1.2 1993/08/26 00:02:50 geoff + * Fix a stupid null-pointer bug + * + * Revision 1.1 1993/08/25 21:32:05 geoff + * Initial revision + * + */ + +#include +#include "config.h" +#include "fields.h" + +field_t * fieldread P ((FILE * file, char * delims, + int flags, int maxf)); + /* Read a line with fields from a file */ +field_t * fieldmake P ((char * line, int allocated, char * delims, + int flags, int maxf)); + /* Make a field structure from a line */ +static field_t * fieldparse P ((field_t * fieldp, char * line, char * delims, + int flags, int maxf)); + /* Parse the fields in a line */ +static int fieldbackch P ((char * str, char ** out, int strip)); + /* Process backslash sequences */ +int fieldwrite P ((FILE * file, field_t * fieldp, int delim)); + /* Write a line with fields to a file */ +void fieldfree P ((field_t * fieldp)); + /* Free a field returned by fieldread */ + +unsigned int field_field_inc = 20; /* Increment to increase # fields by */ +unsigned int field_line_inc = 512; /* Incr to increase line length by */ + +#ifndef USG +#define strchr index +#endif /* USG */ + +extern void free (); +extern char * malloc (); +extern char * realloc (); +extern char * strchr (); +extern int strlen (); + +/* + * Read one line of the given file into a buffer, break it up into + * fields, and return them to the caller. The field_t structure + * returned must eventually be freed with fieldfree. + */ +field_t * fieldread (file, delims, flags, maxf) + FILE * file; /* File to read lines from */ + char * delims; /* Characters to use for field delimiters */ + int flags; /* Option flags; see fields.h */ + int maxf; /* Maximum number of fields to parse */ + { + register char * linebuf; /* Buffer to hold the line read in */ + int linemax; /* Maximum line buffer size */ + int linesize; /* Current line buffer size */ + + linebuf = (char *) malloc (field_line_inc); + if (linebuf == NULL) + return NULL; + linemax = field_line_inc; + linesize = 0; + /* + * Read in the line. + */ + while (fgets (&linebuf[linesize], linemax - linesize, file) + != NULL) + { + linesize += strlen (&linebuf[linesize]); + if (linebuf[linesize - 1] == '\n') + break; + else + { + linemax += field_line_inc; + linebuf = (char *) realloc (linebuf, linemax); + if (linebuf == NULL) + return NULL; + } + } + if (linesize == 0) + { + free (linebuf); + return NULL; + } + return fieldmake (linebuf, 1, delims, flags, maxf); + } + +field_t * fieldmake (line, allocated, delims, flags, maxf) + char * line; /* Line to make into a field structure */ + int allocated; /* NZ if line allocated with malloc */ + char * delims; /* Characters to use for field delimiters */ + int flags; /* Option flags; see fields.h */ + int maxf; /* Maximum number of fields to parse */ + { + register field_t * fieldp; /* Structure describing the fields */ + int linesize; /* Current line buffer size */ + + fieldp = (field_t *) malloc (sizeof (field_t)); + if (fieldp == NULL) + return NULL; + fieldp->nfields = 0; + fieldp->linebuf = allocated ? line : NULL; + fieldp->fields = NULL; + fieldp->hadnl = 0; + linesize = strlen (line); + if (line[linesize - 1] == '\n') + { + line[--linesize] = '\0'; + fieldp->hadnl = 1; + } + /* + * Shrink the line buffer if necessary. + */ + if (allocated && (flags & FLD_NOSHRINK) == 0) + { + line = fieldp->linebuf = + (char *) realloc (fieldp->linebuf, linesize + 1); + if (fieldp->linebuf == NULL) + { + fieldfree (fieldp); + return NULL; + } + } + return fieldparse (fieldp, line, delims, flags, maxf); + } + +static field_t * fieldparse (fieldp, line, delims, flags, maxf) + register field_t * fieldp; /* Field structure to parse into */ + register char * line; /* Line to be parsed */ + char * delims; /* Characters to use for field delimiters */ + int flags; /* Option flags; see fields.h */ + int maxf; /* Maximum number of fields to parse */ + { + int fieldmax; /* Max size of fields array */ + char * lineout; /* Where to store xlated char in line */ + char quote; /* Quote character in use */ + + fieldp->nfields = 0; + fieldmax = + (maxf != 0 && maxf < field_field_inc) ? maxf + 2 : field_field_inc; + fieldp->fields = (char **) malloc (fieldmax * sizeof (char *)); + if (fieldp->fields == NULL) + { + fieldfree (fieldp); + return NULL; + } + if ((flags + & (FLD_SHQUOTES | FLD_SNGLQUOTES | FLD_BACKQUOTES | FLD_DBLQUOTES)) + == FLD_SHQUOTES) + flags |= FLD_SNGLQUOTES | FLD_BACKQUOTES | FLD_DBLQUOTES; + while (1) + { + if (flags & FLD_RUNS) + { + while (*line != '\0' && strchr (delims, *line) != NULL) + line++; /* Skip runs of delimiters */ + if (*line == '\0') + break; + } + fieldp->fields[fieldp->nfields] = lineout = line; + /* + * Skip to the next delimiter. At the end of skipping, "line" will + * point to either a delimiter or a null byte. + */ + if (flags + & (FLD_SHQUOTES | FLD_SNGLQUOTES | FLD_BACKQUOTES + | FLD_DBLQUOTES | FLD_BACKSLASH)) + { + while (*line != '\0') + { + if (strchr (delims, *line) != NULL) + break; + else if (((flags & FLD_SNGLQUOTES) && *line == '\'') + || ((flags & FLD_BACKQUOTES) && *line == '`') + || ((flags & FLD_DBLQUOTES) && *line == '"')) + { + if ((flags & FLD_SHQUOTES) == 0 + && line != fieldp->fields[fieldp->nfields]) + quote = '\0'; + else + quote = *line; + } + else + quote = '\0'; + if (quote == '\0') + { + if (*line == '\\' && (flags & FLD_BACKSLASH)) + { + line++; + if (*line == '\0') + break; + line += fieldbackch (line, &lineout, + flags & FLD_STRIPQUOTES); + } + else + *lineout++ = *line++; + } + else + { + /* Process quoted string */ + if ((flags & FLD_STRIPQUOTES) == 0) + *lineout++ = quote; + ++line; + while (*line != '\0') + { + if (*line == quote) + { + if ((flags & FLD_STRIPQUOTES) == 0) + *lineout++ = quote; + line++; /* Go on past quote */ + if ((flags & FLD_SHQUOTES) == 0) + { + while (*line != '\0' + && strchr (delims, *line) == NULL) + line++; /* Skip to delimiter */ + } + break; + } + else if (*line == '\\') + { + if (flags & FLD_BACKSLASH) + { + line++; + if (*line == '\0') + break; + else + line += fieldbackch (line, &lineout, + flags & FLD_STRIPQUOTES); + } + else + { + *lineout++ = '\\'; + if (*++line == '\0') + break; + *lineout++ = *line; + } + } + else + *lineout++ = *line++; + } + } + } + } + else + { + while (*line != '\0' && strchr (delims, *line) == NULL) + line++; /* Skip to delimiter */ + lineout = line; + } + fieldp->nfields++; + if (*line++ == '\0') + break; + if (maxf != 0 && fieldp->nfields > maxf) + break; + *lineout = '\0'; + if (fieldp->nfields >= fieldmax) + { + fieldmax += field_field_inc; + fieldp->fields = + (char **) realloc (fieldp->fields, fieldmax * sizeof (char *)); + if (fieldp->fields == NULL) + { + fieldfree (fieldp); + return NULL; + } + } + } + /* + * Shrink the field pointers and return the field structure. + */ + if ((flags & FLD_NOSHRINK) == 0 && fieldp->nfields >= fieldmax) + { + fieldp->fields = (char **) realloc (fieldp->fields, + (fieldp->nfields + 1) * sizeof (char *)); + if (fieldp->fields == NULL) + { + fieldfree (fieldp); + return NULL; + } + } + fieldp->fields[fieldp->nfields] = NULL; + return fieldp; + } + +static int fieldbackch (str, out, strip) + register char * str; /* First char of backslash sequence */ + register char ** out; /* Where to store result */ + int strip; /* NZ to convert the sequence */ + { + register int ch; /* Character being developed */ + char * origstr; /* Original value of str */ + + if (!strip) + { + *(*out)++ = '\\'; + if (*str != 'x' && *str != 'X' && (*str < '0' || *str > '7')) + { + *(*out)++ = *str; + return *str != '\0'; + } + } + switch (*str) + { + case '\0': + *(*out)++ = '\0'; + return 0; + case 'a': + *(*out)++ = '\007'; + return 1; + case 'b': + *(*out)++ = '\b'; + return 1; + case 'f': + *(*out)++ = '\f'; + return 1; + case 'n': + *(*out)++ = '\n'; + return 1; + case 'r': + *(*out)++ = '\r'; + return 1; + case 'v': + *(*out)++ = '\v'; + return 1; + case 'X': + case 'x': + /* Hexadecimal sequence */ + origstr = str++; + ch = 0; + if (*str >= '0' && *str <= '9') + ch = *str++ - '0'; + else if (*str >= 'a' && *str <= 'f') + ch = *str++ - 'a' + 0xa; + else if (*str >= 'A' && *str <= 'F') + ch = *str++ - 'A' + 0xa; + if (*str >= '0' && *str <= '9') + ch = (ch << 4) | (*str++ - '0'); + else if (*str >= 'a' && *str <= 'f') + ch = (ch << 4) | (*str++ - 'a' + 0xa); + else if (*str >= 'A' && *str <= 'F') + ch = (ch << 4) | (*str++ - 'A' + 0xa); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + /* Octal sequence */ + origstr = str; + ch = *str++ - '0'; + if (*str >= '0' && *str <= '7') + ch = (ch << 3) | (*str++ - '0'); + if (*str >= '0' && *str <= '7') + ch = (ch << 3) | (*str++ - '0'); + break; + default: + *(*out)++ = *str; + return 1; + } + if (strip) + { + *(*out)++ = ch; + return str - origstr; + } + else + { + for (ch = 0; origstr < str; ch++) + *(*out)++ = *origstr++; + return ch; + } + } + +int fieldwrite (file, fieldp, delim) + FILE * file; /* File to write to */ + register field_t * fieldp; /* Field structure to write */ + int delim; /* Delimiter to place between fields */ + { + int error; /* NZ if an error occurs */ + register int fieldno; /* Number of field being written */ + + error = 0; + for (fieldno = 0; fieldno < fieldp->nfields; fieldno++) + { + if (fieldno != 0) + error |= putc (delim, file) == EOF; + error |= fputs (fieldp->fields[fieldno], file) == EOF; + } + if (fieldp->hadnl) + error |= putc ('\n', file) == EOF; + return error; + } + +void fieldfree (fieldp) + register field_t * fieldp; /* Field structure to free */ + { + + if (fieldp == NULL) + return; + if (fieldp->linebuf != NULL) + free ((char *) fieldp->linebuf); + if (fieldp->fields != NULL) + free ((char *) fieldp->fields); + free ((char *) fieldp); + } diff --git a/snappy/snappy-1.0.5/testdata/geo.protodata b/snappy/snappy-1.0.5/testdata/geo.protodata new file mode 100644 index 00000000..c4e3e0d8 Binary files /dev/null and b/snappy/snappy-1.0.5/testdata/geo.protodata differ diff --git a/snappy/snappy-1.0.5/testdata/grammar.lsp b/snappy/snappy-1.0.5/testdata/grammar.lsp new file mode 100644 index 00000000..c60a9938 --- /dev/null +++ b/snappy/snappy-1.0.5/testdata/grammar.lsp @@ -0,0 +1,94 @@ +;;; -*- Mode: Lisp; Syntax: Common-Lisp; -*- + +(define-language + :grammar + '(((S $any) -> (S1 $any)) + ((S (Compound $s1 $s2)) -> (S1 $s1) (Conjunction) (S1 $s2)) + + ((S1 (Statement $v)) -> (NP $subj) (VP $subj $tense $v)) + ((S1 (Acknowledge $a)) -> (Acknowledge $a)) + ((S1 (Command $v)) -> (VP Self present $v)) + ((S1 (Question $v)) -> (Aux $tense) (NP $subj) (VP $subj $tense $v)) + ((S1 (Question $v)) -> (Be $tense) (NP $subj) (Be-Arg $subj $tense $v)) + + ((Be-Arg $subj $tense (Occur $tense (loc $subj $loc))) -> + (Loc-Adjunct $tense (loc $subj $loc))) + + ((VP $subj $tense (Occur $tense $v)) -> (VP1 $subj $tense $v)) + ((VP $subj $tense (Occur $tense $v)) -> (Aux $tense)(VP1 $subj present $v)) + + ((VP1 $subj $tense $v) -> (VP2 $subj $tense $v) (Adjunct? $v)) + + ((VP2 $subj $tense ($rel $subj $loc)) -> + (Verb/in $rel $tense)) + ((VP2 $subj $tense ($rel $subj $loc $obj)) -> + (Verb/tr $rel $tense) (NP $obj)) + ((VP2 $subj $tense ($rel $subj $loc $obj $obj2)) -> + (Verb/di $rel $tense) (NP $obj) (NP $obj2)) + ((VP2 $subj $tense (loc $subj $loc)) -> + (Be $tense) (Loc-Adjunct $tense (loc $subj $loc))) + + ((NP $n) -> (Pronoun $n)) + ((NP $n) -> (Article) (Noun $n)) + ((NP $n) -> (Noun $n)) + ((NP ($x $y)) -> (Number $x) (Number $y)) + + ((PP ($prep $n)) -> (Prep $prep) (NP $n)) + ((Adjunct? $v) ->) + ((Adjunct? $v) -> (Loc-Adjunct $tense $v)) + #+Allegro ((Loc-Adjunct $tense ($rel $subj $loc @rest)) -> (PP $loc)) + #+Allegro ((Loc-Adjunct $tense ($rel $subj $loc @rest)) -> (Adjunct $loc)) + #+Lucid ((Loc-Adjunct $tense ($rel $subj $loc . $rest)) -> (PP $loc)) + #+Lucid ((Loc-Adjunct $tense ($rel $subj $loc . $rest)) -> (Adjunct $loc)) + + ) + :lexicon + '( + ((Acknowledge $a) -> (yes true) (no false) (maybe unknown) (huh unparsed)) + ((Adjunct $loc) -> here there (nearby near) near left right up down) + ((Article) -> a an the) + ((Aux $tense) -> (will future) (did past) (do $finite)) + ((Be $tense) -> (am present) (are present) (is present) (be $finite) + (was past) (were past)) + ((Conjunction) -> and --) + ((Noun $n) -> gold Wumpus pit breeze stench glitter nothing) + ((Number $n) -> 0 1 2 3 4 5 6 7 8 9) + ((Prep $prep) -> in at to near) + ((Pronoun $n) -> (you self) (me master) (I master)) + + ((Verb/in $rel $tense) -> (go move $finite) (went move past) + (move move $finite) (move move past) (shoot shoot $finite)) + ((Verb/tr $rel $tense) -> (move carry $finite) (moved carry past) + (carry carry $finite) (carry carried past) + (grab grab $finite) (grab grabbed past) (get grab $finite) + (got grab past) (release release $finite) (release release past) + (drop release $finite) (dropped release past) (shoot shoot-at $finite) + (shot shoot-at past) (kill shoot-at $finite) (killed shoot-at past) + (smell perceive $finite) (feel perceive $finite) (felt perceive past)) + ((Verb/di $rel $tense) -> (bring bring $finite) (brought bring past) + (get bring $finite) (got bring past)) + )) + +(defparameter *sentences* + '((I will shoot the wumpus at 4 4) + (yes) + (You went right -- I will go left) + (carry the gold) + (yes and no) + (did you bring me the gold) + (a breeze is here -- I am near 5 3) + (a stench is in 3 5) + (a pit is nearby) + (is the wumpus near) + (Did you go to 3 8) + (Yes -- Nothing is there) + (Shoot -- Shoot left) + (Kill the wumpus -- shoot up))) + +(defun ss (&optional (sentences *sentences*)) + "Run some test sentences, and count how many were not parsed." + (count-if-not + #'(lambda (s) + (format t "~2&>>> ~(~{~a ~}~)~%" s) + (write (second (parse s)) :pretty t)) + *sentences*)) diff --git a/snappy/snappy-1.0.5/testdata/house.jpg b/snappy/snappy-1.0.5/testdata/house.jpg new file mode 100644 index 00000000..6b3aae8c Binary files /dev/null and b/snappy/snappy-1.0.5/testdata/house.jpg differ diff --git a/snappy/snappy-1.0.5/testdata/html b/snappy/snappy-1.0.5/testdata/html new file mode 100644 index 00000000..ef768ccd --- /dev/null +++ b/snappy/snappy-1.0.5/testdata/html @@ -0,0 +1 @@ + content: @ 1099872000000000: 'HTTP/1.1 200 OK\r\nX-Google-Crawl-Date: Mon, 08 Nov 2004 17:22:09 GMT\r\nContent-Type: text/html\r\nConnection: close\r\nX-Powered-By: PHP/4.3.8\r\nServer: Apache/1.3.31 (Unix) mod_gzip/1.3.19.1a PHP/4.3.8\r\nDate: Mon, 08 Nov 2004 17:19:07 GMT\r\n\r\n \r\n\r\n\r\n\r\n\r\n\nMicro Achat : Ordinateurs, PDA - Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

Derni\350re mise \340 jour de cette page : lundi 8 novembre 2004  |  16:45
\r\n \r\n\r\n\r\n\r\n\t\r\n\r\n\t\t\r\n\r\n\t\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n\t\t\r\n\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t

\r\n\r\n\r\n\r\n


\r\n\r\n\r\n\r\n
\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\"\"
Imagerie 
\"\"\n\t\t\t\t\t\t\t\tLG L1720B\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
332.89 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tAcer Veriton 7600G\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
705 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tShuttle SN95G5\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
375 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tAsus A7N8X-E Deluxe\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
91.99 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tThermalright SP-94\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
49 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\"\"
1 \">\"PC Look
2 \">\"Atelier Informatique
3 \">\"Zanax Multim\351dia
4 \">\"MISTEROOPS
5 \">\"168 Golden Avenue
6 \">\"microchoix
7 \">\"e-Soph
8 \">\"PC Price Club
9 \">\"PC 77
10 \">\"Web In Informatique
\n\t\t\t\t
\n\t\t\t\t
\r\n \r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t
\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\r\n\r\n\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n

\r\n\t\t\t

\r\n\t\t\t

\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\r\n \r\n \r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

CD et DVD bient\364t insensibles aux rayures
OpenOffice gagne son service
La messagerie en cinq minutes selon Ipswitch
> toutes les news


\r\n\t\t
\r\n \r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Recevez chaque jour l\'actualit\351 des produits et des promos
\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n\r\n\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Entreprise
\r\n\t\t\t\tQuand le billet papier s\'envole vers la d\351mat\351rialisation


Trucs et astuces
\r\n\t\t\t\tD\351pannez Windows XP


Conso
\r\n\t\t\t\tVos photos sur papier imprimante ou labo ?


Produits & Tests
\r\n\t\t\t\t5 programmes d\222encodage vid\351o gratuits


\r\n\t\t
\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n
\r\n
\r\n\t\t\r\n\t\t

\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\r\n\r\n\r\n\t\t\t\r\n\r\n\r\n\r\n\t\t\t\t\r\n
\r\n
\r\nPortable
\r\nUn nouvel ultra portable r\351alis\351 par Nec
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nLe Versa S940 a un format r\351duit, mais ses performances sont \340 la hauteur.
\r\n\340 partir de 1663 \200\r\n
\r\n
\r\nPortable
\r\nAsus pr\351sente trois petits nouveaux dans la gamme A3N
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nCes trois portables Centrino int\350grent, entre autres, une webcam et un contr\364leur Wi-Fi.
\r\n\340 partir de 1346 \200\r\n
\r\n
\r\n\t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t
\r\n\t\r\n\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
BON PLAN
\r\n
\r\n
\r\nLes derni\350res technologies INTEL dans un nouveau design pour ce shuttle haut de gamme, pour un prix abordable.
\r\n

\r\n
\r\n\340 partir de
\r\n
415 \200
\r\n
\r\n
\r\n
publicit\351
\r\n
\r\n\t\r\n\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

\r\n\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\tDesktops
\r\n\t\t\t\tPortables
\r\n\t\t\t\tMini-PC
\r\n\t\t\t\tPda / Tablets-PC
\r\n\t\t\t\tApple
\r\n\t\t\t\tGPS
\r\n\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n

\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\tPortable Toshiba consacre deux gammes de machines au multim\351dia
\r\n\tEquipement haut de gamme et Windows Media Center sont au menu de ces portables \340 vocation multim\351dia.

\r\n\tOrdinateur Arriv\351e d\'un Power Mac G5 d\'entr\351e de gamme
\r\n\tLa firme \340 la pomme propose une station de travail \351volutive et relativement abordable.

\r\n\tPC Alienware propose deux machines au look \351trange
\r\n\tAurora et Area 51 sont deux gammes d\'ordinateurs enti\350rement configurables.

\r\n\tPortable Trois nouveaux iBook G4 chez Apple
\r\n\tChez Apple, les portables gagnent en vitesse et communiquent sans fil en standard.

\r\n\t\t\t\t> toutes les news\r\n\t\t\t
\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n

\r\n\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tAsus A3N15-C Pro
\r\n Voici un portable autonome et puissant gr\342ce \340 la technologie Intel Centrino.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1170 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tSoltek EQ3702A Miroir
\r\n Ce mini PC est une solution int\351ressante pour les utilisateurs poss\351dant d\351j\340 un \351cran.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t559 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tIBM ThinkPad R51
\r\n Voici un portable complet et pourtant relativement l\351ger.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1299 \200
\r\n
\r\n\t\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t> toutes les promos\r\n\t\t
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t
\r\n\t\t\t\r\n\t\t\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n\t\r\n\r\n
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\n
\r\n
\r\nLes graveurs de DVD
\r\nQuel graveur choisir ? Quel type de format ? Quelle vitesse ? Double couche ou simple couche ? Voici tout ce qu\'il faut savoir pour faire le bon choix.
\r\n\t\t\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n \t\r\n
\r\n\t\t
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
\r\n\t\t\t\t

\r\n\t\t\t\tChoisir une r\351gion
\r\n\r\n
Un d\351partement
\r\n\r\n
\r\n
Un arrondissement
\r\n\r\n
\r\n
\r\n\t\t\t\tRecherche directe
\r\n\t\t\t\trechercher une ville
et/ou une boutique
\r\n\t\t\t\t

\r\n\t\t\t\t \r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
Recherche avanc\351e
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
Bureautique
\r\n\t\t\t\tTraducteur, organiseur...

\r\n\t\t\t\t

Multim\351dia
\r\n\t\t\t\tPhoto, audio, vid\351o...

\r\n\t\t\t\t

Utilitaires
\r\n\t\t\t\tAntivirus, pilotes, gravure...

\r\n\t\t\t\t

Personnaliser son PC
\r\n\t\t\t\tEcrans de veille, th\350mes...

\r\n\t\t\t\t

D\351veloppement
\r\n\t\t\t\tCr\351ation de logiciels, BDD...

\r\n\t\t\t\t

Jeux
\r\n\t\t\t\tAction, simulation...

\r\n\t\t\t\t

Internet
\r\n\t\t\t\tUtilitaires, email, FTP...

\r\n\t\t\t\t

Loisirs
\r\n\t\t\t\tHumour, culture...

\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\t\t

\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\nMicro Achat : Ordinateurs, PDA - Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

Derni\350re mise \340 jour de cette page : lundi 8 novembre 2004  |  16:45
\r\n \r\n\r\n\r\n\r\n\t\r\n\r\n\t\t\r\n\r\n\t\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n\t\t\r\n\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t

\r\n\r\n\r\n\r\n


\r\n\r\n\r\n\r\n
\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\"\"
Imagerie 
\"\"\n\t\t\t\t\t\t\t\tLG L1720B\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
332.89 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tAcer Veriton 7600G\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
705 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tShuttle SN95G5\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
375 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tAsus A7N8X-E Deluxe\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
91.99 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tThermalright SP-94\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
49 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\"\"
1 \">\"PC Look
2 \">\"Atelier Informatique
3 \">\"Zanax Multim\351dia
4 \">\"MISTEROOPS
5 \">\"168 Golden Avenue
6 \">\"microchoix
7 \">\"e-Soph
8 \">\"PC Price Club
9 \">\"PC 77
10 \">\"Web In Informatique
\n\t\t\t\t
\n\t\t\t\t
\r\n \r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t
\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\r\n\r\n\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n

\r\n\t\t\t

\r\n\t\t\t

\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\r\n \r\n \r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

CD et DVD bient\364t insensibles aux rayures
OpenOffice gagne son service
La messagerie en cinq minutes selon Ipswitch
> toutes les news


\r\n\t\t
\r\n \r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Recevez chaque jour l\'actualit\351 des produits et des promos
\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n\r\n\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Entreprise
\r\n\t\t\t\tQuand le billet papier s\'envole vers la d\351mat\351rialisation


Trucs et astuces
\r\n\t\t\t\tD\351pannez Windows XP


Conso
\r\n\t\t\t\tVos photos sur papier imprimante ou labo ?


Produits & Tests
\r\n\t\t\t\t5 programmes d\222encodage vid\351o gratuits


\r\n\t\t
\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n
\r\n
\r\n\t\t\r\n\t\t

\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\r\n\r\n\r\n\t\t\t\r\n\r\n\r\n\r\n\t\t\t\t\r\n
\r\n
\r\nPortable
\r\nUn nouvel ultra portable r\351alis\351 par Nec
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nLe Versa S940 a un format r\351duit, mais ses performances sont \340 la hauteur.
\r\n\340 partir de 1663 \200\r\n
\r\n
\r\nPortable
\r\nAsus pr\351sente trois petits nouveaux dans la gamme A3N
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nCes trois portables Centrino int\350grent, entre autres, une webcam et un contr\364leur Wi-Fi.
\r\n\340 partir de 1346 \200\r\n
\r\n
\r\n\t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t
\r\n\t\r\n\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
BON PLAN
\r\n
\r\n
\r\nLes derni\350res technologies INTEL dans un nouveau design pour ce shuttle haut de gamme, pour un prix abordable.
\r\n

\r\n
\r\n\340 partir de
\r\n
415 \200
\r\n
\r\n
\r\n
publicit\351
\r\n
\r\n\t\r\n\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

\r\n\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\tDesktops
\r\n\t\t\t\tPortables
\r\n\t\t\t\tMini-PC
\r\n\t\t\t\tPda / Tablets-PC
\r\n\t\t\t\tApple
\r\n\t\t\t\tGPS
\r\n\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n

\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\tPortable Toshiba consacre deux gammes de machines au multim\351dia
\r\n\tEquipement haut de gamme et Windows Media Center sont au menu de ces portables \340 vocation multim\351dia.

\r\n\tOrdinateur Arriv\351e d\'un Power Mac G5 d\'entr\351e de gamme
\r\n\tLa firme \340 la pomme propose une station de travail \351volutive et relativement abordable.

\r\n\tPC Alienware propose deux machines au look \351trange
\r\n\tAurora et Area 51 sont deux gammes d\'ordinateurs enti\350rement configurables.

\r\n\tPortable Trois nouveaux iBook G4 chez Apple
\r\n\tChez Apple, les portables gagnent en vitesse et communiquent sans fil en standard.

\r\n\t\t\t\t> toutes les news\r\n\t\t\t
\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n

\r\n\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tAsus A3N15-C Pro
\r\n Voici un portable autonome et puissant gr\342ce \340 la technologie Intel Centrino.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1170 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tSoltek EQ3702A Miroir
\r\n Ce mini PC est une solution int\351ressante pour les utilisateurs poss\351dant d\351j\340 un \351cran.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t559 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tIBM ThinkPad R51
\r\n Voici un portable complet et pourtant relativement l\351ger.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1299 \200
\r\n
\r\n\t\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t> toutes les promos\r\n\t\t
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t
\r\n\t\t\t\r\n\t\t\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n\t\r\n\r\n
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\n
\r\n
\r\nLes graveurs de DVD
\r\nQuel graveur choisir ? Quel type de format ? Quelle vitesse ? Double couche ou simple couche ? Voici tout ce qu\'il faut savoir pour faire le bon choix.
\r\n\t\t\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n \t\r\n
\r\n\t\t
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
\r\n\t\t\t\t

\r\n\t\t\t\tChoisir une r\351gion
\r\n\r\n
Un d\351partement
\r\n\r\n
\r\n
Un arrondissement
\r\n\r\n
\r\n
\r\n\t\t\t\tRecherche directe
\r\n\t\t\t\trechercher une ville
et/ou une boutique
\r\n\t\t\t\t

\r\n\t\t\t\t \r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
Recherche avanc\351e
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
Bureautique
\r\n\t\t\t\tTraducteur, organiseur...

\r\n\t\t\t\t

Multim\351dia
\r\n\t\t\t\tPhoto, audio, vid\351o...

\r\n\t\t\t\t

Utilitaires
\r\n\t\t\t\tAntivirus, pilotes, gravure...

\r\n\t\t\t\t

Personnaliser son PC
\r\n\t\t\t\tEcrans de veille, th\350mes...

\r\n\t\t\t\t

D\351veloppement
\r\n\t\t\t\tCr\351ation de logiciels, BDD...

\r\n\t\t\t\t

Jeux
\r\n\t\t\t\tAction, simulation...

\r\n\t\t\t\t

Internet
\r\n\t\t\t\tUtilitaires, email, FTP...

\r\n\t\t\t\t

Loisirs
\r\n\t\t\t\tHumour, culture...

\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\t\t

\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\nMicro Achat : Ordinateurs, PDA - Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

Derni\350re mise \340 jour de cette page : lundi 8 novembre 2004  |  16:45
\r\n \r\n\r\n\r\n\r\n\t\r\n\r\n\t\t\r\n\r\n\t\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n\t\t\r\n\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t

\r\n\r\n\r\n\r\n


\r\n\r\n\r\n\r\n
\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\"\"
Imagerie 
\"\"\n\t\t\t\t\t\t\t\tLG L1720B\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
332.89 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tAcer Veriton 7600G\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
705 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tShuttle SN95G5\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
375 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tAsus A7N8X-E Deluxe\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
91.99 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tThermalright SP-94\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
49 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\"\"
1 \">\"PC Look
2 \">\"Atelier Informatique
3 \">\"Zanax Multim\351dia
4 \">\"MISTEROOPS
5 \">\"168 Golden Avenue
6 \">\"microchoix
7 \">\"e-Soph
8 \">\"PC Price Club
9 \">\"PC 77
10 \">\"Web In Informatique
\n\t\t\t\t
\n\t\t\t\t
\r\n \r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t
\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\r\n\r\n\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n

\r\n\t\t\t

\r\n\t\t\t

\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\r\n \r\n \r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

CD et DVD bient\364t insensibles aux rayures
OpenOffice gagne son service
La messagerie en cinq minutes selon Ipswitch
> toutes les news


\r\n\t\t
\r\n \r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Recevez chaque jour l\'actualit\351 des produits et des promos
\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n\r\n\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Entreprise
\r\n\t\t\t\tQuand le billet papier s\'envole vers la d\351mat\351rialisation


Trucs et astuces
\r\n\t\t\t\tD\351pannez Windows XP


Conso
\r\n\t\t\t\tVos photos sur papier imprimante ou labo ?


Produits & Tests
\r\n\t\t\t\t5 programmes d\222encodage vid\351o gratuits


\r\n\t\t
\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n
\r\n
\r\n\t\t\r\n\t\t

\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\r\n\r\n\r\n\t\t\t\r\n\r\n\r\n\r\n\t\t\t\t\r\n
\r\n
\r\nPortable
\r\nUn nouvel ultra portable r\351alis\351 par Nec
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nLe Versa S940 a un format r\351duit, mais ses performances sont \340 la hauteur.
\r\n\340 partir de 1663 \200\r\n
\r\n
\r\nPortable
\r\nAsus pr\351sente trois petits nouveaux dans la gamme A3N
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nCes trois portables Centrino int\350grent, entre autres, une webcam et un contr\364leur Wi-Fi.
\r\n\340 partir de 1346 \200\r\n
\r\n
\r\n\t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t
\r\n\t\r\n\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
BON PLAN
\r\n
\r\n
\r\nLes derni\350res technologies INTEL dans un nouveau design pour ce shuttle haut de gamme, pour un prix abordable.
\r\n

\r\n
\r\n\340 partir de
\r\n
415 \200
\r\n
\r\n
\r\n
publicit\351
\r\n
\r\n\t\r\n\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

\r\n\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\tDesktops
\r\n\t\t\t\tPortables
\r\n\t\t\t\tMini-PC
\r\n\t\t\t\tPda / Tablets-PC
\r\n\t\t\t\tApple
\r\n\t\t\t\tGPS
\r\n\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n

\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\tPortable Toshiba consacre deux gammes de machines au multim\351dia
\r\n\tEquipement haut de gamme et Windows Media Center sont au menu de ces portables \340 vocation multim\351dia.

\r\n\tOrdinateur Arriv\351e d\'un Power Mac G5 d\'entr\351e de gamme
\r\n\tLa firme \340 la pomme propose une station de travail \351volutive et relativement abordable.

\r\n\tPC Alienware propose deux machines au look \351trange
\r\n\tAurora et Area 51 sont deux gammes d\'ordinateurs enti\350rement configurables.

\r\n\tPortable Trois nouveaux iBook G4 chez Apple
\r\n\tChez Apple, les portables gagnent en vitesse et communiquent sans fil en standard.

\r\n\t\t\t\t> toutes les news\r\n\t\t\t
\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n

\r\n\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tAsus A3N15-C Pro
\r\n Voici un portable autonome et puissant gr\342ce \340 la technologie Intel Centrino.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1170 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tSoltek EQ3702A Miroir
\r\n Ce mini PC est une solution int\351ressante pour les utilisateurs poss\351dant d\351j\340 un \351cran.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t559 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tIBM ThinkPad R51
\r\n Voici un portable complet et pourtant relativement l\351ger.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1299 \200
\r\n
\r\n\t\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t> toutes les promos\r\n\t\t
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t
\r\n\t\t\t\r\n\t\t\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n\t\r\n\r\n
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\n
\r\n
\r\nLes graveurs de DVD
\r\nQuel graveur choisir ? Quel type de format ? Quelle vitesse ? Double couche ou simple couche ? Voici tout ce qu\'il faut savoir pour faire le bon choix.
\r\n\t\t\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n \t\r\n
\r\n\t\t
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
\r\n\t\t\t\t

\r\n\t\t\t\tChoisir une r\351gion
\r\n\r\n
Un d\351partement
\r\n\r\n
\r\n
Un arrondissement
\r\n\r\n
\r\n
\r\n\t\t\t\tRecherche directe
\r\n\t\t\t\trechercher une ville
et/ou une boutique
\r\n\t\t\t\t

\r\n\t\t\t\t \r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
Recherche avanc\351e
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
Bureautique
\r\n\t\t\t\tTraducteur, organiseur...

\r\n\t\t\t\t

Multim\351dia
\r\n\t\t\t\tPhoto, audio, vid\351o...

\r\n\t\t\t\t

Utilitaires
\r\n\t\t\t\tAntivirus, pilotes, gravure...

\r\n\t\t\t\t

Personnaliser son PC
\r\n\t\t\t\tEcrans de veille, th\350mes...

\r\n\t\t\t\t

D\351veloppement
\r\n\t\t\t\tCr\351ation de logiciels, BDD...

\r\n\t\t\t\t

Jeux
\r\n\t\t\t\tAction, simulation...

\r\n\t\t\t\t

Internet
\r\n\t\t\t\tUtilitaires, email, FTP...

\r\n\t\t\t\t

Loisirs
\r\n\t\t\t\tHumour, culture...

\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\t\t

\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\nMicro Achat : Ordinateurs, PDA - Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

Derni\350re mise \340 jour de cette page : lundi 8 novembre 2004  |  16:45
\r\n \r\n\r\n\r\n\r\n\t\r\n\r\n\t\t\r\n\r\n\t\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n\t\t\r\n\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t

\r\n\r\n\r\n\r\n


\r\n\r\n\r\n\r\n
\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\"\"
Imagerie 
\"\"\n\t\t\t\t\t\t\t\tLG L1720B\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
332.89 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tAcer Veriton 7600G\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
705 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tShuttle SN95G5\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
375 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tAsus A7N8X-E Deluxe\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
91.99 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tThermalright SP-94\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
49 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\"\"
1 \">\"PC Look
2 \">\"Atelier Informatique
3 \">\"Zanax Multim\351dia
4 \">\"MISTEROOPS
5 \">\"168 Golden Avenue
6 \">\"microchoix
7 \">\"e-Soph
8 \">\"PC Price Club
9 \">\"PC 77
10 \">\"Web In Informatique
\n\t\t\t\t
\n\t\t\t\t
\r\n \r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t
\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\r\n\r\n\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n

\r\n\t\t\t

\r\n\t\t\t

\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\r\n \r\n \r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

CD et DVD bient\364t insensibles aux rayures
OpenOffice gagne son service
La messagerie en cinq minutes selon Ipswitch
> toutes les news


\r\n\t\t
\r\n \r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Recevez chaque jour l\'actualit\351 des produits et des promos
\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n\r\n\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Entreprise
\r\n\t\t\t\tQuand le billet papier s\'envole vers la d\351mat\351rialisation


Trucs et astuces
\r\n\t\t\t\tD\351pannez Windows XP


Conso
\r\n\t\t\t\tVos photos sur papier imprimante ou labo ?


Produits & Tests
\r\n\t\t\t\t5 programmes d\222encodage vid\351o gratuits


\r\n\t\t
\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n
\r\n
\r\n\t\t\r\n\t\t

\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\r\n\r\n\r\n\t\t\t\r\n\r\n\r\n\r\n\t\t\t\t\r\n
\r\n
\r\nPortable
\r\nUn nouvel ultra portable r\351alis\351 par Nec
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nLe Versa S940 a un format r\351duit, mais ses performances sont \340 la hauteur.
\r\n\340 partir de 1663 \200\r\n
\r\n
\r\nPortable
\r\nAsus pr\351sente trois petits nouveaux dans la gamme A3N
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nCes trois portables Centrino int\350grent, entre autres, une webcam et un contr\364leur Wi-Fi.
\r\n\340 partir de 1346 \200\r\n
\r\n
\r\n\t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t
\r\n\t\r\n\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
BON PLAN
\r\n
\r\n
\r\nLes derni\350res technologies INTEL dans un nouveau design pour ce shuttle haut de gamme, pour un prix abordable.
\r\n

\r\n
\r\n\340 partir de
\r\n
415 \200
\r\n
\r\n
\r\n
publicit\351
\r\n
\r\n\t\r\n\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

\r\n\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\tDesktops
\r\n\t\t\t\tPortables
\r\n\t\t\t\tMini-PC
\r\n\t\t\t\tPda / Tablets-PC
\r\n\t\t\t\tApple
\r\n\t\t\t\tGPS
\r\n\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n

\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\tPortable Toshiba consacre deux gammes de machines au multim\351dia
\r\n\tEquipement haut de gamme et Windows Media Center sont au menu de ces portables \340 vocation multim\351dia.

\r\n\tOrdinateur Arriv\351e d\'un Power Mac G5 d\'entr\351e de gamme
\r\n\tLa firme \340 la pomme propose une station de travail \351volutive et relativement abordable.

\r\n\tPC Alienware propose deux machines au look \351trange
\r\n\tAurora et Area 51 sont deux gammes d\'ordinateurs enti\350rement configurables.

\r\n\tPortable Trois nouveaux iBook G4 chez Apple
\r\n\tChez Apple, les portables gagnent en vitesse et communiquent sans fil en standard.

\r\n\t\t\t\t> toutes les news\r\n\t\t\t
\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n

\r\n\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tAsus A3N15-C Pro
\r\n Voici un portable autonome et puissant gr\342ce \340 la technologie Intel Centrino.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1170 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tSoltek EQ3702A Miroir
\r\n Ce mini PC est une solution int\351ressante pour les utilisateurs poss\351dant d\351j\340 un \351cran.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t559 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tIBM ThinkPad R51
\r\n Voici un portable complet et pourtant relativement l\351ger.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1299 \200
\r\n
\r\n\t\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t> toutes les promos\r\n\t\t
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t
\r\n\t\t\t\r\n\t\t\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n\t\r\n\r\n
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\n
\r\n
\r\nLes graveurs de DVD
\r\nQuel graveur choisir ? Quel type de format ? Quelle vitesse ? Double couche ou simple couche ? Voici tout ce qu\'il faut savoir pour faire le bon choix.
\r\n\t\t\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n \t\r\n
\r\n\t\t
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
\r\n\t\t\t\t

\r\n\t\t\t\tChoisir une r\351gion
\r\n\r\n
Un d\351partement
\r\n\r\n
\r\n
Un arrondissement
\r\n\r\n
\r\n
\r\n\t\t\t\tRecherche directe
\r\n\t\t\t\trechercher une ville
et/ou une boutique
\r\n\t\t\t\t

\r\n\t\t\t\t \r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
Recherche avanc\351e
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
Bureautique
\r\n\t\t\t\tTraducteur, organiseur...

\r\n\t\t\t\t

Multim\351dia
\r\n\t\t\t\tPhoto, audio, vid\351o...

\r\n\t\t\t\t

Utilitaires
\r\n\t\t\t\tAntivirus, pilotes, gravure...

\r\n\t\t\t\t

Personnaliser son PC
\r\n\t\t\t\tEcrans de veille, th\350mes...

\r\n\t\t\t\t

D\351veloppement
\r\n\t\t\t\tCr\351ation de logiciels, BDD...

\r\n\t\t\t\t

Jeux
\r\n\t\t\t\tAction, simulation...

\r\n\t\t\t\t

Internet
\r\n\t\t\t\tUtilitaires, email, FTP...

\r\n\t\t\t\t

Loisirs
\r\n\t\t\t\tHumour, culture...

\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\t\t

\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\nMicro Achat : Ordinateurs, PDA - Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

Derni\350re mise \340 jour de cette page : lundi 8 novembre 2004  |  16:45
\r\n \r\n\r\n\r\n\r\n\t\r\n\r\n\t\t\r\n\r\n\t\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n\t\t\r\n\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t

\r\n\r\n\r\n\r\n


\r\n\r\n\r\n\r\n
\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\"\"
Imagerie 
\"\"\n\t\t\t\t\t\t\t\tLG L1720B\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
332.89 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tAcer Veriton 7600G\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
705 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tShuttle SN95G5\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
375 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tAsus A7N8X-E Deluxe\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
91.99 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tThermalright SP-94\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
49 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\"\"
1 \">\"PC Look
2 \">\"Atelier Informatique
3 \">\"Zanax Multim\351dia
4 \">\"MISTEROOPS
5 \">\"168 Golden Avenue
6 \">\"microchoix
7 \">\"e-Soph
8 \">\"PC Price Club
9 \">\"PC 77
10 \">\"Web In Informatique
\n\t\t\t\t
\n\t\t\t\t
\r\n \r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t
\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\r\n\r\n\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n

\r\n\t\t\t

\r\n\t\t\t

\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\r\n \r\n \r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

CD et DVD bient\364t insensibles aux rayures
OpenOffice gagne son service
La messagerie en cinq minutes selon Ipswitch
> toutes les news


\r\n\t\t
\r\n \r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Recevez chaque jour l\'actualit\351 des produits et des promos
\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n\r\n\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Entreprise
\r\n\t\t\t\tQuand le billet papier s\'envole vers la d\351mat\351rialisation


Trucs et astuces
\r\n\t\t\t\tD\351pannez Windows XP


Conso
\r\n\t\t\t\tVos photos sur papier imprimante ou labo ?


Produits & Tests
\r\n\t\t\t\t5 programmes d\222encodage vid\351o gratuits


\r\n\t\t
\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n
\r\n
\r\n\t\t\r\n\t\t

\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\r\n\r\n\r\n\t\t\t\r\n\r\n\r\n\r\n\t\t\t\t\r\n
\r\n
\r\nPortable
\r\nUn nouvel ultra portable r\351alis\351 par Nec
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nLe Versa S940 a un format r\351duit, mais ses performances sont \340 la hauteur.
\r\n\340 partir de 1663 \200\r\n
\r\n
\r\nPortable
\r\nAsus pr\351sente trois petits nouveaux dans la gamme A3N
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nCes trois portables Centrino int\350grent, entre autres, une webcam et un contr\364leur Wi-Fi.
\r\n\340 partir de 1346 \200\r\n
\r\n
\r\n\t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t
\r\n\t\r\n\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
BON PLAN
\r\n
\r\n
\r\nLes derni\350res technologies INTEL dans un nouveau design pour ce shuttle haut de gamme, pour un prix abordable.
\r\n

\r\n
\r\n\340 partir de
\r\n
415 \200
\r\n
\r\n
\r\n
publicit\351
\r\n
\r\n\t\r\n\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

\r\n\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\tDesktops
\r\n\t\t\t\tPortables
\r\n\t\t\t\tMini-PC
\r\n\t\t\t\tPda / Tablets-PC
\r\n\t\t\t\tApple
\r\n\t\t\t\tGPS
\r\n\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n

\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\tPortable Toshiba consacre deux gammes de machines au multim\351dia
\r\n\tEquipement haut de gamme et Windows Media Center sont au menu de ces portables \340 vocation multim\351dia.

\r\n\tOrdinateur Arriv\351e d\'un Power Mac G5 d\'entr\351e de gamme
\r\n\tLa firme \340 la pomme propose une station de travail \351volutive et relativement abordable.

\r\n\tPC Alienware propose deux machines au look \351trange
\r\n\tAurora et Area 51 sont deux gammes d\'ordinateurs enti\350rement configurables.

\r\n\tPortable Trois nouveaux iBook G4 chez Apple
\r\n\tChez Apple, les portables gagnent en vitesse et communiquent sans fil en standard.

\r\n\t\t\t\t> toutes les news\r\n\t\t\t
\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n

\r\n\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tAsus A3N15-C Pro
\r\n Voici un portable autonome et puissant gr\342ce \340 la technologie Intel Centrino.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1170 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tSoltek EQ3702A Miroir
\r\n Ce mini PC est une solution int\351ressante pour les utilisateurs poss\351dant d\351j\340 un \351cran.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t559 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tIBM ThinkPad R51
\r\n Voici un portable complet et pourtant relativement l\351ger.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1299 \200
\r\n
\r\n\t\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t> toutes les promos\r\n\t\t
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t
\r\n\t\t\t\r\n\t\t\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n\t\r\n\r\n
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\n
\r\n
\r\nLes graveurs de DVD
\r\nQuel graveur choisir ? Quel type de format ? Quelle vitesse ? Double couche ou simple couche ? Voici tout ce qu\'il faut savoir pour faire le bon choix.
\r\n\t\t\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n \t\r\n
\r\n\t\t
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
\r\n\t\t\t\t

\r\n\t\t\t\tChoisir une r\351gion
\r\n\r\n
Un d\351partement
\r\n\r\n
\r\n
Un arrondissement
\r\n\r\n
\r\n
\r\n\t\t\t\tRecherche directe
\r\n\t\t\t\trechercher une ville
et/ou une boutique
\r\n\t\t\t\t

\r\n\t\t\t\t \r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
Recherche avanc\351e
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
Bureautique
\r\n\t\t\t\tTraducteur, organiseur...

\r\n\t\t\t\t

Multim\351dia
\r\n\t\t\t\tPhoto, audio, vid\351o...

\r\n\t\t\t\t

Utilitaires
\r\n\t\t\t\tAntivirus, pilotes, gravure...

\r\n\t\t\t\t

Personnaliser son PC
\r\n\t\t\t\tEcrans de veille, th\350mes...

\r\n\t\t\t\t

D\351veloppement
\r\n\t\t\t\tCr\351ation de logiciels, BDD...

\r\n\t\t\t\t

Jeux
\r\n\t\t\t\tAction, simulation...

\r\n\t\t\t\t

Internet
\r\n\t\t\t\tUtilitaires, email, FTP...

\r\n\t\t\t\t

Loisirs
\r\n\t\t\t\tHumour, culture...

\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\t\t

\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n +#include +#include "leveldb/comparator.h" +#include "table/format.h" +#include "util/coding.h" +#include "util/logging.h" + +namespace leveldb { + +inline uint32_t Block::NumRestarts() const { + assert(size_ >= 2*sizeof(uint32_t)); + return DecodeFixed32(data_ + size_ - sizeof(uint32_t)); +} + +Block::Block(const BlockContents& contents) + : data_(contents.data.data()), + size_(contents.data.size()), + owned_(contents.heap_allocated) { + if (size_ < sizeof(uint32_t)) { + size_ = 0; // Error marker + } else { + restart_offset_ = size_ - (1 + NumRestarts()) * sizeof(uint32_t); + if (restart_offset_ > size_ - sizeof(uint32_t)) { + // The size is too small for NumRestarts() and therefore + // restart_offset_ wrapped around. + size_ = 0; + } + } +} + +Block::~Block() { + if (owned_) { + delete[] data_; + } +} + +// Helper routine: decode the next block entry starting at "p", +// storing the number of shared key bytes, non_shared key bytes, +// and the length of the value in "*shared", "*non_shared", and +// "*value_length", respectively. Will not derefence past "limit". +// +// If any errors are detected, returns nullptr. Otherwise, returns a +// pointer to the key delta (just past the three decoded values). +static inline const char* DecodeEntry(const char* p, const char* limit, + uint32_t* shared, + uint32_t* non_shared, + uint32_t* value_length) { + if (limit - p < 3) return nullptr; + *shared = reinterpret_cast(p)[0]; + *non_shared = reinterpret_cast(p)[1]; + *value_length = reinterpret_cast(p)[2]; + if ((*shared | *non_shared | *value_length) < 128) { + // Fast path: all three values are encoded in one byte each + p += 3; + } else { + if ((p = GetVarint32Ptr(p, limit, shared)) == nullptr) return nullptr; + if ((p = GetVarint32Ptr(p, limit, non_shared)) == nullptr) return nullptr; + if ((p = GetVarint32Ptr(p, limit, value_length)) == nullptr) return nullptr; + } + + if (static_cast(limit - p) < (*non_shared + *value_length)) { + return nullptr; + } + return p; +} + +class Block::Iter : public Iterator { + private: + const Comparator* const comparator_; + const char* const data_; // underlying block contents + uint32_t const restarts_; // Offset of restart array (list of fixed32) + uint32_t const num_restarts_; // Number of uint32_t entries in restart array + + // current_ is offset in data_ of current entry. >= restarts_ if !Valid + uint32_t current_; + uint32_t restart_index_; // Index of restart block in which current_ falls + std::string key_; + Slice value_; + Status status_; + + inline int Compare(const Slice& a, const Slice& b) const { + return comparator_->Compare(a, b); + } + + // Return the offset in data_ just past the end of the current entry. + inline uint32_t NextEntryOffset() const { + return (value_.data() + value_.size()) - data_; + } + + uint32_t GetRestartPoint(uint32_t index) { + assert(index < num_restarts_); + return DecodeFixed32(data_ + restarts_ + index * sizeof(uint32_t)); + } + + void SeekToRestartPoint(uint32_t index) { + key_.clear(); + restart_index_ = index; + // current_ will be fixed by ParseNextKey(); + + // ParseNextKey() starts at the end of value_, so set value_ accordingly + uint32_t offset = GetRestartPoint(index); + value_ = Slice(data_ + offset, 0); + } + + public: + Iter(const Comparator* comparator, + const char* data, + uint32_t restarts, + uint32_t num_restarts) + : comparator_(comparator), + data_(data), + restarts_(restarts), + num_restarts_(num_restarts), + current_(restarts_), + restart_index_(num_restarts_) { + assert(num_restarts_ > 0); + } + + virtual bool Valid() const { return current_ < restarts_; } + virtual Status status() const { return status_; } + virtual Slice key() const { + assert(Valid()); + return key_; + } + virtual Slice value() const { + assert(Valid()); + return value_; + } + + virtual void Next() { + assert(Valid()); + ParseNextKey(); + } + + virtual void Prev() { + assert(Valid()); + + // Scan backwards to a restart point before current_ + const uint32_t original = current_; + while (GetRestartPoint(restart_index_) >= original) { + if (restart_index_ == 0) { + // No more entries + current_ = restarts_; + restart_index_ = num_restarts_; + return; + } + restart_index_--; + } + + SeekToRestartPoint(restart_index_); + do { + // Loop until end of current entry hits the start of original entry + } while (ParseNextKey() && NextEntryOffset() < original); + } + + virtual void Seek(const Slice& target) { + // Binary search in restart array to find the first restart point + // with a key >= target + uint32_t left = 0; + uint32_t right = num_restarts_ - 1; + while (left < right) { + uint32_t mid = (left + right + 1) / 2; + uint32_t region_offset = GetRestartPoint(mid); + uint32_t shared, non_shared, value_length; + const char* key_ptr = DecodeEntry(data_ + region_offset, + data_ + restarts_, + &shared, &non_shared, &value_length); + if (key_ptr == nullptr || (shared != 0)) { + CorruptionError(); + return; + } + Slice mid_key(key_ptr, non_shared); + if (Compare(mid_key, target) < 0) { + // Key at "mid" is smaller than "target". Therefore all + // blocks before "mid" are uninteresting. + left = mid; + } else { + // Key at "mid" is >= "target". Therefore all blocks at or + // after "mid" are uninteresting. + right = mid - 1; + } + } + + // Linear search (within restart block) for first key >= target + SeekToRestartPoint(left); + while (true) { + if (!ParseNextKey()) { + return; + } + if (Compare(key_, target) >= 0) { + return; + } + } + } + + virtual void SeekToFirst() { + SeekToRestartPoint(0); + ParseNextKey(); + } + + virtual void SeekToLast() { + SeekToRestartPoint(num_restarts_ - 1); + while (ParseNextKey() && NextEntryOffset() < restarts_) { + // Keep skipping + } + } + + private: + void CorruptionError() { + current_ = restarts_; + restart_index_ = num_restarts_; + status_ = Status::Corruption("bad entry in block"); + key_.clear(); + value_.clear(); + } + + bool ParseNextKey() { + current_ = NextEntryOffset(); + const char* p = data_ + current_; + const char* limit = data_ + restarts_; // Restarts come right after data + if (p >= limit) { + // No more entries to return. Mark as invalid. + current_ = restarts_; + restart_index_ = num_restarts_; + return false; + } + + // Decode next entry + uint32_t shared, non_shared, value_length; + p = DecodeEntry(p, limit, &shared, &non_shared, &value_length); + if (p == nullptr || key_.size() < shared) { + CorruptionError(); + return false; + } else { + key_.resize(shared); + key_.append(p, non_shared); + value_ = Slice(p + non_shared, value_length); + while (restart_index_ + 1 < num_restarts_ && + GetRestartPoint(restart_index_ + 1) < current_) { + ++restart_index_; + } + return true; + } + } +}; + +Iterator* Block::NewIterator(const Comparator* cmp) { + if (size_ < 2*sizeof(uint32_t)) { + return NewErrorIterator(Status::Corruption("bad block contents")); + } + const uint32_t num_restarts = NumRestarts(); + if (num_restarts == 0) { + return NewEmptyIterator(); + } else { + return new Iter(cmp, data_, restart_offset_, num_restarts); + } +} + +} // namespace leveldb diff --git a/table/block.h b/table/block.h new file mode 100644 index 00000000..2493eb9f --- /dev/null +++ b/table/block.h @@ -0,0 +1,44 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_BLOCK_H_ +#define STORAGE_LEVELDB_TABLE_BLOCK_H_ + +#include +#include +#include "leveldb/iterator.h" + +namespace leveldb { + +struct BlockContents; +class Comparator; + +class Block { + public: + // Initialize the block with the specified contents. + explicit Block(const BlockContents& contents); + + ~Block(); + + size_t size() const { return size_; } + Iterator* NewIterator(const Comparator* comparator); + + private: + uint32_t NumRestarts() const; + + const char* data_; + size_t size_; + uint32_t restart_offset_; // Offset in data_ of restart array + bool owned_; // Block owns data_[] + + // No copying allowed + Block(const Block&); + void operator=(const Block&); + + class Iter; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_BLOCK_H_ diff --git a/table/block_builder.cc b/table/block_builder.cc new file mode 100644 index 00000000..db660cd0 --- /dev/null +++ b/table/block_builder.cc @@ -0,0 +1,109 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// BlockBuilder generates blocks where keys are prefix-compressed: +// +// When we store a key, we drop the prefix shared with the previous +// string. This helps reduce the space requirement significantly. +// Furthermore, once every K keys, we do not apply the prefix +// compression and store the entire key. We call this a "restart +// point". The tail end of the block stores the offsets of all of the +// restart points, and can be used to do a binary search when looking +// for a particular key. Values are stored as-is (without compression) +// immediately following the corresponding key. +// +// An entry for a particular key-value pair has the form: +// shared_bytes: varint32 +// unshared_bytes: varint32 +// value_length: varint32 +// key_delta: char[unshared_bytes] +// value: char[value_length] +// shared_bytes == 0 for restart points. +// +// The trailer of the block has the form: +// restarts: uint32[num_restarts] +// num_restarts: uint32 +// restarts[i] contains the offset within the block of the ith restart point. + +#include "table/block_builder.h" + +#include +#include +#include "leveldb/comparator.h" +#include "leveldb/table_builder.h" +#include "util/coding.h" + +namespace leveldb { + +BlockBuilder::BlockBuilder(const Options* options) + : options_(options), + restarts_(), + counter_(0), + finished_(false) { + assert(options->block_restart_interval >= 1); + restarts_.push_back(0); // First restart point is at offset 0 +} + +void BlockBuilder::Reset() { + buffer_.clear(); + restarts_.clear(); + restarts_.push_back(0); // First restart point is at offset 0 + counter_ = 0; + finished_ = false; + last_key_.clear(); +} + +size_t BlockBuilder::CurrentSizeEstimate() const { + return (buffer_.size() + // Raw data buffer + restarts_.size() * sizeof(uint32_t) + // Restart array + sizeof(uint32_t)); // Restart array length +} + +Slice BlockBuilder::Finish() { + // Append restart array + for (size_t i = 0; i < restarts_.size(); i++) { + PutFixed32(&buffer_, restarts_[i]); + } + PutFixed32(&buffer_, restarts_.size()); + finished_ = true; + return Slice(buffer_); +} + +void BlockBuilder::Add(const Slice& key, const Slice& value) { + Slice last_key_piece(last_key_); + assert(!finished_); + assert(counter_ <= options_->block_restart_interval); + assert(buffer_.empty() // No values yet? + || options_->comparator->Compare(key, last_key_piece) > 0); + size_t shared = 0; + if (counter_ < options_->block_restart_interval) { + // See how much sharing to do with previous string + const size_t min_length = std::min(last_key_piece.size(), key.size()); + while ((shared < min_length) && (last_key_piece[shared] == key[shared])) { + shared++; + } + } else { + // Restart compression + restarts_.push_back(buffer_.size()); + counter_ = 0; + } + const size_t non_shared = key.size() - shared; + + // Add "" to buffer_ + PutVarint32(&buffer_, shared); + PutVarint32(&buffer_, non_shared); + PutVarint32(&buffer_, value.size()); + + // Add string delta to buffer_ followed by value + buffer_.append(key.data() + shared, non_shared); + buffer_.append(value.data(), value.size()); + + // Update state + last_key_.resize(shared); + last_key_.append(key.data() + shared, non_shared); + assert(Slice(last_key_) == key); + counter_++; +} + +} // namespace leveldb diff --git a/table/block_builder.h b/table/block_builder.h new file mode 100644 index 00000000..5b545bd1 --- /dev/null +++ b/table/block_builder.h @@ -0,0 +1,57 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_ +#define STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_ + +#include + +#include +#include "leveldb/slice.h" + +namespace leveldb { + +struct Options; + +class BlockBuilder { + public: + explicit BlockBuilder(const Options* options); + + // Reset the contents as if the BlockBuilder was just constructed. + void Reset(); + + // REQUIRES: Finish() has not been callled since the last call to Reset(). + // REQUIRES: key is larger than any previously added key + void Add(const Slice& key, const Slice& value); + + // Finish building the block and return a slice that refers to the + // block contents. The returned slice will remain valid for the + // lifetime of this builder or until Reset() is called. + Slice Finish(); + + // Returns an estimate of the current (uncompressed) size of the block + // we are building. + size_t CurrentSizeEstimate() const; + + // Return true iff no entries have been added since the last Reset() + bool empty() const { + return buffer_.empty(); + } + + private: + const Options* options_; + std::string buffer_; // Destination buffer + std::vector restarts_; // Restart points + int counter_; // Number of entries emitted since restart + bool finished_; // Has Finish() been called? + std::string last_key_; + + // No copying allowed + BlockBuilder(const BlockBuilder&); + void operator=(const BlockBuilder&); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_ diff --git a/table/block_test.cc b/table/block_test.cc new file mode 100644 index 00000000..92154ac0 --- /dev/null +++ b/table/block_test.cc @@ -0,0 +1,106 @@ +// Copyright (c) 2012 Facebook. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/table.h" + +#include +#include "db/dbformat.h" +#include "db/memtable.h" +#include "db/write_batch_internal.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "leveldb/table_builder.h" +#include "table/block.h" +#include "table/block_builder.h" +#include "table/format.h" +#include "util/random.h" +#include "util/testharness.h" +#include "util/testutil.h" + +namespace leveldb { + +static std::string RandomString(Random* rnd, int len) { + std::string r; + test::RandomString(rnd, len, &r); + return r; +} + +class BlockTest {}; + +// block test +TEST(BlockTest, SimpleTest) { + Random rnd(301); + Options options = Options(); + std::vector keys; + std::vector values; + BlockBuilder builder(&options); + int num_records = 100000; + char buf[10]; + char* p = &buf[0]; + + // add a bunch of records to a block + for (int i = 0; i < num_records; i++) { + // generate random kvs + sprintf(p, "%6d", i); + std::string k(p); + std::string v = RandomString(&rnd, 100); // 100 byte values + + // write kvs to the block + Slice key(k); + Slice value(v); + builder.Add(key, value); + + // remember kvs in a lookaside array + keys.push_back(k); + values.push_back(v); + } + + // read serialized contents of the block + Slice rawblock = builder.Finish(); + + // create block reader + BlockContents contents; + contents.data = rawblock; + contents.cachable = false; + contents.heap_allocated = false; + Block reader(contents); + + // read contents of block sequentially + int count = 0; + Iterator* iter = reader.NewIterator(options.comparator); + for (iter->SeekToFirst();iter->Valid(); count++, iter->Next()) { + + // read kv from block + Slice k = iter->key(); + Slice v = iter->value(); + + // compare with lookaside array + ASSERT_EQ(k.ToString().compare(keys[count]), 0); + ASSERT_EQ(v.ToString().compare(values[count]), 0); + } + delete iter; + + // read block contents randomly + iter = reader.NewIterator(options.comparator); + for (int i = 0; i < num_records; i++) { + + // find a random key in the lookaside array + int index = rnd.Uniform(num_records); + Slice k(keys[index]); + + // search in block for this key + iter->Seek(k); + ASSERT_TRUE(iter->Valid()); + Slice v = iter->value(); + ASSERT_EQ(v.ToString().compare(values[index]), 0); + } + delete iter; +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/table/filter_block.cc b/table/filter_block.cc new file mode 100644 index 00000000..b9dfc5c0 --- /dev/null +++ b/table/filter_block.cc @@ -0,0 +1,111 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/filter_block.h" + +#include "leveldb/filter_policy.h" +#include "util/coding.h" + +namespace leveldb { + +// See doc/table_format.txt for an explanation of the filter block format. + +// Generate new filter every 2KB of data +static const size_t kFilterBaseLg = 11; +static const size_t kFilterBase = 1 << kFilterBaseLg; + +FilterBlockBuilder::FilterBlockBuilder(const FilterPolicy* policy) + : policy_(policy) { +} + +void FilterBlockBuilder::StartBlock(uint64_t block_offset) { + uint64_t filter_index = (block_offset / kFilterBase); + assert(filter_index >= filter_offsets_.size()); + while (filter_index > filter_offsets_.size()) { + GenerateFilter(); + } +} + +void FilterBlockBuilder::AddKey(const Slice& key) { + Slice k = key; + start_.push_back(keys_.size()); + keys_.append(k.data(), k.size()); +} + +Slice FilterBlockBuilder::Finish() { + if (!start_.empty()) { + GenerateFilter(); + } + + // Append array of per-filter offsets + const uint32_t array_offset = result_.size(); + for (size_t i = 0; i < filter_offsets_.size(); i++) { + PutFixed32(&result_, filter_offsets_[i]); + } + + PutFixed32(&result_, array_offset); + result_.push_back(kFilterBaseLg); // Save encoding parameter in result + return Slice(result_); +} + +void FilterBlockBuilder::GenerateFilter() { + const size_t num_keys = start_.size(); + if (num_keys == 0) { + // Fast path if there are no keys for this filter + filter_offsets_.push_back(result_.size()); + return; + } + + // Make list of keys from flattened key structure + start_.push_back(keys_.size()); // Simplify length computation + tmp_keys_.resize(num_keys); + for (size_t i = 0; i < num_keys; i++) { + const char* base = keys_.data() + start_[i]; + size_t length = start_[i+1] - start_[i]; + tmp_keys_[i] = Slice(base, length); + } + + // Generate filter for current set of keys and append to result_. + filter_offsets_.push_back(result_.size()); + policy_->CreateFilter(&tmp_keys_[0], num_keys, &result_); + + tmp_keys_.clear(); + keys_.clear(); + start_.clear(); +} + +FilterBlockReader::FilterBlockReader(const FilterPolicy* policy, + const Slice& contents) + : policy_(policy), + data_(nullptr), + offset_(nullptr), + num_(0), + base_lg_(0) { + size_t n = contents.size(); + if (n < 5) return; // 1 byte for base_lg_ and 4 for start of offset array + base_lg_ = contents[n-1]; + uint32_t last_word = DecodeFixed32(contents.data() + n - 5); + if (last_word > n - 5) return; + data_ = contents.data(); + offset_ = data_ + last_word; + num_ = (n - 5 - last_word) / 4; +} + +bool FilterBlockReader::KeyMayMatch(uint64_t block_offset, const Slice& key) { + uint64_t index = block_offset >> base_lg_; + if (index < num_) { + uint32_t start = DecodeFixed32(offset_ + index*4); + uint32_t limit = DecodeFixed32(offset_ + index*4 + 4); + if (start <= limit && limit <= (offset_ - data_)) { + Slice filter = Slice(data_ + start, limit - start); + return policy_->KeyMayMatch(key, filter); + } else if (start == limit) { + // Empty filters do not match any keys + return false; + } + } + return true; // Errors are treated as potential matches +} + +} diff --git a/table/filter_block.h b/table/filter_block.h new file mode 100644 index 00000000..c67d010b --- /dev/null +++ b/table/filter_block.h @@ -0,0 +1,68 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A filter block is stored near the end of a Table file. It contains +// filters (e.g., bloom filters) for all data blocks in the table combined +// into a single filter block. + +#ifndef STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_ +#define STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_ + +#include +#include +#include +#include +#include "leveldb/slice.h" +#include "util/hash.h" + +namespace leveldb { + +class FilterPolicy; + +// A FilterBlockBuilder is used to construct all of the filters for a +// particular Table. It generates a single string which is stored as +// a special block in the Table. +// +// The sequence of calls to FilterBlockBuilder must match the regexp: +// (StartBlock AddKey*)* Finish +class FilterBlockBuilder { + public: + explicit FilterBlockBuilder(const FilterPolicy*); + + void StartBlock(uint64_t block_offset); + void AddKey(const Slice& key); + Slice Finish(); + + private: + void GenerateFilter(); + + const FilterPolicy* policy_; + std::string keys_; // Flattened key contents + std::vector start_; // Starting index in keys_ of each key + std::string result_; // Filter data computed so far + std::vector tmp_keys_; // policy_->CreateFilter() argument + std::vector filter_offsets_; + + // No copying allowed + FilterBlockBuilder(const FilterBlockBuilder&); + void operator=(const FilterBlockBuilder&); +}; + +class FilterBlockReader { + public: + // REQUIRES: "contents" and *policy must stay live while *this is live. + FilterBlockReader(const FilterPolicy* policy, const Slice& contents); + bool KeyMayMatch(uint64_t block_offset, const Slice& key); + + private: + const FilterPolicy* policy_; + const char* data_; // Pointer to filter data (at block-start) + const char* offset_; // Pointer to beginning of offset array (at block-end) + size_t num_; // Number of entries in offset array + size_t base_lg_; // Encoding parameter (see kFilterBaseLg in .cc file) +}; + +} + +#endif // STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_ diff --git a/table/filter_block_test.cc b/table/filter_block_test.cc new file mode 100644 index 00000000..cadb273b --- /dev/null +++ b/table/filter_block_test.cc @@ -0,0 +1,128 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/filter_block.h" + +#include "leveldb/filter_policy.h" +#include "util/coding.h" +#include "util/hash.h" +#include "util/logging.h" +#include "util/testharness.h" +#include "util/testutil.h" + +namespace leveldb { + +// For testing: emit an array with one hash value per key +class TestHashFilter : public FilterPolicy { + public: + virtual const char* Name() const { + return "TestHashFilter"; + } + + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const { + for (int i = 0; i < n; i++) { + uint32_t h = Hash(keys[i].data(), keys[i].size(), 1); + PutFixed32(dst, h); + } + } + + virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const { + uint32_t h = Hash(key.data(), key.size(), 1); + for (unsigned int i = 0; i + 4 <= filter.size(); i += 4) { + if (h == DecodeFixed32(filter.data() + i)) { + return true; + } + } + return false; + } +}; + +class FilterBlockTest { + public: + TestHashFilter policy_; +}; + +TEST(FilterBlockTest, EmptyBuilder) { + FilterBlockBuilder builder(&policy_); + Slice block = builder.Finish(); + ASSERT_EQ("\\x00\\x00\\x00\\x00\\x0b", EscapeString(block)); + FilterBlockReader reader(&policy_, block); + ASSERT_TRUE(reader.KeyMayMatch(0, "foo")); + ASSERT_TRUE(reader.KeyMayMatch(100000, "foo")); +} + +TEST(FilterBlockTest, SingleChunk) { + FilterBlockBuilder builder(&policy_); + builder.StartBlock(100); + builder.AddKey("foo"); + builder.AddKey("bar"); + builder.AddKey("box"); + builder.StartBlock(200); + builder.AddKey("box"); + builder.StartBlock(300); + builder.AddKey("hello"); + Slice block = builder.Finish(); + FilterBlockReader reader(&policy_, block); + ASSERT_TRUE(reader.KeyMayMatch(100, "foo")); + ASSERT_TRUE(reader.KeyMayMatch(100, "bar")); + ASSERT_TRUE(reader.KeyMayMatch(100, "box")); + ASSERT_TRUE(reader.KeyMayMatch(100, "hello")); + ASSERT_TRUE(reader.KeyMayMatch(100, "foo")); + ASSERT_TRUE(! reader.KeyMayMatch(100, "missing")); + ASSERT_TRUE(! reader.KeyMayMatch(100, "other")); +} + +TEST(FilterBlockTest, MultiChunk) { + FilterBlockBuilder builder(&policy_); + + // First filter + builder.StartBlock(0); + builder.AddKey("foo"); + builder.StartBlock(2000); + builder.AddKey("bar"); + + // Second filter + builder.StartBlock(3100); + builder.AddKey("box"); + + // Third filter is empty + + // Last filter + builder.StartBlock(9000); + builder.AddKey("box"); + builder.AddKey("hello"); + + Slice block = builder.Finish(); + FilterBlockReader reader(&policy_, block); + + // Check first filter + ASSERT_TRUE(reader.KeyMayMatch(0, "foo")); + ASSERT_TRUE(reader.KeyMayMatch(2000, "bar")); + ASSERT_TRUE(! reader.KeyMayMatch(0, "box")); + ASSERT_TRUE(! reader.KeyMayMatch(0, "hello")); + + // Check second filter + ASSERT_TRUE(reader.KeyMayMatch(3100, "box")); + ASSERT_TRUE(! reader.KeyMayMatch(3100, "foo")); + ASSERT_TRUE(! reader.KeyMayMatch(3100, "bar")); + ASSERT_TRUE(! reader.KeyMayMatch(3100, "hello")); + + // Check third filter (empty) + ASSERT_TRUE(! reader.KeyMayMatch(4100, "foo")); + ASSERT_TRUE(! reader.KeyMayMatch(4100, "bar")); + ASSERT_TRUE(! reader.KeyMayMatch(4100, "box")); + ASSERT_TRUE(! reader.KeyMayMatch(4100, "hello")); + + // Check last filter + ASSERT_TRUE(reader.KeyMayMatch(9000, "box")); + ASSERT_TRUE(reader.KeyMayMatch(9000, "hello")); + ASSERT_TRUE(! reader.KeyMayMatch(9000, "foo")); + ASSERT_TRUE(! reader.KeyMayMatch(9000, "bar")); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/table/format.cc b/table/format.cc new file mode 100644 index 00000000..6c3f5910 --- /dev/null +++ b/table/format.cc @@ -0,0 +1,178 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/format.h" + +#include "leveldb/env.h" +#include "port/port.h" +#include "table/block.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { + +void BlockHandle::EncodeTo(std::string* dst) const { + // Sanity check that all fields have been set + assert(offset_ != ~static_cast(0)); + assert(size_ != ~static_cast(0)); + PutVarint64(dst, offset_); + PutVarint64(dst, size_); +} + +Status BlockHandle::DecodeFrom(Slice* input) { + if (GetVarint64(input, &offset_) && + GetVarint64(input, &size_)) { + return Status::OK(); + } else { + return Status::Corruption("bad block handle"); + } +} + +void Footer::EncodeTo(std::string* dst) const { +#ifndef NDEBUG + const size_t original_size = dst->size(); +#endif + metaindex_handle_.EncodeTo(dst); + index_handle_.EncodeTo(dst); + dst->resize(2 * BlockHandle::kMaxEncodedLength); // Padding + PutFixed32(dst, static_cast(kTableMagicNumber & 0xffffffffu)); + PutFixed32(dst, static_cast(kTableMagicNumber >> 32)); + assert(dst->size() == original_size + kEncodedLength); +} + +Status Footer::DecodeFrom(Slice* input) { + assert(input != nullptr); + assert(input->size() >= kEncodedLength); + + const char* magic_ptr = input->data() + kEncodedLength - 8; + const uint32_t magic_lo = DecodeFixed32(magic_ptr); + const uint32_t magic_hi = DecodeFixed32(magic_ptr + 4); + const uint64_t magic = ((static_cast(magic_hi) << 32) | + (static_cast(magic_lo))); + if (magic != kTableMagicNumber) { + return Status::InvalidArgument("not an sstable (bad magic number)"); + } + + Status result = metaindex_handle_.DecodeFrom(input); + if (result.ok()) { + result = index_handle_.DecodeFrom(input); + } + if (result.ok()) { + // We skip over any leftover data (just padding for now) in "input" + const char* end = magic_ptr + 8; + *input = Slice(end, input->data() + input->size() - end); + } + return result; +} + +Status ReadBlock(RandomAccessFile* file, + const ReadOptions& options, + const BlockHandle& handle, + BlockContents* result) { + result->data = Slice(); + result->cachable = false; + result->heap_allocated = false; + + // Read the block contents as well as the type/crc footer. + // See table_builder.cc for the code that built this structure. + size_t n = static_cast(handle.size()); + char* buf = new char[n + kBlockTrailerSize]; + Slice contents; + Status s = file->Read(handle.offset(), n + kBlockTrailerSize, &contents, buf); + if (!s.ok()) { + delete[] buf; + return s; + } + if (contents.size() != n + kBlockTrailerSize) { + delete[] buf; + return Status::Corruption("truncated block read"); + } + + // Check the crc of the type and the block contents + const char* data = contents.data(); // Pointer to where Read put the data + if (options.verify_checksums) { + const uint32_t crc = crc32c::Unmask(DecodeFixed32(data + n + 1)); + const uint32_t actual = crc32c::Value(data, n + 1); + if (actual != crc) { + delete[] buf; + s = Status::Corruption("block checksum mismatch"); + return s; + } + } + + char* ubuf = nullptr; + int decompress_size = 0; + switch (data[n]) { + case kNoCompression: + if (data != buf) { + // File implementation gave us pointer to some other data. + // Use it directly under the assumption that it will be live + // while the file is open. + delete[] buf; + result->data = Slice(data, n); + result->heap_allocated = false; + result->cachable = false; // Do not double-cache + } else { + result->data = Slice(buf, n); + result->heap_allocated = true; + result->cachable = true; + } + + // Ok + break; + case kSnappyCompression: { + size_t ulength = 0; + static char snappy_corrupt_msg[] = + "Snappy not supported or corrupted Snappy compressed block contents"; + if (!port::Snappy_GetUncompressedLength(data, n, &ulength)) { + delete[] buf; + return Status::Corruption(snappy_corrupt_msg); + } + ubuf = new char[ulength]; + if (!port::Snappy_Uncompress(data, n, ubuf)) { + delete[] buf; + delete[] ubuf; + return Status::Corruption(snappy_corrupt_msg); + } + delete[] buf; + result->data = Slice(ubuf, ulength); + result->heap_allocated = true; + result->cachable = true; + break; + } + case kZlibCompression: + ubuf = port::Zlib_Uncompress(data, n, &decompress_size); + static char zlib_corrupt_msg[] = + "Zlib not supported or corrupted Zlib compressed block contents"; + if (!ubuf) { + delete[] buf; + return Status::Corruption(zlib_corrupt_msg); + } + delete[] buf; + result->data = Slice(ubuf, decompress_size); + result->heap_allocated = true; + result->cachable = true; + break; + case kBZip2Compression: + ubuf = port::BZip2_Uncompress(data, n, &decompress_size); + static char bzip2_corrupt_msg[] = + "Bzip2 not supported or corrupted Bzip2 compressed block contents"; + if (!ubuf) { + delete[] buf; + return Status::Corruption(bzip2_corrupt_msg); + } + delete[] buf; + result->data = Slice(ubuf, decompress_size); + result->heap_allocated = true; + result->cachable = true; + break; + default: + delete[] buf; + return Status::Corruption("bad block type"); + } + + return Status::OK(); +} + +} // namespace leveldb diff --git a/table/format.h b/table/format.h new file mode 100644 index 00000000..6c0b80c0 --- /dev/null +++ b/table/format.h @@ -0,0 +1,108 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_FORMAT_H_ +#define STORAGE_LEVELDB_TABLE_FORMAT_H_ + +#include +#include +#include "leveldb/slice.h" +#include "leveldb/status.h" +#include "leveldb/table_builder.h" + +namespace leveldb { + +class Block; +class RandomAccessFile; +struct ReadOptions; + +// BlockHandle is a pointer to the extent of a file that stores a data +// block or a meta block. +class BlockHandle { + public: + BlockHandle(); + + // The offset of the block in the file. + uint64_t offset() const { return offset_; } + void set_offset(uint64_t offset) { offset_ = offset; } + + // The size of the stored block + uint64_t size() const { return size_; } + void set_size(uint64_t size) { size_ = size; } + + void EncodeTo(std::string* dst) const; + Status DecodeFrom(Slice* input); + + // Maximum encoding length of a BlockHandle + enum { kMaxEncodedLength = 10 + 10 }; + + private: + uint64_t offset_; + uint64_t size_; +}; + +// Footer encapsulates the fixed information stored at the tail +// end of every table file. +class Footer { + public: + Footer() { } + + // The block handle for the metaindex block of the table + const BlockHandle& metaindex_handle() const { return metaindex_handle_; } + void set_metaindex_handle(const BlockHandle& h) { metaindex_handle_ = h; } + + // The block handle for the index block of the table + const BlockHandle& index_handle() const { + return index_handle_; + } + void set_index_handle(const BlockHandle& h) { + index_handle_ = h; + } + + void EncodeTo(std::string* dst) const; + Status DecodeFrom(Slice* input); + + // Encoded length of a Footer. Note that the serialization of a + // Footer will always occupy exactly this many bytes. It consists + // of two block handles and a magic number. + enum { + kEncodedLength = 2*BlockHandle::kMaxEncodedLength + 8 + }; + + private: + BlockHandle metaindex_handle_; + BlockHandle index_handle_; +}; + +// kTableMagicNumber was picked by running +// echo http://code.google.com/p/leveldb/ | sha1sum +// and taking the leading 64 bits. +static const uint64_t kTableMagicNumber = 0xdb4775248b80fb57ull; + +// 1-byte type + 32-bit crc +static const size_t kBlockTrailerSize = 5; + +struct BlockContents { + Slice data; // Actual contents of data + bool cachable; // True iff data can be cached + bool heap_allocated; // True iff caller should delete[] data.data() +}; + +// Read the block identified by "handle" from "file". On failure +// return non-OK. On success fill *result and return OK. +extern Status ReadBlock(RandomAccessFile* file, + const ReadOptions& options, + const BlockHandle& handle, + BlockContents* result); + +// Implementation details follow. Clients should ignore, + +inline BlockHandle::BlockHandle() + : offset_(~static_cast(0)), + size_(~static_cast(0)) { +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_FORMAT_H_ diff --git a/table/iter_heap.h b/table/iter_heap.h new file mode 100644 index 00000000..52518ba9 --- /dev/null +++ b/table/iter_heap.h @@ -0,0 +1,63 @@ +// Copyright 2008-present Facebook. All Rights Reserved. +#ifndef STORAGE_LEVELDB_ITER_HEAP_H_ +#define STORAGE_LEVELDB_ITER_HEAP_H_ + +#include + +#include "leveldb/comparator.h" +#include "table/iterator_wrapper.h" + +namespace leveldb { + +// Return the max of two keys. +class MaxIteratorComparator { + public: + MaxIteratorComparator(const Comparator* comparator) : + comparator_(comparator) {} + + bool operator()(IteratorWrapper* a, IteratorWrapper* b) { + return comparator_->Compare(a->key(), b->key()) <= 0; + } + private: + const Comparator* comparator_; +}; + +// Return the max of two keys. +class MinIteratorComparator { + public: + // if maxHeap is set comparator returns the max value. + // else returns the min Value. + // Can use to create a minHeap or a maxHeap. + MinIteratorComparator(const Comparator* comparator) : + comparator_(comparator) {} + + bool operator()(IteratorWrapper* a, IteratorWrapper* b) { + return comparator_->Compare(a->key(), b->key()) > 0; + } + private: + const Comparator* comparator_; +}; + +typedef std::priority_queue< + IteratorWrapper*, + std::vector, + MaxIteratorComparator> MaxIterHeap; + +typedef std::priority_queue< + IteratorWrapper*, + std::vector, + MinIteratorComparator> MinIterHeap; + +// Return's a new MaxHeap of IteratorWrapper's using the provided Comparator. +MaxIterHeap NewMaxIterHeap(const Comparator* comparator) { + return MaxIterHeap(MaxIteratorComparator(comparator)); +} + +// Return's a new MinHeap of IteratorWrapper's using the provided Comparator. +MinIterHeap NewMinIterHeap(const Comparator* comparator) { + return MinIterHeap(MinIteratorComparator(comparator)); +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_ITER_HEAP_H_ diff --git a/table/iterator.cc b/table/iterator.cc new file mode 100644 index 00000000..01107872 --- /dev/null +++ b/table/iterator.cc @@ -0,0 +1,67 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/iterator.h" + +namespace leveldb { + +Iterator::Iterator() { + cleanup_.function = nullptr; + cleanup_.next = nullptr; +} + +Iterator::~Iterator() { + if (cleanup_.function != nullptr) { + (*cleanup_.function)(cleanup_.arg1, cleanup_.arg2); + for (Cleanup* c = cleanup_.next; c != nullptr; ) { + (*c->function)(c->arg1, c->arg2); + Cleanup* next = c->next; + delete c; + c = next; + } + } +} + +void Iterator::RegisterCleanup(CleanupFunction func, void* arg1, void* arg2) { + assert(func != nullptr); + Cleanup* c; + if (cleanup_.function == nullptr) { + c = &cleanup_; + } else { + c = new Cleanup; + c->next = cleanup_.next; + cleanup_.next = c; + } + c->function = func; + c->arg1 = arg1; + c->arg2 = arg2; +} + +namespace { +class EmptyIterator : public Iterator { + public: + explicit EmptyIterator(const Status& s) : status_(s) { } + virtual bool Valid() const { return false; } + virtual void Seek(const Slice& target) { } + virtual void SeekToFirst() { } + virtual void SeekToLast() { } + virtual void Next() { assert(false); } + virtual void Prev() { assert(false); } + Slice key() const { assert(false); return Slice(); } + Slice value() const { assert(false); return Slice(); } + virtual Status status() const { return status_; } + private: + Status status_; +}; +} // namespace + +Iterator* NewEmptyIterator() { + return new EmptyIterator(Status::OK()); +} + +Iterator* NewErrorIterator(const Status& status) { + return new EmptyIterator(status); +} + +} // namespace leveldb diff --git a/table/iterator_wrapper.h b/table/iterator_wrapper.h new file mode 100644 index 00000000..98d85246 --- /dev/null +++ b/table/iterator_wrapper.h @@ -0,0 +1,63 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_ +#define STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_ + +namespace leveldb { + +// A internal wrapper class with an interface similar to Iterator that +// caches the valid() and key() results for an underlying iterator. +// This can help avoid virtual function calls and also gives better +// cache locality. +class IteratorWrapper { + public: + IteratorWrapper(): iter_(nullptr), valid_(false) { } + explicit IteratorWrapper(Iterator* iter): iter_(nullptr) { + Set(iter); + } + ~IteratorWrapper() { delete iter_; } + Iterator* iter() const { return iter_; } + + // Takes ownership of "iter" and will delete it when destroyed, or + // when Set() is invoked again. + void Set(Iterator* iter) { + delete iter_; + iter_ = iter; + if (iter_ == nullptr) { + valid_ = false; + } else { + Update(); + } + } + + + // Iterator interface methods + bool Valid() const { return valid_; } + Slice key() const { assert(Valid()); return key_; } + Slice value() const { assert(Valid()); return iter_->value(); } + // Methods below require iter() != nullptr + Status status() const { assert(iter_); return iter_->status(); } + void Next() { assert(iter_); iter_->Next(); Update(); } + void Prev() { assert(iter_); iter_->Prev(); Update(); } + void Seek(const Slice& k) { assert(iter_); iter_->Seek(k); Update(); } + void SeekToFirst() { assert(iter_); iter_->SeekToFirst(); Update(); } + void SeekToLast() { assert(iter_); iter_->SeekToLast(); Update(); } + + private: + void Update() { + valid_ = iter_->Valid(); + if (valid_) { + key_ = iter_->key(); + } + } + + Iterator* iter_; + bool valid_; + Slice key_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_ diff --git a/table/merger.cc b/table/merger.cc new file mode 100644 index 00000000..ce821620 --- /dev/null +++ b/table/merger.cc @@ -0,0 +1,227 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/merger.h" + +#include "leveldb/comparator.h" +#include "leveldb/iterator.h" +#include "table/iter_heap.h" +#include "table/iterator_wrapper.h" + +namespace leveldb { + +namespace { + +class MergingIterator : public Iterator { + public: + MergingIterator(const Comparator* comparator, Iterator** children, int n) + : comparator_(comparator), + children_(new IteratorWrapper[n]), + n_(n), + current_(nullptr), + direction_(kForward), + maxHeap_(NewMaxIterHeap(comparator_)), + minHeap_ (NewMinIterHeap(comparator_)) { + for (int i = 0; i < n; i++) { + children_[i].Set(children[i]); + } + for (int i = 0; i < n; ++i) { + if (children_[i].Valid()) { + minHeap_.push(&children_[i]); + } + } + } + + virtual ~MergingIterator() { + delete[] children_; + } + + virtual bool Valid() const { + return (current_ != nullptr); + } + + virtual void SeekToFirst() { + ClearHeaps(); + for (int i = 0; i < n_; i++) { + children_[i].SeekToFirst(); + if (children_[i].Valid()) { + minHeap_.push(&children_[i]); + } + } + FindSmallest(); + direction_ = kForward; + } + + virtual void SeekToLast() { + ClearHeaps(); + for (int i = 0; i < n_; i++) { + children_[i].SeekToLast(); + if (children_[i].Valid()) { + maxHeap_.push(&children_[i]); + } + } + FindLargest(); + direction_ = kReverse; + } + + virtual void Seek(const Slice& target) { + ClearHeaps(); + for (int i = 0; i < n_; i++) { + children_[i].Seek(target); + if (children_[i].Valid()) { + minHeap_.push(&children_[i]); + } + } + FindSmallest(); + direction_ = kForward; + } + + virtual void Next() { + assert(Valid()); + + // Ensure that all children are positioned after key(). + // If we are moving in the forward direction, it is already + // true for all of the non-current_ children since current_ is + // the smallest child and key() == current_->key(). Otherwise, + // we explicitly position the non-current_ children. + if (direction_ != kForward) { + ClearHeaps(); + for (int i = 0; i < n_; i++) { + IteratorWrapper* child = &children_[i]; + if (child != current_) { + child->Seek(key()); + if (child->Valid() && + comparator_->Compare(key(), child->key()) == 0) { + child->Next(); + } + if (child->Valid()) { + minHeap_.push(child); + } + } + } + direction_ = kForward; + } + + // as the current points to the current record. move the iterator forward. + // and if it is valid add it to the heap. + current_->Next(); + if (current_->Valid()){ + minHeap_.push(current_); + } + FindSmallest(); + } + + virtual void Prev() { + assert(Valid()); + // Ensure that all children are positioned before key(). + // If we are moving in the reverse direction, it is already + // true for all of the non-current_ children since current_ is + // the largest child and key() == current_->key(). Otherwise, + // we explicitly position the non-current_ children. + if (direction_ != kReverse) { + ClearHeaps(); + for (int i = 0; i < n_; i++) { + IteratorWrapper* child = &children_[i]; + if (child != current_) { + child->Seek(key()); + if (child->Valid()) { + // Child is at first entry >= key(). Step back one to be < key() + child->Prev(); + } else { + // Child has no entries >= key(). Position at last entry. + child->SeekToLast(); + } + if (child->Valid()) { + maxHeap_.push(child); + } + } + } + direction_ = kReverse; + } + + current_->Prev(); + if (current_->Valid()) { + maxHeap_.push(current_); + } + FindLargest(); + } + + virtual Slice key() const { + assert(Valid()); + return current_->key(); + } + + virtual Slice value() const { + assert(Valid()); + return current_->value(); + } + + virtual Status status() const { + Status status; + for (int i = 0; i < n_; i++) { + status = children_[i].status(); + if (!status.ok()) { + break; + } + } + return status; + } + + private: + void FindSmallest(); + void FindLargest(); + void ClearHeaps(); + + const Comparator* comparator_; + IteratorWrapper* children_; + int n_; + IteratorWrapper* current_; + // Which direction is the iterator moving? + enum Direction { + kForward, + kReverse + }; + Direction direction_; + MaxIterHeap maxHeap_; + MinIterHeap minHeap_; +}; + +void MergingIterator::FindSmallest() { + if (minHeap_.empty()) { + current_ = nullptr; + } else { + current_ = minHeap_.top(); + assert(current_->Valid()); + minHeap_.pop(); + } +} + +void MergingIterator::FindLargest() { + if (maxHeap_.empty()) { + current_ = nullptr; + } else { + current_ = maxHeap_.top(); + assert(current_->Valid()); + maxHeap_.pop(); + } +} + +void MergingIterator::ClearHeaps() { + maxHeap_ = NewMaxIterHeap(comparator_); + minHeap_ = NewMinIterHeap(comparator_); +} +} // namespace + +Iterator* NewMergingIterator(const Comparator* cmp, Iterator** list, int n) { + assert(n >= 0); + if (n == 0) { + return NewEmptyIterator(); + } else if (n == 1) { + return list[0]; + } else { + return new MergingIterator(cmp, list, n); + } +} + +} // namespace leveldb diff --git a/table/merger.h b/table/merger.h new file mode 100644 index 00000000..91ddd80f --- /dev/null +++ b/table/merger.h @@ -0,0 +1,26 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_MERGER_H_ +#define STORAGE_LEVELDB_TABLE_MERGER_H_ + +namespace leveldb { + +class Comparator; +class Iterator; + +// Return an iterator that provided the union of the data in +// children[0,n-1]. Takes ownership of the child iterators and +// will delete them when the result iterator is deleted. +// +// The result does no duplicate suppression. I.e., if a particular +// key is present in K child iterators, it will be yielded K times. +// +// REQUIRES: n >= 0 +extern Iterator* NewMergingIterator( + const Comparator* comparator, Iterator** children, int n); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_MERGER_H_ diff --git a/table/table.cc b/table/table.cc new file mode 100644 index 00000000..8e9b0253 --- /dev/null +++ b/table/table.cc @@ -0,0 +1,346 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/table.h" + +#include "leveldb/cache.h" +#include "leveldb/comparator.h" +#include "leveldb/env.h" +#include "leveldb/filter_policy.h" +#include "leveldb/options.h" +#include "leveldb/statistics.h" +#include "table/block.h" +#include "table/filter_block.h" +#include "table/format.h" +#include "table/two_level_iterator.h" +#include "util/coding.h" + +namespace leveldb { + +// The longest the prefix of the cache key used to identify blocks can be. +// We are using the fact that we know for Posix files the unique ID is three +// varints. +const size_t kMaxCacheKeyPrefixSize = kMaxVarint64Length*3+1; + +struct Table::Rep { + ~Rep() { + delete filter; + delete [] filter_data; + delete index_block; + } + + Options options; + Status status; + unique_ptr file; + char cache_key_prefix[kMaxCacheKeyPrefixSize]; + size_t cache_key_prefix_size; + FilterBlockReader* filter; + const char* filter_data; + + BlockHandle metaindex_handle; // Handle to metaindex_block: saved from footer + Block* index_block; +}; + +// Helper function to setup the cache key's prefix for the Table. +void Table::SetupCacheKeyPrefix(Rep* rep) { + assert(kMaxCacheKeyPrefixSize >= 10); + rep->cache_key_prefix_size = 0; + if (rep->options.block_cache) { + rep->cache_key_prefix_size = rep->file->GetUniqueId(rep->cache_key_prefix, + kMaxCacheKeyPrefixSize); + + if (rep->cache_key_prefix_size == 0) { + // If the prefix wasn't generated or was too long, we create one from the + // cache. + char* end = EncodeVarint64(rep->cache_key_prefix, + rep->options.block_cache->NewId()); + rep->cache_key_prefix_size = + static_cast(end - rep->cache_key_prefix); + } + } +} + +Status Table::Open(const Options& options, + unique_ptr&& file, + uint64_t size, + unique_ptr* table) { + table->reset(); + if (size < Footer::kEncodedLength) { + return Status::InvalidArgument("file is too short to be an sstable"); + } + + char footer_space[Footer::kEncodedLength]; + Slice footer_input; + Status s = file->Read(size - Footer::kEncodedLength, Footer::kEncodedLength, + &footer_input, footer_space); + if (!s.ok()) return s; + + // Check that we actually read the whole footer from the file. It may be + // that size isn't correct. + if (footer_input.size() != Footer::kEncodedLength) { + return Status::InvalidArgument("file is too short to be an sstable"); + } + + + Footer footer; + s = footer.DecodeFrom(&footer_input); + if (!s.ok()) return s; + + // Read the index block + BlockContents contents; + Block* index_block = nullptr; + if (s.ok()) { + s = ReadBlock(file.get(), ReadOptions(), footer.index_handle(), &contents); + if (s.ok()) { + index_block = new Block(contents); + } + } + + if (s.ok()) { + // We've successfully read the footer and the index block: we're + // ready to serve requests. + Rep* rep = new Table::Rep; + rep->options = options; + rep->file = std::move(file); + rep->metaindex_handle = footer.metaindex_handle(); + rep->index_block = index_block; + SetupCacheKeyPrefix(rep); + rep->filter_data = nullptr; + rep->filter = nullptr; + table->reset(new Table(rep)); + (*table)->ReadMeta(footer); + } else { + if (index_block) delete index_block; + } + + return s; +} + +void Table::ReadMeta(const Footer& footer) { + if (rep_->options.filter_policy == nullptr) { + return; // Do not need any metadata + } + + // TODO(sanjay): Skip this if footer.metaindex_handle() size indicates + // it is an empty block. + ReadOptions opt; + BlockContents contents; + if (!ReadBlock(rep_->file.get(), opt, footer.metaindex_handle(), + &contents).ok()) { + // Do not propagate errors since meta info is not needed for operation + return; + } + Block* meta = new Block(contents); + + Iterator* iter = meta->NewIterator(BytewiseComparator()); + std::string key = "filter."; + key.append(rep_->options.filter_policy->Name()); + iter->Seek(key); + if (iter->Valid() && iter->key() == Slice(key)) { + ReadFilter(iter->value()); + } + delete iter; + delete meta; +} + +void Table::ReadFilter(const Slice& filter_handle_value) { + Slice v = filter_handle_value; + BlockHandle filter_handle; + if (!filter_handle.DecodeFrom(&v).ok()) { + return; + } + + // We might want to unify with ReadBlock() if we start + // requiring checksum verification in Table::Open. + ReadOptions opt; + BlockContents block; + if (!ReadBlock(rep_->file.get(), opt, filter_handle, &block).ok()) { + return; + } + if (block.heap_allocated) { + rep_->filter_data = block.data.data(); // Will need to delete later + } + rep_->filter = new FilterBlockReader(rep_->options.filter_policy, block.data); +} + +Table::~Table() { + delete rep_; +} + +static void DeleteBlock(void* arg, void* ignored) { + delete reinterpret_cast(arg); +} + +static void DeleteCachedBlock(const Slice& key, void* value) { + Block* block = reinterpret_cast(value); + delete block; +} + +static void ReleaseBlock(void* arg, void* h) { + Cache* cache = reinterpret_cast(arg); + Cache::Handle* handle = reinterpret_cast(h); + cache->Release(handle); +} + +// Convert an index iterator value (i.e., an encoded BlockHandle) +// into an iterator over the contents of the corresponding block. +Iterator* Table::BlockReader(void* arg, + const ReadOptions& options, + const Slice& index_value, + bool* didIO) { + Table* table = reinterpret_cast(arg); + Cache* block_cache = table->rep_->options.block_cache.get(); + Statistics* const statistics = table->rep_->options.statistics; + Block* block = nullptr; + Cache::Handle* cache_handle = nullptr; + + BlockHandle handle; + Slice input = index_value; + Status s = handle.DecodeFrom(&input); + // We intentionally allow extra stuff in index_value so that we + // can add more features in the future. + + if (s.ok()) { + BlockContents contents; + if (block_cache != nullptr) { + char cache_key[kMaxCacheKeyPrefixSize + kMaxVarint64Length]; + const size_t cache_key_prefix_size = table->rep_->cache_key_prefix_size; + assert(cache_key_prefix_size != 0); + assert(cache_key_prefix_size <= kMaxCacheKeyPrefixSize); + memcpy(cache_key, table->rep_->cache_key_prefix, + cache_key_prefix_size); + char* end = EncodeVarint64(cache_key + cache_key_prefix_size, + handle.offset()); + Slice key(cache_key, static_cast(end-cache_key)); + cache_handle = block_cache->Lookup(key); + if (cache_handle != nullptr) { + block = reinterpret_cast(block_cache->Value(cache_handle)); + + RecordTick(statistics, BLOCK_CACHE_HIT); + } else { + s = ReadBlock(table->rep_->file.get(), options, handle, &contents); + if (s.ok()) { + block = new Block(contents); + if (contents.cachable && options.fill_cache) { + cache_handle = block_cache->Insert( + key, block, block->size(), &DeleteCachedBlock); + } + } + if (didIO != nullptr) { + *didIO = true; // we did some io from storage + } + + RecordTick(statistics, BLOCK_CACHE_MISS); + } + } else { + s = ReadBlock(table->rep_->file.get(), options, handle, &contents); + if (s.ok()) { + block = new Block(contents); + } + if (didIO != nullptr) { + *didIO = true; // we did some io from storage + } + } + } + + Iterator* iter; + if (block != nullptr) { + iter = block->NewIterator(table->rep_->options.comparator); + if (cache_handle == nullptr) { + iter->RegisterCleanup(&DeleteBlock, block, nullptr); + } else { + iter->RegisterCleanup(&ReleaseBlock, block_cache, cache_handle); + } + } else { + iter = NewErrorIterator(s); + } + return iter; +} + +Iterator* Table::BlockReader(void* arg, + const ReadOptions& options, + const Slice& index_value) { + return BlockReader(arg, options, index_value, nullptr); +} + +Iterator* Table::NewIterator(const ReadOptions& options) const { + return NewTwoLevelIterator( + rep_->index_block->NewIterator(rep_->options.comparator), + &Table::BlockReader, const_cast(this), options); +} + +Status Table::InternalGet(const ReadOptions& options, const Slice& k, + void* arg, + void (*saver)(void*, const Slice&, const Slice&, bool)) { + Status s; + Iterator* iiter = rep_->index_block->NewIterator(rep_->options.comparator); + iiter->Seek(k); + if (iiter->Valid()) { + Slice handle_value = iiter->value(); + FilterBlockReader* filter = rep_->filter; + BlockHandle handle; + if (filter != nullptr && + handle.DecodeFrom(&handle_value).ok() && + !filter->KeyMayMatch(handle.offset(), k)) { + // Not found + RecordTick(rep_->options.statistics, BLOOM_FILTER_USEFUL); + } else { + bool didIO = false; + Iterator* block_iter = BlockReader(this, options, iiter->value(), + &didIO); + block_iter->Seek(k); + if (block_iter->Valid()) { + (*saver)(arg, block_iter->key(), block_iter->value(), didIO); + } + s = block_iter->status(); + delete block_iter; + } + } + if (s.ok()) { + s = iiter->status(); + } + delete iiter; + return s; +} + +void SaveDidIO(void* arg, const Slice& key, const Slice& value, bool didIO) { + *reinterpret_cast(arg) = didIO; +} +bool Table::TEST_KeyInCache(const ReadOptions& options, const Slice& key) { + // We use InternalGet() as it has logic that checks whether we read the + // block from the disk or not. + bool didIO = false; + Status s = InternalGet(options, key, &didIO, SaveDidIO); + assert(s.ok()); + return !didIO; +} + +uint64_t Table::ApproximateOffsetOf(const Slice& key) const { + Iterator* index_iter = + rep_->index_block->NewIterator(rep_->options.comparator); + index_iter->Seek(key); + uint64_t result; + if (index_iter->Valid()) { + BlockHandle handle; + Slice input = index_iter->value(); + Status s = handle.DecodeFrom(&input); + if (s.ok()) { + result = handle.offset(); + } else { + // Strange: we can't decode the block handle in the index block. + // We'll just return the offset of the metaindex block, which is + // close to the whole file size for this case. + result = rep_->metaindex_handle.offset(); + } + } else { + // key is past the last key in the file. Approximate the offset + // by returning the offset of the metaindex block (which is + // right near the end of the file). + result = rep_->metaindex_handle.offset(); + } + delete index_iter; + return result; +} + +} // namespace leveldb diff --git a/table/table_builder.cc b/table/table_builder.cc new file mode 100644 index 00000000..77f14545 --- /dev/null +++ b/table/table_builder.cc @@ -0,0 +1,314 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/table_builder.h" + +#include +#include "leveldb/comparator.h" +#include "leveldb/env.h" +#include "leveldb/filter_policy.h" +#include "leveldb/options.h" +#include "table/block_builder.h" +#include "table/filter_block.h" +#include "table/format.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { + +struct TableBuilder::Rep { + Options options; + Options index_block_options; + WritableFile* file; + uint64_t offset; + Status status; + BlockBuilder data_block; + BlockBuilder index_block; + std::string last_key; + int64_t num_entries; + bool closed; // Either Finish() or Abandon() has been called. + FilterBlockBuilder* filter_block; + + // We do not emit the index entry for a block until we have seen the + // first key for the next data block. This allows us to use shorter + // keys in the index block. For example, consider a block boundary + // between the keys "the quick brown fox" and "the who". We can use + // "the r" as the key for the index block entry since it is >= all + // entries in the first block and < all entries in subsequent + // blocks. + // + // Invariant: r->pending_index_entry is true only if data_block is empty. + bool pending_index_entry; + BlockHandle pending_handle; // Handle to add to index block + + std::string compressed_output; + + Rep(const Options& opt, WritableFile* f) + : options(opt), + index_block_options(opt), + file(f), + offset(0), + data_block(&options), + index_block(&index_block_options), + num_entries(0), + closed(false), + filter_block(opt.filter_policy == nullptr ? nullptr + : new FilterBlockBuilder(opt.filter_policy)), + pending_index_entry(false) { + index_block_options.block_restart_interval = 1; + } +}; + +TableBuilder::TableBuilder(const Options& options, WritableFile* file, + int level) + : rep_(new Rep(options, file)), level_(level) { + if (rep_->filter_block != nullptr) { + rep_->filter_block->StartBlock(0); + } +} + +TableBuilder::~TableBuilder() { + assert(rep_->closed); // Catch errors where caller forgot to call Finish() + delete rep_->filter_block; + delete rep_; +} + +Status TableBuilder::ChangeOptions(const Options& options) { + // Note: if more fields are added to Options, update + // this function to catch changes that should not be allowed to + // change in the middle of building a Table. + if (options.comparator != rep_->options.comparator) { + return Status::InvalidArgument("changing comparator while building table"); + } + + // Note that any live BlockBuilders point to rep_->options and therefore + // will automatically pick up the updated options. + rep_->options = options; + rep_->index_block_options = options; + rep_->index_block_options.block_restart_interval = 1; + return Status::OK(); +} + +void TableBuilder::Add(const Slice& key, const Slice& value) { + Rep* r = rep_; + assert(!r->closed); + if (!ok()) return; + if (r->num_entries > 0) { + assert(r->options.comparator->Compare(key, Slice(r->last_key)) > 0); + } + + if (r->pending_index_entry) { + assert(r->data_block.empty()); + r->options.comparator->FindShortestSeparator(&r->last_key, key); + std::string handle_encoding; + r->pending_handle.EncodeTo(&handle_encoding); + r->index_block.Add(r->last_key, Slice(handle_encoding)); + r->pending_index_entry = false; + } + + if (r->filter_block != nullptr) { + r->filter_block->AddKey(key); + } + + r->last_key.assign(key.data(), key.size()); + r->num_entries++; + r->data_block.Add(key, value); + + const size_t estimated_block_size = r->data_block.CurrentSizeEstimate(); + if (estimated_block_size >= r->options.block_size) { + Flush(); + } +} + +void TableBuilder::Flush() { + Rep* r = rep_; + assert(!r->closed); + if (!ok()) return; + if (r->data_block.empty()) return; + assert(!r->pending_index_entry); + WriteBlock(&r->data_block, &r->pending_handle); + if (ok()) { + r->pending_index_entry = true; + r->status = r->file->Flush(); + } + if (r->filter_block != nullptr) { + r->filter_block->StartBlock(r->offset); + } +} + +static bool GoodCompressionRatio(size_t compressed_size, size_t raw_size) { + // Check to see if compressed less than 12.5% + return compressed_size < raw_size - (raw_size / 8u); +} + +void TableBuilder::WriteBlock(BlockBuilder* block, BlockHandle* handle) { + // File format contains a sequence of blocks where each block has: + // block_data: uint8[n] + // type: uint8 + // crc: uint32 + assert(ok()); + Rep* r = rep_; + Slice raw = block->Finish(); + + Slice block_contents; + std::string* compressed = &r->compressed_output; + CompressionType type; + // If the use has specified a different compression level for each level, + // then pick the compresison for that level. + if (!r->options.compression_per_level.empty()) { + const int n = r->options.compression_per_level.size(); + // It is possible for level_ to be -1; in that case, we use level + // 0's compression. This occurs mostly in backwards compatibility + // situations when the builder doesn't know what level the file + // belongs to. Likewise, if level_ is beyond the end of the + // specified compression levels, use the last value. + type = r->options.compression_per_level[std::max(0, std::min(level_, n))]; + } else { + type = r->options.compression; + } + switch (type) { + case kNoCompression: + block_contents = raw; + break; + + case kSnappyCompression: { + std::string* compressed = &r->compressed_output; + if (port::Snappy_Compress(r->options.compression_opts, raw.data(), + raw.size(), compressed) && + GoodCompressionRatio(compressed->size(), raw.size())) { + block_contents = *compressed; + } else { + // Snappy not supported, or not good compression ratio, so just + // store uncompressed form + block_contents = raw; + type = kNoCompression; + } + break; + } + case kZlibCompression: + if (port::Zlib_Compress(r->options.compression_opts, raw.data(), + raw.size(), compressed) && + GoodCompressionRatio(compressed->size(), raw.size())) { + block_contents = *compressed; + } else { + // Zlib not supported, or not good compression ratio, so just + // store uncompressed form + block_contents = raw; + type = kNoCompression; + } + break; + case kBZip2Compression: + if (port::BZip2_Compress(r->options.compression_opts, raw.data(), + raw.size(), compressed) && + GoodCompressionRatio(compressed->size(), raw.size())) { + block_contents = *compressed; + } else { + // BZip not supported, or not good compression ratio, so just + // store uncompressed form + block_contents = raw; + type = kNoCompression; + } + break; + } + WriteRawBlock(block_contents, type, handle); + r->compressed_output.clear(); + block->Reset(); +} + +void TableBuilder::WriteRawBlock(const Slice& block_contents, + CompressionType type, + BlockHandle* handle) { + Rep* r = rep_; + handle->set_offset(r->offset); + handle->set_size(block_contents.size()); + r->status = r->file->Append(block_contents); + if (r->status.ok()) { + char trailer[kBlockTrailerSize]; + trailer[0] = type; + uint32_t crc = crc32c::Value(block_contents.data(), block_contents.size()); + crc = crc32c::Extend(crc, trailer, 1); // Extend crc to cover block type + EncodeFixed32(trailer+1, crc32c::Mask(crc)); + r->status = r->file->Append(Slice(trailer, kBlockTrailerSize)); + if (r->status.ok()) { + r->offset += block_contents.size() + kBlockTrailerSize; + } + } +} + +Status TableBuilder::status() const { + return rep_->status; +} + +Status TableBuilder::Finish() { + Rep* r = rep_; + Flush(); + assert(!r->closed); + r->closed = true; + + BlockHandle filter_block_handle, metaindex_block_handle, index_block_handle; + + // Write filter block + if (ok() && r->filter_block != nullptr) { + WriteRawBlock(r->filter_block->Finish(), kNoCompression, + &filter_block_handle); + } + + // Write metaindex block + if (ok()) { + BlockBuilder meta_index_block(&r->options); + if (r->filter_block != nullptr) { + // Add mapping from "filter.Name" to location of filter data + std::string key = "filter."; + key.append(r->options.filter_policy->Name()); + std::string handle_encoding; + filter_block_handle.EncodeTo(&handle_encoding); + meta_index_block.Add(key, handle_encoding); + } + + // TODO(postrelease): Add stats and other meta blocks + WriteBlock(&meta_index_block, &metaindex_block_handle); + } + + // Write index block + if (ok()) { + if (r->pending_index_entry) { + r->options.comparator->FindShortSuccessor(&r->last_key); + std::string handle_encoding; + r->pending_handle.EncodeTo(&handle_encoding); + r->index_block.Add(r->last_key, Slice(handle_encoding)); + r->pending_index_entry = false; + } + WriteBlock(&r->index_block, &index_block_handle); + } + + // Write footer + if (ok()) { + Footer footer; + footer.set_metaindex_handle(metaindex_block_handle); + footer.set_index_handle(index_block_handle); + std::string footer_encoding; + footer.EncodeTo(&footer_encoding); + r->status = r->file->Append(footer_encoding); + if (r->status.ok()) { + r->offset += footer_encoding.size(); + } + } + return r->status; +} + +void TableBuilder::Abandon() { + Rep* r = rep_; + assert(!r->closed); + r->closed = true; +} + +uint64_t TableBuilder::NumEntries() const { + return rep_->num_entries; +} + +uint64_t TableBuilder::FileSize() const { + return rep_->offset; +} + +} // namespace leveldb diff --git a/table/table_test.cc b/table/table_test.cc new file mode 100644 index 00000000..4daf7837 --- /dev/null +++ b/table/table_test.cc @@ -0,0 +1,964 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/table.h" + +#include +#include +#include "db/dbformat.h" +#include "db/memtable.h" +#include "db/write_batch_internal.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "leveldb/table_builder.h" +#include "table/block.h" +#include "table/block_builder.h" +#include "table/format.h" +#include "util/random.h" +#include "util/testharness.h" +#include "util/testutil.h" + +namespace leveldb { + +// Return reverse of "key". +// Used to test non-lexicographic comparators. +static std::string Reverse(const Slice& key) { + std::string str(key.ToString()); + std::string rev(""); + for (std::string::reverse_iterator rit = str.rbegin(); + rit != str.rend(); ++rit) { + rev.push_back(*rit); + } + return rev; +} + +namespace { +class ReverseKeyComparator : public Comparator { + public: + virtual const char* Name() const { + return "leveldb.ReverseBytewiseComparator"; + } + + virtual int Compare(const Slice& a, const Slice& b) const { + return BytewiseComparator()->Compare(Reverse(a), Reverse(b)); + } + + virtual void FindShortestSeparator( + std::string* start, + const Slice& limit) const { + std::string s = Reverse(*start); + std::string l = Reverse(limit); + BytewiseComparator()->FindShortestSeparator(&s, l); + *start = Reverse(s); + } + + virtual void FindShortSuccessor(std::string* key) const { + std::string s = Reverse(*key); + BytewiseComparator()->FindShortSuccessor(&s); + *key = Reverse(s); + } +}; +} // namespace +static ReverseKeyComparator reverse_key_comparator; + +static void Increment(const Comparator* cmp, std::string* key) { + if (cmp == BytewiseComparator()) { + key->push_back('\0'); + } else { + assert(cmp == &reverse_key_comparator); + std::string rev = Reverse(*key); + rev.push_back('\0'); + *key = Reverse(rev); + } +} + +// An STL comparator that uses a Comparator +namespace anon { +struct STLLessThan { + const Comparator* cmp; + + STLLessThan() : cmp(BytewiseComparator()) { } + explicit STLLessThan(const Comparator* c) : cmp(c) { } + bool operator()(const std::string& a, const std::string& b) const { + return cmp->Compare(Slice(a), Slice(b)) < 0; + } +}; +} // namespace + +class StringSink: public WritableFile { + public: + ~StringSink() { } + + const std::string& contents() const { return contents_; } + + virtual Status Close() { return Status::OK(); } + virtual Status Flush() { return Status::OK(); } + virtual Status Sync() { return Status::OK(); } + + virtual Status Append(const Slice& data) { + contents_.append(data.data(), data.size()); + return Status::OK(); + } + + private: + std::string contents_; +}; + + +class StringSource: public RandomAccessFile { + public: + StringSource(const Slice& contents, uint64_t uniq_id) + : contents_(contents.data(), contents.size()), uniq_id_(uniq_id) { + } + + virtual ~StringSource() { } + + uint64_t Size() const { return contents_.size(); } + + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const { + if (offset > contents_.size()) { + return Status::InvalidArgument("invalid Read offset"); + } + if (offset + n > contents_.size()) { + n = contents_.size() - offset; + } + memcpy(scratch, &contents_[offset], n); + *result = Slice(scratch, n); + return Status::OK(); + } + + virtual size_t GetUniqueId(char* id, size_t max_size) const { + if (max_size < 20) { + return 0; + } + + char* rid = id; + rid = EncodeVarint64(rid, uniq_id_); + rid = EncodeVarint64(rid, 0); + return static_cast(rid-id); + } + + private: + std::string contents_; + uint64_t uniq_id_; +}; + +typedef std::map KVMap; + +// Helper class for tests to unify the interface between +// BlockBuilder/TableBuilder and Block/Table. +class Constructor { + public: + explicit Constructor(const Comparator* cmp) : data_(anon::STLLessThan(cmp)) { } + virtual ~Constructor() { } + + void Add(const std::string& key, const Slice& value) { + data_[key] = value.ToString(); + } + + // Finish constructing the data structure with all the keys that have + // been added so far. Returns the keys in sorted order in "*keys" + // and stores the key/value pairs in "*kvmap" + void Finish(const Options& options, + std::vector* keys, + KVMap* kvmap) { + *kvmap = data_; + keys->clear(); + for (KVMap::const_iterator it = data_.begin(); + it != data_.end(); + ++it) { + keys->push_back(it->first); + } + data_.clear(); + Status s = FinishImpl(options, *kvmap); + ASSERT_TRUE(s.ok()) << s.ToString(); + } + + // Construct the data structure from the data in "data" + virtual Status FinishImpl(const Options& options, const KVMap& data) = 0; + + virtual Iterator* NewIterator() const = 0; + + virtual const KVMap& data() { return data_; } + + virtual DB* db() const { return nullptr; } // Overridden in DBConstructor + + private: + KVMap data_; +}; + +class BlockConstructor: public Constructor { + public: + explicit BlockConstructor(const Comparator* cmp) + : Constructor(cmp), + comparator_(cmp), + block_(nullptr) { } + ~BlockConstructor() { + delete block_; + } + virtual Status FinishImpl(const Options& options, const KVMap& data) { + delete block_; + block_ = nullptr; + BlockBuilder builder(&options); + + for (KVMap::const_iterator it = data.begin(); + it != data.end(); + ++it) { + builder.Add(it->first, it->second); + } + // Open the block + data_ = builder.Finish().ToString(); + BlockContents contents; + contents.data = data_; + contents.cachable = false; + contents.heap_allocated = false; + block_ = new Block(contents); + return Status::OK(); + } + virtual Iterator* NewIterator() const { + return block_->NewIterator(comparator_); + } + + private: + const Comparator* comparator_; + std::string data_; + Block* block_; + + BlockConstructor(); +}; + +class TableConstructor: public Constructor { + public: + explicit TableConstructor(const Comparator* cmp) + : Constructor(cmp) { + } + ~TableConstructor() { + Reset(); + } + virtual Status FinishImpl(const Options& options, const KVMap& data) { + Reset(); + sink_.reset(new StringSink()); + TableBuilder builder(options, sink_.get()); + + for (KVMap::const_iterator it = data.begin(); + it != data.end(); + ++it) { + builder.Add(it->first, it->second); + ASSERT_TRUE(builder.status().ok()); + } + Status s = builder.Finish(); + ASSERT_TRUE(s.ok()) << s.ToString(); + + ASSERT_EQ(sink_->contents().size(), builder.FileSize()); + + // Open the table + uniq_id_ = cur_uniq_id_++; + source_.reset(new StringSource(sink_->contents(), uniq_id_)); + return Table::Open(options, std::move(source_), + sink_->contents().size(), &table_); + } + + virtual Iterator* NewIterator() const { + return table_->NewIterator(ReadOptions()); + } + + uint64_t ApproximateOffsetOf(const Slice& key) const { + return table_->ApproximateOffsetOf(key); + } + + virtual Status Reopen(const Options& options) { + source_.reset(new StringSource(sink_->contents(), uniq_id_)); + return Table::Open(options, std::move(source_), + sink_->contents().size(), &table_); + } + + virtual Table* table() { + return table_.get(); + } + + private: + void Reset() { + uniq_id_ = 0; + table_.reset(); + sink_.reset(); + source_.reset(); + } + + uint64_t uniq_id_; + unique_ptr sink_; + unique_ptr source_; + unique_ptr
table_; + + TableConstructor(); + + static uint64_t cur_uniq_id_; +}; +uint64_t TableConstructor::cur_uniq_id_ = 1; + +// A helper class that converts internal format keys into user keys +class KeyConvertingIterator: public Iterator { + public: + explicit KeyConvertingIterator(Iterator* iter) : iter_(iter) { } + virtual ~KeyConvertingIterator() { delete iter_; } + virtual bool Valid() const { return iter_->Valid(); } + virtual void Seek(const Slice& target) { + ParsedInternalKey ikey(target, kMaxSequenceNumber, kTypeValue); + std::string encoded; + AppendInternalKey(&encoded, ikey); + iter_->Seek(encoded); + } + virtual void SeekToFirst() { iter_->SeekToFirst(); } + virtual void SeekToLast() { iter_->SeekToLast(); } + virtual void Next() { iter_->Next(); } + virtual void Prev() { iter_->Prev(); } + + virtual Slice key() const { + assert(Valid()); + ParsedInternalKey key; + if (!ParseInternalKey(iter_->key(), &key)) { + status_ = Status::Corruption("malformed internal key"); + return Slice("corrupted key"); + } + return key.user_key; + } + + virtual Slice value() const { return iter_->value(); } + virtual Status status() const { + return status_.ok() ? iter_->status() : status_; + } + + private: + mutable Status status_; + Iterator* iter_; + + // No copying allowed + KeyConvertingIterator(const KeyConvertingIterator&); + void operator=(const KeyConvertingIterator&); +}; + +class MemTableConstructor: public Constructor { + public: + explicit MemTableConstructor(const Comparator* cmp) + : Constructor(cmp), + internal_comparator_(cmp) { + memtable_ = new MemTable(internal_comparator_); + memtable_->Ref(); + } + ~MemTableConstructor() { + memtable_->Unref(); + } + virtual Status FinishImpl(const Options& options, const KVMap& data) { + memtable_->Unref(); + memtable_ = new MemTable(internal_comparator_); + memtable_->Ref(); + int seq = 1; + for (KVMap::const_iterator it = data.begin(); + it != data.end(); + ++it) { + memtable_->Add(seq, kTypeValue, it->first, it->second); + seq++; + } + return Status::OK(); + } + virtual Iterator* NewIterator() const { + return new KeyConvertingIterator(memtable_->NewIterator()); + } + + private: + InternalKeyComparator internal_comparator_; + MemTable* memtable_; +}; + +class DBConstructor: public Constructor { + public: + explicit DBConstructor(const Comparator* cmp) + : Constructor(cmp), + comparator_(cmp) { + db_ = nullptr; + NewDB(); + } + ~DBConstructor() { + delete db_; + } + virtual Status FinishImpl(const Options& options, const KVMap& data) { + delete db_; + db_ = nullptr; + NewDB(); + for (KVMap::const_iterator it = data.begin(); + it != data.end(); + ++it) { + WriteBatch batch; + batch.Put(it->first, it->second); + ASSERT_TRUE(db_->Write(WriteOptions(), &batch).ok()); + } + return Status::OK(); + } + virtual Iterator* NewIterator() const { + return db_->NewIterator(ReadOptions()); + } + + virtual DB* db() const { return db_; } + + private: + void NewDB() { + std::string name = test::TmpDir() + "/table_testdb"; + + Options options; + options.comparator = comparator_; + Status status = DestroyDB(name, options); + ASSERT_TRUE(status.ok()) << status.ToString(); + + options.create_if_missing = true; + options.error_if_exists = true; + options.write_buffer_size = 10000; // Something small to force merging + status = DB::Open(options, name, &db_); + ASSERT_TRUE(status.ok()) << status.ToString(); + } + + const Comparator* comparator_; + DB* db_; +}; + +static bool SnappyCompressionSupported() { + std::string out; + Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + return port::Snappy_Compress(Options().compression_opts, in.data(), in.size(), + &out); +} + +static bool ZlibCompressionSupported() { + std::string out; + Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + return port::Zlib_Compress(Options().compression_opts, in.data(), in.size(), + &out); +} + +#ifdef BZIP2 +static bool BZip2CompressionSupported() { + std::string out; + Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + return port::BZip2_Compress(Options().compression_opts, in.data(), in.size(), + &out); +} +#endif + +enum TestType { + TABLE_TEST, + BLOCK_TEST, + MEMTABLE_TEST, + DB_TEST +}; + +struct TestArgs { + TestType type; + bool reverse_compare; + int restart_interval; + CompressionType compression; +}; + + +static std::vector Generate_Arg_List() +{ + std::vector ret; + TestType test_type[4] = {TABLE_TEST, BLOCK_TEST, MEMTABLE_TEST, DB_TEST}; + int test_type_len = 4; + bool reverse_compare[2] = {false, true}; + int reverse_compare_len = 2; + int restart_interval[3] = {16, 1, 1024}; + int restart_interval_len = 3; + + // Only add compression if it is supported + std::vector compression_types; + compression_types.push_back(kNoCompression); +#ifdef SNAPPY + if (SnappyCompressionSupported()) + compression_types.push_back(kSnappyCompression); +#endif + +#ifdef ZLIB + if (ZlibCompressionSupported()) + compression_types.push_back(kZlibCompression); +#endif + +#ifdef BZIP2 + if (BZip2CompressionSupported()) + compression_types.push_back(kBZip2Compression); +#endif + + for(int i =0; i < test_type_len; i++) + for (int j =0; j < reverse_compare_len; j++) + for (int k =0; k < restart_interval_len; k++) + for (unsigned int n =0; n < compression_types.size(); n++) { + TestArgs one_arg; + one_arg.type = test_type[i]; + one_arg.reverse_compare = reverse_compare[j]; + one_arg.restart_interval = restart_interval[k]; + one_arg.compression = compression_types[n]; + ret.push_back(one_arg); + } + + return ret; +} + +class Harness { + public: + Harness() : constructor_(nullptr) { } + + void Init(const TestArgs& args) { + delete constructor_; + constructor_ = nullptr; + options_ = Options(); + + options_.block_restart_interval = args.restart_interval; + options_.compression = args.compression; + // Use shorter block size for tests to exercise block boundary + // conditions more. + options_.block_size = 256; + if (args.reverse_compare) { + options_.comparator = &reverse_key_comparator; + } + switch (args.type) { + case TABLE_TEST: + constructor_ = new TableConstructor(options_.comparator); + break; + case BLOCK_TEST: + constructor_ = new BlockConstructor(options_.comparator); + break; + case MEMTABLE_TEST: + constructor_ = new MemTableConstructor(options_.comparator); + break; + case DB_TEST: + constructor_ = new DBConstructor(options_.comparator); + break; + } + } + + ~Harness() { + delete constructor_; + } + + void Add(const std::string& key, const std::string& value) { + constructor_->Add(key, value); + } + + void Test(Random* rnd) { + std::vector keys; + KVMap data; + constructor_->Finish(options_, &keys, &data); + + TestForwardScan(keys, data); + TestBackwardScan(keys, data); + TestRandomAccess(rnd, keys, data); + } + + void TestForwardScan(const std::vector& keys, + const KVMap& data) { + Iterator* iter = constructor_->NewIterator(); + ASSERT_TRUE(!iter->Valid()); + iter->SeekToFirst(); + for (KVMap::const_iterator model_iter = data.begin(); + model_iter != data.end(); + ++model_iter) { + ASSERT_EQ(ToString(data, model_iter), ToString(iter)); + iter->Next(); + } + ASSERT_TRUE(!iter->Valid()); + delete iter; + } + + void TestBackwardScan(const std::vector& keys, + const KVMap& data) { + Iterator* iter = constructor_->NewIterator(); + ASSERT_TRUE(!iter->Valid()); + iter->SeekToLast(); + for (KVMap::const_reverse_iterator model_iter = data.rbegin(); + model_iter != data.rend(); + ++model_iter) { + ASSERT_EQ(ToString(data, model_iter), ToString(iter)); + iter->Prev(); + } + ASSERT_TRUE(!iter->Valid()); + delete iter; + } + + void TestRandomAccess(Random* rnd, + const std::vector& keys, + const KVMap& data) { + static const bool kVerbose = false; + Iterator* iter = constructor_->NewIterator(); + ASSERT_TRUE(!iter->Valid()); + KVMap::const_iterator model_iter = data.begin(); + if (kVerbose) fprintf(stderr, "---\n"); + for (int i = 0; i < 200; i++) { + const int toss = rnd->Uniform(5); + switch (toss) { + case 0: { + if (iter->Valid()) { + if (kVerbose) fprintf(stderr, "Next\n"); + iter->Next(); + ++model_iter; + ASSERT_EQ(ToString(data, model_iter), ToString(iter)); + } + break; + } + + case 1: { + if (kVerbose) fprintf(stderr, "SeekToFirst\n"); + iter->SeekToFirst(); + model_iter = data.begin(); + ASSERT_EQ(ToString(data, model_iter), ToString(iter)); + break; + } + + case 2: { + std::string key = PickRandomKey(rnd, keys); + model_iter = data.lower_bound(key); + if (kVerbose) fprintf(stderr, "Seek '%s'\n", + EscapeString(key).c_str()); + iter->Seek(Slice(key)); + ASSERT_EQ(ToString(data, model_iter), ToString(iter)); + break; + } + + case 3: { + if (iter->Valid()) { + if (kVerbose) fprintf(stderr, "Prev\n"); + iter->Prev(); + if (model_iter == data.begin()) { + model_iter = data.end(); // Wrap around to invalid value + } else { + --model_iter; + } + ASSERT_EQ(ToString(data, model_iter), ToString(iter)); + } + break; + } + + case 4: { + if (kVerbose) fprintf(stderr, "SeekToLast\n"); + iter->SeekToLast(); + if (keys.empty()) { + model_iter = data.end(); + } else { + std::string last = data.rbegin()->first; + model_iter = data.lower_bound(last); + } + ASSERT_EQ(ToString(data, model_iter), ToString(iter)); + break; + } + } + } + delete iter; + } + + std::string ToString(const KVMap& data, const KVMap::const_iterator& it) { + if (it == data.end()) { + return "END"; + } else { + return "'" + it->first + "->" + it->second + "'"; + } + } + + std::string ToString(const KVMap& data, + const KVMap::const_reverse_iterator& it) { + if (it == data.rend()) { + return "END"; + } else { + return "'" + it->first + "->" + it->second + "'"; + } + } + + std::string ToString(const Iterator* it) { + if (!it->Valid()) { + return "END"; + } else { + return "'" + it->key().ToString() + "->" + it->value().ToString() + "'"; + } + } + + std::string PickRandomKey(Random* rnd, const std::vector& keys) { + if (keys.empty()) { + return "foo"; + } else { + const int index = rnd->Uniform(keys.size()); + std::string result = keys[index]; + switch (rnd->Uniform(3)) { + case 0: + // Return an existing key + break; + case 1: { + // Attempt to return something smaller than an existing key + if (result.size() > 0 && result[result.size()-1] > '\0') { + result[result.size()-1]--; + } + break; + } + case 2: { + // Return something larger than an existing key + Increment(options_.comparator, &result); + break; + } + } + return result; + } + } + + // Returns nullptr if not running against a DB + DB* db() const { return constructor_->db(); } + + private: + Options options_; + Constructor* constructor_; +}; + +// Test the empty key +TEST(Harness, SimpleEmptyKey) { + std::vector args = Generate_Arg_List(); + for (unsigned int i = 0; i < args.size(); i++) { + Init(args[i]); + Random rnd(test::RandomSeed() + 1); + Add("", "v"); + Test(&rnd); + } +} + +TEST(Harness, SimpleSingle) { + std::vector args = Generate_Arg_List(); + for (unsigned int i = 0; i < args.size(); i++) { + Init(args[i]); + Random rnd(test::RandomSeed() + 2); + Add("abc", "v"); + Test(&rnd); + } +} + +TEST(Harness, SimpleMulti) { + std::vector args = Generate_Arg_List(); + for (unsigned int i = 0; i < args.size(); i++) { + Init(args[i]); + Random rnd(test::RandomSeed() + 3); + Add("abc", "v"); + Add("abcd", "v"); + Add("ac", "v2"); + Test(&rnd); + } +} + +TEST(Harness, SimpleSpecialKey) { + std::vector args = Generate_Arg_List(); + for (unsigned int i = 0; i < args.size(); i++) { + Init(args[i]); + Random rnd(test::RandomSeed() + 4); + Add("\xff\xff", "v3"); + Test(&rnd); + } +} + +TEST(Harness, Randomized) { + std::vector args = Generate_Arg_List(); + for (unsigned int i = 0; i < args.size(); i++) { + Init(args[i]); + Random rnd(test::RandomSeed() + 5); + for (int num_entries = 0; num_entries < 2000; + num_entries += (num_entries < 50 ? 1 : 200)) { + if ((num_entries % 10) == 0) { + fprintf(stderr, "case %d of %d: num_entries = %d\n", + (i + 1), int(args.size()), num_entries); + } + for (int e = 0; e < num_entries; e++) { + std::string v; + Add(test::RandomKey(&rnd, rnd.Skewed(4)), + test::RandomString(&rnd, rnd.Skewed(5), &v).ToString()); + } + Test(&rnd); + } + } +} + +TEST(Harness, RandomizedLongDB) { + Random rnd(test::RandomSeed()); + TestArgs args = { DB_TEST, false, 16, kNoCompression }; + Init(args); + int num_entries = 100000; + for (int e = 0; e < num_entries; e++) { + std::string v; + Add(test::RandomKey(&rnd, rnd.Skewed(4)), + test::RandomString(&rnd, rnd.Skewed(5), &v).ToString()); + } + Test(&rnd); + + // We must have created enough data to force merging + int files = 0; + for (int level = 0; level < db()->NumberLevels(); level++) { + std::string value; + char name[100]; + snprintf(name, sizeof(name), "leveldb.num-files-at-level%d", level); + ASSERT_TRUE(db()->GetProperty(name, &value)); + files += atoi(value.c_str()); + } + ASSERT_GT(files, 0); +} + +class MemTableTest { }; + +TEST(MemTableTest, Simple) { + InternalKeyComparator cmp(BytewiseComparator()); + MemTable* memtable = new MemTable(cmp); + memtable->Ref(); + WriteBatch batch; + WriteBatchInternal::SetSequence(&batch, 100); + batch.Put(std::string("k1"), std::string("v1")); + batch.Put(std::string("k2"), std::string("v2")); + batch.Put(std::string("k3"), std::string("v3")); + batch.Put(std::string("largekey"), std::string("vlarge")); + ASSERT_TRUE(WriteBatchInternal::InsertInto(&batch, memtable).ok()); + + Iterator* iter = memtable->NewIterator(); + iter->SeekToFirst(); + while (iter->Valid()) { + fprintf(stderr, "key: '%s' -> '%s'\n", + iter->key().ToString().c_str(), + iter->value().ToString().c_str()); + iter->Next(); + } + + delete iter; + memtable->Unref(); +} + +static bool Between(uint64_t val, uint64_t low, uint64_t high) { + bool result = (val >= low) && (val <= high); + if (!result) { + fprintf(stderr, "Value %llu is not in range [%llu, %llu]\n", + (unsigned long long)(val), + (unsigned long long)(low), + (unsigned long long)(high)); + } + return result; +} + +class TableTest { }; + +TEST(TableTest, ApproximateOffsetOfPlain) { + TableConstructor c(BytewiseComparator()); + c.Add("k01", "hello"); + c.Add("k02", "hello2"); + c.Add("k03", std::string(10000, 'x')); + c.Add("k04", std::string(200000, 'x')); + c.Add("k05", std::string(300000, 'x')); + c.Add("k06", "hello3"); + c.Add("k07", std::string(100000, 'x')); + std::vector keys; + KVMap kvmap; + Options options; + options.block_size = 1024; + options.compression = kNoCompression; + c.Finish(options, &keys, &kvmap); + + ASSERT_TRUE(Between(c.ApproximateOffsetOf("abc"), 0, 0)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01"), 0, 0)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01a"), 0, 0)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k02"), 0, 0)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k03"), 0, 0)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04"), 10000, 11000)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04a"), 210000, 211000)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k05"), 210000, 211000)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k06"), 510000, 511000)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k07"), 510000, 511000)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("xyz"), 610000, 612000)); + +} + +static void Do_Compression_Test(CompressionType comp) { + Random rnd(301); + TableConstructor c(BytewiseComparator()); + std::string tmp; + c.Add("k01", "hello"); + c.Add("k02", test::CompressibleString(&rnd, 0.25, 10000, &tmp)); + c.Add("k03", "hello3"); + c.Add("k04", test::CompressibleString(&rnd, 0.25, 10000, &tmp)); + std::vector keys; + KVMap kvmap; + Options options; + options.block_size = 1024; + options.compression = comp; + c.Finish(options, &keys, &kvmap); + + ASSERT_TRUE(Between(c.ApproximateOffsetOf("abc"), 0, 0)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01"), 0, 0)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k02"), 0, 0)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k03"), 2000, 3000)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04"), 2000, 3000)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("xyz"), 4000, 6000)); +} + +TEST(TableTest, ApproximateOffsetOfCompressed) { + CompressionType compression_state[2]; + int valid = 0; + if (!SnappyCompressionSupported()) { + fprintf(stderr, "skipping snappy compression tests\n"); + } else { + compression_state[valid] = kSnappyCompression; + valid++; + } + + if (!ZlibCompressionSupported()) { + fprintf(stderr, "skipping zlib compression tests\n"); + } else { + compression_state[valid] = kZlibCompression; + valid++; + } + + for(int i =0; i < valid; i++) + { + Do_Compression_Test(compression_state[i]); + } + +} + +TEST(TableTest, BlockCacheLeak) { + // Check that when we reopen a table we don't lose access to blocks already + // in the cache. This test checks whether the Table actually makes use of the + // unique ID from the file. + + Options opt; + opt.block_size = 1024; + opt.compression = kNoCompression; + opt.block_cache = NewLRUCache(16*1024*1024); // big enough so we don't ever + // lose cached values. + + TableConstructor c(BytewiseComparator()); + c.Add("k01", "hello"); + c.Add("k02", "hello2"); + c.Add("k03", std::string(10000, 'x')); + c.Add("k04", std::string(200000, 'x')); + c.Add("k05", std::string(300000, 'x')); + c.Add("k06", "hello3"); + c.Add("k07", std::string(100000, 'x')); + std::vector keys; + KVMap kvmap; + c.Finish(opt, &keys, &kvmap); + + unique_ptr iter(c.NewIterator()); + iter->SeekToFirst(); + while (iter->Valid()) { + iter->key(); + iter->value(); + iter->Next(); + } + ASSERT_OK(iter->status()); + + ASSERT_OK(c.Reopen(opt)); + for (const std::string& key: keys) { + ASSERT_TRUE(c.table()->TEST_KeyInCache(ReadOptions(), key)); + } +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/table/two_level_iterator.cc b/table/two_level_iterator.cc new file mode 100644 index 00000000..e64ff7ca --- /dev/null +++ b/table/two_level_iterator.cc @@ -0,0 +1,183 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/two_level_iterator.h" + +#include "leveldb/table.h" +#include "table/block.h" +#include "table/format.h" +#include "table/iterator_wrapper.h" + +namespace leveldb { + +namespace { + +typedef Iterator* (*BlockFunction)(void*, const ReadOptions&, const Slice&); + +class TwoLevelIterator: public Iterator { + public: + TwoLevelIterator( + Iterator* index_iter, + BlockFunction block_function, + void* arg, + const ReadOptions& options); + + virtual ~TwoLevelIterator(); + + virtual void Seek(const Slice& target); + virtual void SeekToFirst(); + virtual void SeekToLast(); + virtual void Next(); + virtual void Prev(); + + virtual bool Valid() const { + return data_iter_.Valid(); + } + virtual Slice key() const { + assert(Valid()); + return data_iter_.key(); + } + virtual Slice value() const { + assert(Valid()); + return data_iter_.value(); + } + virtual Status status() const { + // It'd be nice if status() returned a const Status& instead of a Status + if (!index_iter_.status().ok()) { + return index_iter_.status(); + } else if (data_iter_.iter() != nullptr && !data_iter_.status().ok()) { + return data_iter_.status(); + } else { + return status_; + } + } + + private: + void SaveError(const Status& s) { + if (status_.ok() && !s.ok()) status_ = s; + } + void SkipEmptyDataBlocksForward(); + void SkipEmptyDataBlocksBackward(); + void SetDataIterator(Iterator* data_iter); + void InitDataBlock(); + + BlockFunction block_function_; + void* arg_; + const ReadOptions options_; + Status status_; + IteratorWrapper index_iter_; + IteratorWrapper data_iter_; // May be nullptr + // If data_iter_ is non-nullptr, then "data_block_handle_" holds the + // "index_value" passed to block_function_ to create the data_iter_. + std::string data_block_handle_; +}; + +TwoLevelIterator::TwoLevelIterator( + Iterator* index_iter, + BlockFunction block_function, + void* arg, + const ReadOptions& options) + : block_function_(block_function), + arg_(arg), + options_(options), + index_iter_(index_iter), + data_iter_(nullptr) { +} + +TwoLevelIterator::~TwoLevelIterator() { +} + +void TwoLevelIterator::Seek(const Slice& target) { + index_iter_.Seek(target); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.Seek(target); + SkipEmptyDataBlocksForward(); +} + +void TwoLevelIterator::SeekToFirst() { + index_iter_.SeekToFirst(); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.SeekToFirst(); + SkipEmptyDataBlocksForward(); +} + +void TwoLevelIterator::SeekToLast() { + index_iter_.SeekToLast(); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.SeekToLast(); + SkipEmptyDataBlocksBackward(); +} + +void TwoLevelIterator::Next() { + assert(Valid()); + data_iter_.Next(); + SkipEmptyDataBlocksForward(); +} + +void TwoLevelIterator::Prev() { + assert(Valid()); + data_iter_.Prev(); + SkipEmptyDataBlocksBackward(); +} + + +void TwoLevelIterator::SkipEmptyDataBlocksForward() { + while (data_iter_.iter() == nullptr || !data_iter_.Valid()) { + // Move to next block + if (!index_iter_.Valid()) { + SetDataIterator(nullptr); + return; + } + index_iter_.Next(); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.SeekToFirst(); + } +} + +void TwoLevelIterator::SkipEmptyDataBlocksBackward() { + while (data_iter_.iter() == nullptr || !data_iter_.Valid()) { + // Move to next block + if (!index_iter_.Valid()) { + SetDataIterator(nullptr); + return; + } + index_iter_.Prev(); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.SeekToLast(); + } +} + +void TwoLevelIterator::SetDataIterator(Iterator* data_iter) { + if (data_iter_.iter() != nullptr) SaveError(data_iter_.status()); + data_iter_.Set(data_iter); +} + +void TwoLevelIterator::InitDataBlock() { + if (!index_iter_.Valid()) { + SetDataIterator(nullptr); + } else { + Slice handle = index_iter_.value(); + if (data_iter_.iter() != nullptr + && handle.compare(data_block_handle_) == 0) { + // data_iter_ is already constructed with this iterator, so + // no need to change anything + } else { + Iterator* iter = (*block_function_)(arg_, options_, handle); + data_block_handle_.assign(handle.data(), handle.size()); + SetDataIterator(iter); + } + } +} + +} // namespace + +Iterator* NewTwoLevelIterator( + Iterator* index_iter, + BlockFunction block_function, + void* arg, + const ReadOptions& options) { + return new TwoLevelIterator(index_iter, block_function, arg, options); +} + +} // namespace leveldb diff --git a/table/two_level_iterator.h b/table/two_level_iterator.h new file mode 100644 index 00000000..629ca345 --- /dev/null +++ b/table/two_level_iterator.h @@ -0,0 +1,34 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_ +#define STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_ + +#include "leveldb/iterator.h" + +namespace leveldb { + +struct ReadOptions; + +// Return a new two level iterator. A two-level iterator contains an +// index iterator whose values point to a sequence of blocks where +// each block is itself a sequence of key,value pairs. The returned +// two-level iterator yields the concatenation of all key/value pairs +// in the sequence of blocks. Takes ownership of "index_iter" and +// will delete it when no longer needed. +// +// Uses a supplied function to convert an index_iter value into +// an iterator over the contents of the corresponding block. +extern Iterator* NewTwoLevelIterator( + Iterator* index_iter, + Iterator* (*block_function)( + void* arg, + const ReadOptions& options, + const Slice& index_value), + void* arg, + const ReadOptions& options); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_ diff --git a/thrift/README b/thrift/README new file mode 100644 index 00000000..f76c2bbf --- /dev/null +++ b/thrift/README @@ -0,0 +1,25 @@ +This directory has the thrift server code that exposes leveldb apis. + +The thrift api is specified in thrift/if/leveldb.thrift. + +The thrift header files are in ./thrift/lib. These are part of +Apache Thrift code base and are needed for compilation of the leveldb +thrift server. The thrift libraries are copied into ./thrift/libs. +If you want to use a different version of thrift, please update these +directories with the corresponding thrift header files and the +compiled thrift libraries. + +If you want to compile leveldb with thrift-server support, please set the following +enviroment variables appropriately: + USE_THRIFT=1 + LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./thrift/libs:./snappy/libs + make clean leveldb_server leveldb_server_test + +You can run the leveldb server unit tests by + ./leveldb_server_test + +You can regenerate the thrift cpp files by doing the following + +cd ./thrift +bin/thrift --gen cpp if/leveldb.thrift + diff --git a/thrift/assoc.h b/thrift/assoc.h new file mode 100644 index 00000000..af944bd1 --- /dev/null +++ b/thrift/assoc.h @@ -0,0 +1,806 @@ +/** +* Thrift server that supports operations on the +* Facebook TAO Graph database +* @author Dhruba Borthakur (dhruba@gmail.com) +* Copyright 2012 Facebook +*/ +#ifndef THRIFT_LEVELDB_ASSOC_SERVER_H_ +#define THRIFT_LEVELDB_ASSOC_SERVER_H_ + +#include +#include +#include "openhandles.h" +#include "server_options.h" + +#include "leveldb/db.h" +#include "leveldb/write_batch.h" +#include "util/testharness.h" +#include "port/port.h" +#include "util/mutexlock.h" +#include "util/murmurhash.h" + +using namespace apache::thrift; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; +using namespace apache::thrift::server; + +using boost::shared_ptr; + +using namespace ::Tleveldb; + +// +// These are the service methods that processes Association Data. +// Native types are stored in big-endian format, i.e. first bytes +// have most significant bits. + +class AssocServiceHandler : virtual public AssocServiceIf { + public: + + AssocServiceHandler(OpenHandles* openhandles) { + openhandles_ = openhandles; + woptions_sync_.sync = true; + } + + int64_t taoAssocPut(const Text& tableName, int64_t assocType, int64_t id1, + int64_t id2, int64_t id1Type, int64_t id2Type, + int64_t timestamp, AssocVisibility visibility, + bool update_count, int64_t dataVersion, const Text& data, + const Text& wormhole_comment) { + leveldb::DB* db = openhandles_->get(tableName, NULL); + if (db == NULL) { + return Code::kNotFound; + } + int64_t ret = assocPutInternal(tableName, + db, assocType, id1, id2, id1Type, id2Type, + timestamp, visibility, update_count, dataVersion, + data, wormhole_comment); + return ret; + } + + int64_t taoAssocDelete(const Text& tableName, int64_t assocType, int64_t id1, + int64_t id2, AssocVisibility visibility, bool update_count, + const Text& wormhole_comment) { + leveldb::DB* db = openhandles_->get(tableName, NULL); + if (db == NULL) { + return Code::kNotFound; + } + return assocDeleteInternal(tableName, db, assocType, id1, id2, visibility, + update_count, wormhole_comment); + return 0; + } + + void taoAssocRangeGet(std::vector & _return, + const Text& tableName, int64_t assocType, int64_t id1, + int64_t start_time, int64_t end_time, int64_t offset, + int64_t limit) { + leveldb::DB* db = openhandles_->get(tableName, NULL); + if (db == NULL) { + throw generate_exception(tableName, Code::kNotFound, + "taoAssocRangeGet: Unable to open database " , + assocType, id1, 0, 0, 0, 0, Tleveldb::UNUSED1); + } + assocRangeGetBytimeInternal(_return, tableName, db, assocType, id1, + start_time, end_time, offset, limit); + } + + void taoAssocGet(std::vector & _return, + const Text& tableName, int64_t assocType, int64_t id1, + const std::vector & id2s) { + leveldb::DB* db = openhandles_->get(tableName, NULL); + if (db == NULL) { + throw generate_exception(tableName, Code::kNotFound, + "taoAssocGet:Unable to open database " , + assocType, id1, 0, 0, 0, 0, Tleveldb::UNUSED1); + } + assocGetInternal(_return, tableName, db, assocType, id1, id2s); + } + + int64_t taoAssocCount(const Text& tableName, int64_t assocType, int64_t id1) { + leveldb::DB* db = openhandles_->get(tableName, NULL); + if (db == NULL) { + return Code::kNotFound; + } + return assocCountInternal(tableName, db, assocType, id1); + } + + private: + OpenHandles* openhandles_; + leveldb::ReadOptions roptions_; + leveldb::WriteOptions woptions_; // write with no sync + leveldb::WriteOptions woptions_sync_; // write with sync + + // the maximum values returned in a rangeget/multiget call. + const static unsigned int MAX_RANGE_SIZE = 10000; + + // the seed for murmur hash (copied from Hadoop) + const static unsigned int HASHSEED = 0x5bd1e995; + + // A bunch of rowlocks, sharded over the entire rowkey range + // Each rowkey is deterministically mapped to one of these locks. + leveldb::port::RWMutex rowlocks_[1000]; + + // A helper method that hashes the row key to a lock + leveldb::port::RWMutex* findRowLock(char* str, int size) { + int index = MurmurHash(str, size, HASHSEED) % sizeof(rowlocks_); + return &rowlocks_[index]; + } + + // + // Inserts an assoc + // If update_count, returns the updated count of the assoc. + // If !update_count, return zero. + // On failure, throws exception + // + int64_t assocPutInternal(const Text& tableName, leveldb::DB* db, + int64_t assocType, int64_t id1, + int64_t id2, int64_t id1Type, int64_t id2Type, + int64_t ts, AssocVisibility vis, + bool update_count, int64_t dataVersion, const Text& data, + const Text& wormhole_comment) { + leveldb::WriteBatch batch; + ts = convertTime(ts); // change time to numberofmillis till MAXLONG + + // create the payload for this assoc + int payloadsize = sizeof(id1Type) + sizeof(id2Type) + sizeof(dataVersion) + + sizeof(int32_t) + // store the data size + sizeof(int32_t) + // store the wormhole comment size + data.size() + wormhole_comment.size(); + std::string payload; + payload.reserve(payloadsize); + payload.resize(payloadsize); + makePayload(&payload[0], id1Type, id2Type, dataVersion, data, + wormhole_comment); + + int64_t count = 0; + int64_t oldts; + int8_t oldvis; + bool newassoc = false; // is this assoc new or an overwrite + leveldb::Status status; + std::string value; + + // create RowKey for 'c' + int maxkeysize = sizeof(id1) + sizeof(assocType) + 1; + std::string dummy1; + dummy1.reserve(maxkeysize); + dummy1.resize(maxkeysize); + char* keybuf = &dummy1[0]; + int rowkeysize = makeRowKey(keybuf, id1, assocType); + int keysize = appendRowKeyForCount(rowkeysize, keybuf); + leveldb::Slice ckey(keybuf, keysize); + + // find the row lock + leveldb::port::RWMutex* rowlock = findRowLock(keybuf, rowkeysize); + { + // acquire the row lock + leveldb::WriteLock l(rowlock); + + // Scan 'c' to get $count if $update_count == true + if (update_count) { + status = db->Get(roptions_, ckey, &value); + if (status.IsNotFound()) { + // nothing to do + } else if (!status.ok() || (value.size() != sizeof(int64_t))) { + throw generate_exception(tableName, Code::kNotFound, + "AssocPut Unable to extract count ", + assocType, id1, id2, id1Type, id2Type, ts, vis); + } else { + extract_int64(&count, (char *)value.c_str()); + } + } + + // Scan 'm'$id2 to get $ts and $vis + maxkeysize = sizeof(id1) + sizeof(assocType) + 1 + sizeof(id2); + std::string dummy2; + dummy2.reserve(maxkeysize); + dummy2.resize(maxkeysize); + keybuf = &dummy2[0]; + rowkeysize = makeRowKey(keybuf, id1, assocType); + keysize = appendRowKeyForMeta(rowkeysize, keybuf, id2); + leveldb::Slice mkey(keybuf, keysize); + status = db->Get(roptions_, mkey, &value); + if (status.IsNotFound()) { + newassoc = true; + oldvis = UNUSED1; + } else if (!status.ok() || + (value.size() != sizeof(int64_t) + sizeof(int8_t))) { + throw generate_exception(tableName, Code::kNotFound, + "AssocPut Unable to extract m$id2 ", + assocType, id1, id2, id1Type, id2Type, ts, vis); + } + + // make the key 'p'$old_ts$id2 + maxkeysize = sizeof(id1) + sizeof(assocType) + 1 + + sizeof(ts) + sizeof(id2); + std::string dummy3; + dummy3.reserve(maxkeysize); + dummy3.resize(maxkeysize); + keybuf = &dummy3[0]; + rowkeysize = makeRowKey(keybuf, id1, assocType); + + // if ts != oldts, then delete 'p'$old_ts$id2 + if (!newassoc) { + extractTsVisString(&oldts, &oldvis, (char *)value.c_str()); + keysize = appendRowKeyForPayload(rowkeysize, keybuf, oldts, id2); + leveldb::Slice pkey(keybuf, keysize); + if (ts != oldts) { + batch.Delete(pkey); + } + } + + // store in m$id2 the value of $ts$vis + std::string myvalue; + myvalue.reserve(sizeof(int64_t) + sizeof(int8_t)); + myvalue.resize(sizeof(int64_t) + sizeof(int8_t)); + makeTsVisString(&myvalue[0], ts, vis); + leveldb::Slice sl(myvalue); + batch.Put(mkey, leveldb::Slice(myvalue)); + + // store in p$ts$id2 the payload + keybuf = &dummy3[0]; + keysize = appendRowKeyForPayload(rowkeysize, keybuf, ts, id2); + leveldb::Slice pkeynew(keybuf, keysize); + batch.Put(pkeynew, leveldb::Slice(payload)); + + // increment count + if (update_count && (newassoc || oldvis != VISIBLE)) { + assert(count >= 0); + count++; + myvalue.reserve(sizeof(int64_t)); + myvalue.resize(sizeof(int64_t)); + makeCountString(&myvalue[0], count); + batch.Put(ckey, leveldb::Slice(myvalue)); + } + + // We do a write here without sync. This writes it to the + // transaction log but does not sync it. It also makes these + // changes readable by other threads. + status = db->Write(woptions_, &batch); + if (!status.ok()) { + throw generate_exception(tableName, Code::kNotFound, + "AssocPut Unable to batch write ", + assocType, id1, id2, id1Type, id2Type, ts, vis); + } + } // release rowlock + + // Do a sync to the transaction log without holding the rowlock. + // This improves updates for hotrows. The disadvantage is that + // uncommiitted reads might be read by other threads, but that + // should be ok. + batch.Clear(); + status = db->Write(woptions_sync_, &batch); + if (!status.ok()) { + throw generate_exception(tableName, Code::kNotFound, + "AssocPut Unable to batch sync write ", + assocType, id1, id2, id1Type, id2Type, ts, vis); + } + if (update_count) { + assert(count > 0); + return count; + } + return 0; + } + + // + // Deletes an assoc + // If count changes return 1, else returns zero + // On failure, thrws exception + // + int64_t assocDeleteInternal(const Text& tableName, leveldb::DB* db, + int64_t assocType, int64_t id1, + int64_t id2, AssocVisibility vis, + bool update_count, const Text& wormhole_comment) { + leveldb::WriteBatch batch; + int return_value = 0; + int64_t count = 0; + int64_t oldts; + int8_t oldvis; + std::string value; + + // make a key for count + int maxkeysize = sizeof(id1) + sizeof(assocType) + 1; + std::string dummy; + dummy.reserve(maxkeysize); + dummy.resize(maxkeysize); + char* keybuf = &dummy[0]; + int rowkeysize = makeRowKey(keybuf, id1, assocType); + leveldb::Status status; + int keysize = appendRowKeyForCount(rowkeysize, keybuf); + leveldb::Slice ckey(keybuf, keysize); + + // find the row lock + leveldb::port::RWMutex* rowlock = findRowLock(keybuf, rowkeysize); + { + // acquire the row lock + leveldb::WriteLock l(rowlock); + + // Scan 'c' to get $count if $update_count == true + if (update_count) { + status = db->Get(roptions_, ckey, &value); + if (status.IsNotFound()) { + throw generate_exception(tableName, Code::kNotFound, + "assocDelete: Unable to find count ", + assocType, id1, id2, 0, 0, 0, vis); + } else if (!status.ok() || (value.size() != sizeof(int64_t))) { + throw generate_exception(tableName, Code::kNotFound, + "assocDelete: Unable to extract count ", + assocType, id1, id2, 0, 0, 0, vis); + } else { + extract_int64(&count, (char *)value.c_str()); + } + } + + // Scan 'm'$id2 to get $ts and $vis + maxkeysize = sizeof(id1) + sizeof(assocType) + 1 + sizeof(id2); + std::string dummy2; + dummy2.reserve(maxkeysize); + dummy2.resize(maxkeysize); + keybuf = &dummy2[0]; + rowkeysize = makeRowKey(keybuf, id1, assocType); + keysize = appendRowKeyForMeta(rowkeysize, keybuf, id2); + leveldb::Slice mkey(keybuf, keysize); + status = db->Get(roptions_, mkey, &value); + if (status.IsNotFound()) { + throw generate_exception(tableName, Code::kNotFound, + "assocDelete Unable to find column m ", + assocType, id1, id2, 0, 0, 0, vis); + } else if (!status.ok() || + (value.size() != sizeof(int64_t) + sizeof(int8_t))) { + throw generate_exception(tableName, Code::kNotFound, + "assocDelete Unable to extract m$id2 ", + assocType, id1, id2, 0, 0, 0, vis); + } + extractTsVisString(&oldts, &oldvis, (char *)value.c_str()); + + // Create d'$id2 + maxkeysize = sizeof(id1) + sizeof(assocType) + 1 + sizeof(id2); + std::string dummy3; + dummy3.reserve(maxkeysize); + dummy3.resize(maxkeysize); + keybuf = &dummy3[0]; + rowkeysize = makeRowKey(keybuf, id1, assocType); + keysize = appendRowKeyForDelete(rowkeysize, keybuf, id2); + leveldb::Slice dkey(keybuf, keysize); + + // create key for 'p' + maxkeysize = sizeof(id1) + sizeof(assocType) + 1 + + sizeof(oldts) + sizeof(id2); + std::string dummy4; + dummy4.reserve(maxkeysize); + dummy4.resize(maxkeysize); + keybuf = &dummy4[0]; + rowkeysize = makeRowKey(keybuf, id1, assocType); + keysize = appendRowKeyForPayload(rowkeysize, keybuf, oldts, id2); + leveldb::Slice pkey(keybuf, keysize); + + // if this is a hard delete, then delete all columns + if (vis == AssocVisibility::HARD_DELETE) { + batch.Delete(ckey); + batch.Delete(mkey); + batch.Delete(dkey); + batch.Delete(pkey); + } else if (vis == AssocVisibility::DELETED) { + if (oldvis != AssocVisibility::DELETED) { + // change vis in m$id2 + std::string mvalue; + mvalue.reserve(sizeof(int64_t) + sizeof(int8_t)); + mvalue.resize(sizeof(int64_t) + sizeof(int8_t)); + makeTsVisString(&mvalue[0], oldts, vis); + batch.Put(mkey, leveldb::Slice(mvalue)); + } + + // scan p$tsid2 to get payload + // do we need to modify payload with new wormhole comments? + std::string pvalue; + status = db->Get(roptions_, pkey, &pvalue); + if (status.IsNotFound()) { + throw generate_exception(tableName, Code::kNotFound, + "assocDelete Unable to find p ", + assocType, id1, id2, 0, 0, oldts, vis); + } else if (!status.ok() || + (value.size() != sizeof(int64_t) + sizeof(int8_t))) { + throw generate_exception(tableName, Code::kNotFound, + "assocDelete Unable to extract p ", + assocType, id1, id2, 0, 0, oldts, vis); + } + + // store payload in d$id2 + batch.Put(dkey, leveldb::Slice(pvalue)); + + // delete p$ts$id2 + batch.Delete(pkey); + } + if (update_count && oldvis == AssocVisibility::VISIBLE) { + return_value = 1; + assert(count >= 1); + count--; + std::string myvalue; + myvalue.reserve(sizeof(int64_t)); + myvalue.resize(sizeof(int64_t)); + makeCountString(&myvalue[0], count); + batch.Put(ckey, leveldb::Slice(myvalue)); + } + status = db->Write(woptions_, &batch); // write with no sync + if (!status.ok()) { + throw generate_exception(tableName, Code::kNotFound, + "assocDelete Unable to Batch Write ", + assocType, id1, id2, 0, 0, oldts, vis); + } + } // release rowlock + + // Do a sync write after releasing the rowlock. This + // improves performance for hotrow updates. + batch.Clear(); + status = db->Write(woptions_sync_, &batch); + if (!status.ok()) { + throw generate_exception(tableName, Code::kNotFound, + "assocDelete Unable to Batch sync Write ", + assocType, id1, id2, 0, 0, oldts, vis); + } + if (update_count) { + assert(count >= 0); + return count; + } + return return_value; + } + + int64_t assocCountInternal(const Text& tableName, leveldb::DB* db, + int64_t assocType, int64_t id1) { + // create key to query + int maxkeysize = sizeof(id1) + sizeof(assocType) + 1; + std::string dummy; + dummy.reserve(maxkeysize); + dummy.resize(maxkeysize); + char* keybuf = &dummy[0]; + int rowkeysize = makeRowKey(keybuf, id1, assocType); + int keysize = appendRowKeyForCount(rowkeysize, keybuf); // column 'c' + leveldb::Slice ckey(keybuf, keysize); + + // Query database to find value + leveldb::Status status; + std::string value; + int64_t count; + status = db->Get(roptions_, ckey, &value); + + // parse results retrieved from database + if (status.IsNotFound()) { + return 0; // non existant assoc + } else if (!status.ok()) { + throw generate_exception(tableName, Code::kNotFound, + "assocCountInternal Unable to find count ", + assocType, id1, 0, 0, 0, 0, Tleveldb::UNUSED1); + } + if (value.size() != sizeof(int64_t)) { + printf("expected %ld got %ld\n", sizeof(int64_t), value.size()); + throw generate_exception(tableName, Code::kNotFound, + "assocCountInternal Bad sizes for count ", + assocType, id1, 0, 0, 0, 0, Tleveldb::UNUSED1); + } + extract_int64(&count, (char *)value.c_str()); + return count; + } + + void assocRangeGetBytimeInternal(std::vector & _return, + const Text& tableName, leveldb::DB* db, + int64_t assocType, int64_t id1, + int64_t start_time, int64_t end_time, int64_t offset, + int64_t limit) { + if (start_time < end_time) { + throw generate_exception(tableName, Code::kNotFound, + "assocRangeGetBytimeInternal:Bad starttime and endtime\n", + assocType, id1, 0, 0, 0, 0, Tleveldb::UNUSED1); + } + + int64_t ts, id2; + std::string wormhole; + + // convert times to time-till-LONGMAX + int64_t startTime = convertTime(start_time); + int64_t endTime = convertTime(end_time); + + // create max key to query + int maxkeysize = sizeof(id1) + sizeof(assocType) + 1 + sizeof(ts) + + sizeof(id2); + std::string dummy; + dummy.reserve(maxkeysize); + dummy.resize(maxkeysize); + + // create rowkey + char* keybuf = &dummy[0]; + int rowkeysize = makeRowKey(keybuf, id1, assocType); + + // Position scan at 'p'$ts$id2 where ts = startTime and id2 = 0 + id2 = 0; + int keysize = appendRowKeyForPayload(rowkeysize, keybuf, startTime, id2); + leveldb::Slice pkey(keybuf, keysize); + leveldb::Iterator* iter = db->NewIterator(roptions_); + + for (iter->Seek(pkey); iter->Valid() && limit > 0 ; iter->Next()) { + // skip over records that the caller is not interested in + if (offset > 0) { + offset--; + continue; + } + ASSERT_GE(iter->key().size_, (unsigned int)rowkeysize); + + // extract the timestamp and id1 from the key + extractRowKeyP(&ts, &id2, rowkeysize, (char*)(iter->key().data_)); + ASSERT_GE(ts, startTime); + if (ts > endTime) { + break; + } + + // allocate a new slot in the result set. + _return.resize(_return.size() + 1); + TaoAssocGetResult* result = &_return.back(); + + // Fill up new element in result set. + result->id2 = id2; + result->time = convertTime(ts); + extractPayload((char*)iter->value().data_, &result->id1Type, + &result->id2Type, + &result->dataVersion, result->data, wormhole); + limit--; + } + } + + void assocGetInternal(std::vector & _return, + const Text& tableName, + leveldb::DB* db, + int64_t assocType, int64_t id1, + const std::vector & id2s) { + int64_t ts, id2; + + if (id2s.size() > MAX_RANGE_SIZE) { + throw generate_exception(tableName, Code::kNotFound, + "assocGetInternal Ids2 cannot be gteater than 10K.", + assocType, id1, 0, 0, 0, 0, Tleveldb::UNUSED1); + } + // allocate the entire result buffer. + _return.reserve(id2s.size()); + + // create max key to query + int maxkeysize = sizeof(id1) + sizeof(assocType) + 1 + sizeof(ts) + + sizeof(id2); + std::string dummy; + dummy.reserve(maxkeysize); + dummy.resize(maxkeysize); + + // create rowkey + char* keybuf = &dummy[0]; + int rowkeysize = makeRowKey(keybuf, id1, assocType); + leveldb::Iterator* iter = db->NewIterator(roptions_); + + for (unsigned int index = 0; index < id2s.size(); index++) { + int64_t ts; + int8_t oldvis; + leveldb::Status status; + std::string wormhole; + + // query column 'm'$id2 + id2 = id2s[index]; + int keysize = appendRowKeyForMeta(rowkeysize, keybuf, id2); + leveldb::Slice ckey(keybuf, keysize); + iter->Seek(ckey); + if (!iter->Valid()) { + throw generate_exception(tableName, Code::kNotFound, + "Unable to find m$id2 ", + assocType, id1, id2, 0, 0, 0, Tleveldb::UNUSED1); + } + if (ckey != iter->key()) { + continue; // non existant assoc + } + leveldb::Slice value = iter->value(); + if (value.size() != sizeof(int64_t) + sizeof(int8_t)) { + throw generate_exception(tableName, Code::kNotFound, + "Unable to find m$id2 ", + assocType, id1, id2, 0, 0, 0, Tleveldb::UNUSED1); + } + + extractTsVisString(&ts, &oldvis, (char*)value.data_); + if(oldvis != AssocVisibility::VISIBLE) { + continue; + } + ASSERT_NE(ts, 0); + + // this assoc is visible, scan 'p'$ts$id2 to retrieve payload. + keysize = appendRowKeyForPayload(rowkeysize, keybuf, ts, id2); + leveldb::Slice pkey(keybuf, keysize); + iter->Seek(pkey); + if (!iter->Valid() || (pkey != iter->key())) { + throw generate_exception(tableName, Code::kNotFound, + "Unable to find p$ts$id2 ", + assocType, id1, id2, 0, 0, ts, Tleveldb::UNUSED1); + } + + // allocate a new slot in the result set. + _return.resize(_return.size() + 1); + TaoAssocGetResult* result = &_return.back(); + + // Fill up new element in result set. + result->id2 = id2; + result->time = convertTime(ts); + extractPayload((char *)iter->value().data_, &result->id1Type, + &result->id2Type, + &result->dataVersion, result->data, wormhole); + } + } + + // fill the row key and returns the size of the key + inline int makeRowKey(char* dest, int64_t id1, int64_t assocType) { + dest = copy_int64_switch_endian(dest, id1); + dest = copy_int64_switch_endian(dest, assocType); + return sizeof(id1) + sizeof(assocType); + } + + // fill the row key +'c' and returns the size of the key + inline int appendRowKeyForCount(int rowkeysize, char* dest) { + dest += rowkeysize; + *dest = 'c'; + return rowkeysize + 1; + } + + // fill the row key +'p' + $ts$id2 and returns the size of the key + inline int appendRowKeyForPayload(int rowkeysize, char* dest, + int64_t ts, int64_t id2) { + dest += rowkeysize; + *dest++ = 'p'; + dest = copy_int64_switch_endian(dest, ts); + dest = copy_int64_switch_endian(dest, id2); + return rowkeysize + sizeof(ts) + sizeof(id2) + 1; + } + + // extract the timestamp and id2 from the key p$ts$id2 + inline void extractRowKeyP(int64_t* ts, int64_t* id, + int rowkeysize, char* src) { + src += rowkeysize; // skip over the rowkey + ASSERT_EQ(*src, 'p'); + src++; + extract_int64(ts, src); src += sizeof(*ts); + extract_int64(id, src); src += sizeof(*id); + } + + // fill the row key +'m' + id2 and returns the size of the key + inline int appendRowKeyForMeta(int rowkeysize, char* dest, + int64_t id2) { + dest += rowkeysize; + *dest++ = 'm'; + dest = copy_int64_switch_endian(dest, id2); + return rowkeysize + sizeof(id2) + 1; + } + + // fill the row key +'d' + id2 and returns the size of the key + inline int appendRowKeyForDelete(int rowkeysize, char* dest, + int64_t id2) { + dest += rowkeysize; + *dest++ = 'd'; + dest = copy_int64_switch_endian(dest, id2); + return rowkeysize + sizeof(id2) + 1; + } + + // encode id1Type, id2Type, dataversion, etc into the payload + void makePayload(char* dest, int64_t id1Type, int64_t id2Type, + int64_t dataVersion, const Text& data, + const Text& wormhole_comment) { + int32_t datasize = data.size(); + int32_t wormhole_commentsize = wormhole_comment.size(); + + dest = copy_int64_switch_endian(dest, id1Type); + dest = copy_int64_switch_endian(dest, id2Type); + dest = copy_int64_switch_endian(dest, dataVersion); + dest = copy_int32(dest, datasize); + dest = copy_int32(dest, wormhole_commentsize); + memcpy(dest, data.data(), data.size()); + dest += data.size(); + memcpy(dest, wormhole_comment.data(), wormhole_comment.size()); + dest += wormhole_comment.size(); + } + + // extract id1Type, id2Type, dataversion, etc from payload + void extractPayload(char* dest, int64_t* id1Type, int64_t* id2Type, + int64_t* dataVersion, Text& data, + Text& wormhole_comment) { + int32_t datasize, wormsize; + extract_int64(id1Type, dest); dest += sizeof(*id1Type); + extract_int64(id2Type, dest); dest += sizeof(*id2Type); + extract_int64(dataVersion, dest); dest += sizeof(*dataVersion); + extract_int32(&datasize, dest); dest += sizeof(datasize); + extract_int32(&wormsize, dest); dest += sizeof(wormsize); + + data.assign(dest, datasize); dest += datasize; + wormhole_comment.assign(dest, wormsize); dest += wormsize; + } + + // fill the timestamp and visibility + inline void makeTsVisString(char* dest, int64_t ts, int8_t vis) { + dest = copy_int64_switch_endian(dest, ts); + *dest = vis; + } + + // extracts the timestamp and visibility from a byte stream + inline void extractTsVisString(int64_t* ts, int8_t* vis, char* src) { + extract_int64(ts, src); + extract_int8(vis, src + sizeof(*ts)); + } + + // fill the count value + inline void makeCountString(char* dest, int64_t count) { + dest = copy_int64_switch_endian(dest, count); + } + + // + // Switch endianess of the id and copy it to dest. + // Returns the updated destination address + // + inline char* copy_int64_switch_endian(char* dest, int64_t id) { + char* src = (char *)&id + sizeof(id) - 1; + for (unsigned int i = 0; i < sizeof(id); i++) { + *dest++ = *src--; + } + return dest; + } + + // extracts a int64 type from the char stream. Swaps endianness. + inline void extract_int64(int64_t* dest, char* src) { + char* d = (char *)dest; + src += sizeof(int64_t) - 1; + for (unsigned int i = 0; i < sizeof(uint64_t); i++) { + *d++ = *src--; + } + } + + // + // copy a 4 byte quantity to byte stream. swap endianess. + // + inline char* copy_int32(char* dest, int32_t id) { + char* src = (char *)&id + sizeof(id) - 1; + for (unsigned int i = 0; i < sizeof(id); i++) { + *dest++ = *src--; + } + return dest; + } + + // extract a 4 byte quantity from a byte stream + inline void extract_int32(int32_t* dest, char* src) { + char* d = (char *)dest; + src += sizeof(int32_t) - 1; + for (unsigned int i = 0; i < sizeof(*dest); i++) { + *d++ = *src--; + } + } + + // extracts a 1 byte integer from the char stream. + inline void extract_int8(int8_t* dest, char* src) { + *dest = *(int8_t *)src; + } + + // convert a timestamp from an ever-increasing number to + // a decreasing number. All stored timestamps in this database + // are MAXLONG - timestamp. Thus, a backward-scan in time + // is converted to a forward scan in the database. + inline int64_t convertTime(int64_t ts) { + return LONG_MAX - ts; + } + + + // generate an exception message + LeveldbException generate_exception(const Text& tableName, + Code errorCode, const char* message, + int64_t assocType, int64_t id1, + int64_t id2, int64_t id1Type, int64_t id2Type, + int64_t ts, AssocVisibility vis) { + char result[1024]; + sprintf(result, + "id1=%ld assocType=%ld id2=%ld id1Type=%ld id2Type=%ld ts=%ld vis=%d ", + id1, assocType, id2, id1Type, id2Type, ts, vis); + fprintf(stderr, "assoc_server error table %s: %s errorCode=%d %s", + tableName.c_str(), message, errorCode, result); + + LeveldbException e; + e.errorCode = errorCode; + e.message = message; + throw e; + } + +}; + +#endif // THRIFT_LEVELDB_ASSOC_SERVER_H_ diff --git a/thrift/bin/thrift b/thrift/bin/thrift new file mode 100755 index 00000000..a2868450 Binary files /dev/null and b/thrift/bin/thrift differ diff --git a/thrift/folly/Likely.h b/thrift/folly/Likely.h new file mode 100644 index 00000000..c535e8ae --- /dev/null +++ b/thrift/folly/Likely.h @@ -0,0 +1,39 @@ +/* + * Copyright 2012 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Compiler hints to indicate the fast path of an "if" branch: whether + * the if condition is likely to be true or false. + * + * @author Tudor Bosman (tudorb@fb.com) + */ + +#ifndef FOLLY_BASE_LIKELY_H_ +#define FOLLY_BASE_LIKELY_H_ + +#undef LIKELY +#undef UNLIKELY + +#if defined(__GNUC__) && __GNUC__ >= 4 +#define LIKELY(x) (__builtin_expect((x), 1)) +#define UNLIKELY(x) (__builtin_expect((x), 0)) +#else +#define LIKELY(x) (x) +#define UNLIKELY(x) (x) +#endif + +#endif /* FOLLY_BASE_LIKELY_H_ */ + diff --git a/thrift/folly/Preprocessor.h b/thrift/folly/Preprocessor.h new file mode 100644 index 00000000..d0ff3403 --- /dev/null +++ b/thrift/folly/Preprocessor.h @@ -0,0 +1,70 @@ +/* + * Copyright 2012 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @author: Andrei Alexandrescu + +#ifndef FOLLY_PREPROCESSOR_ +#define FOLLY_PREPROCESSOR_ + +/** + * Necessarily evil preprocessor-related amenities. + */ + +/** + * FB_ONE_OR_NONE(hello, world) expands to hello and + * FB_ONE_OR_NONE(hello) expands to nothing. This macro is used to + * insert or eliminate text based on the presence of another argument. + */ +#define FB_ONE_OR_NONE(a, ...) FB_THIRD(a, ## __VA_ARGS__, a) +#define FB_THIRD(a, b, ...) __VA_ARGS__ + +/** + * Helper macro that extracts the first argument out of a list of any + * number of arguments. + */ +#define FB_ARG_1(a, ...) a + +/** + * Helper macro that extracts the second argument out of a list of any + * number of arguments. If only one argument is given, it returns + * that. + */ +#define FB_ARG_2_OR_1(...) FB_ARG_2_OR_1_IMPL(__VA_ARGS__, __VA_ARGS__) +// Support macro for the above +#define FB_ARG_2_OR_1_IMPL(a, b, ...) b + +/** + * FB_ANONYMOUS_VARIABLE(str) introduces an identifier starting with + * str and ending with a number that varies with the line. + */ +#ifndef FB_ANONYMOUS_VARIABLE +#define FB_CONCATENATE_IMPL(s1, s2) s1##s2 +#define FB_CONCATENATE(s1, s2) FB_CONCATENATE_IMPL(s1, s2) +#ifdef __COUNTER__ +#define FB_ANONYMOUS_VARIABLE(str) FB_CONCATENATE(str, __COUNTER__) +#else +#define FB_ANONYMOUS_VARIABLE(str) FB_CONCATENATE(str, __LINE__) +#endif +#endif + +/** + * Use FB_STRINGIZE(name) when you'd want to do what #name does inside + * another macro expansion. + */ +#define FB_STRINGIZE(name) #name + + +#endif // FOLLY_PREPROCESSOR_ diff --git a/thrift/folly/ScopeGuard.h b/thrift/folly/ScopeGuard.h new file mode 100644 index 00000000..9578f7b0 --- /dev/null +++ b/thrift/folly/ScopeGuard.h @@ -0,0 +1,158 @@ +/* + * Copyright 2012 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOLLY_SCOPEGUARD_H_ +#define FOLLY_SCOPEGUARD_H_ + +#include +#include +#include +#include +//#include + +#include "folly/Preprocessor.h" + +namespace folly { + +/** + * ScopeGuard is a general implementation of the "Initilization is + * Resource Acquisition" idiom. Basically, it guarantees that a function + * is executed upon leaving the currrent scope unless otherwise told. + * + * The makeGuard() function is used to create a new ScopeGuard object. + * It can be instantiated with a lambda function, a std::function, + * a functor, or a void(*)() function pointer. + * + * + * Usage example: Add a friend to memory iff it is also added to the db. + * + * void User::addFriend(User& newFriend) { + * // add the friend to memory + * friends_.push_back(&newFriend); + * + * // If the db insertion that follows fails, we should + * // remove it from memory. + * // (You could also declare this as "auto guard = makeGuard(...)") + * ScopeGuard guard = makeGuard([&] { friends_.pop_back(); }); + * + * // this will throw an exception upon error, which + * // makes the ScopeGuard execute UserCont::pop_back() + * // once the Guard's destructor is called. + * db_->addFriend(GetName(), newFriend.GetName()); + * + * // an exception was not thrown, so don't execute + * // the Guard. + * guard.dismiss(); + * } + * + * Examine ScopeGuardTest.cpp for some more sample usage. + * + * Stolen from: + * Andrei's and Petru Marginean's CUJ article: + * http://drdobbs.com/184403758 + * and the loki library: + * http://loki-lib.sourceforge.net/index.php?n=Idioms.ScopeGuardPointer + * and triendl.kj article: + * http://www.codeproject.com/KB/cpp/scope_guard.aspx + */ +class ScopeGuardImplBase { + public: + void dismiss() noexcept { + dismissed_ = true; + } + + protected: + ScopeGuardImplBase() + : dismissed_(false) {} + + ScopeGuardImplBase(ScopeGuardImplBase&& other) + : dismissed_(other.dismissed_) { + other.dismissed_ = true; + } + + bool dismissed_; +}; + +template +class ScopeGuardImpl : public ScopeGuardImplBase { + public: + explicit ScopeGuardImpl(const FunctionType& fn) + : function_(fn) {} + + explicit ScopeGuardImpl(FunctionType&& fn) + : function_(std::move(fn)) {} + + ScopeGuardImpl(ScopeGuardImpl&& other) + : ScopeGuardImplBase(std::move(other)), + function_(std::move(other.function_)) { + } + + ~ScopeGuardImpl() noexcept { + if (!dismissed_) { + execute(); + } + } + +private: + void* operator new(size_t) = delete; + + void execute() noexcept { + try { + function_(); + } catch (const std::exception& ex) { + std::cout << "ScopeGuard cleanup function threw a " << + typeid(ex).name() << "exception: " << ex.what(); + } catch (...) { + std::cout << "ScopeGuard cleanup function threw a non-exception object"; + } + } + + FunctionType function_; +}; + +template +ScopeGuardImpl::type> +makeGuard(FunctionType&& fn) { + return ScopeGuardImpl::type>( + std::forward(fn)); +} + +/** + * This is largely unneeded if you just use auto for your guards. + */ +typedef ScopeGuardImplBase&& ScopeGuard; + +namespace detail { +/** + * Internal use for the macro SCOPE_EXIT below + */ +enum class ScopeGuardOnExit {}; + +template +ScopeGuardImpl::type> +operator+(detail::ScopeGuardOnExit, FunctionType&& fn) { + return ScopeGuardImpl::type>( + std::forward(fn)); +} +} // namespace detail + +} // folly + +#define SCOPE_EXIT \ + auto FB_ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) \ + = ::folly::detail::ScopeGuardOnExit() + [&] + +#endif // FOLLY_SCOPEGUARD_H_ diff --git a/thrift/folly/experimental/io/IOBuf.h b/thrift/folly/experimental/io/IOBuf.h new file mode 100644 index 00000000..1a416e69 --- /dev/null +++ b/thrift/folly/experimental/io/IOBuf.h @@ -0,0 +1,1050 @@ +/* + * Copyright 2012 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOLLY_IO_IOBUF_H_ +#define FOLLY_IO_IOBUF_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace folly { + +/** + * An IOBuf is a pointer to a buffer of data. + * + * IOBuf objects are intended to be used primarily for networking code, and are + * modelled somewhat after FreeBSD's mbuf data structure, and Linux's sk_buff + * structure. + * + * IOBuf objects facilitate zero-copy network programming, by allowing multiple + * IOBuf objects to point to the same underlying buffer of data, using a + * reference count to track when the buffer is no longer needed and can be + * freed. + * + * + * Data Layout + * ----------- + * + * The IOBuf itself is a small object containing a pointer to the buffer and + * information about which segment of the buffer contains valid data. + * + * The data layout looks like this: + * + * +-------+ + * | IOBuf | + * +-------+ + * / + * | + * v + * +------------+--------------------+-----------+ + * | headroom | data | tailroom | + * +------------+--------------------+-----------+ + * ^ ^ ^ ^ + * buffer() data() tail() bufferEnd() + * + * The length() method returns the length of the valid data; capacity() + * returns the entire capacity of the buffer (from buffer() to bufferEnd()). + * The headroom() and tailroom() methods return the amount of unused capacity + * available before and after the data. + * + * + * Buffer Sharing + * -------------- + * + * The buffer itself is reference counted, and multiple IOBuf objects may point + * to the same buffer. Each IOBuf may point to a different section of valid + * data within the underlying buffer. For example, if multiple protocol + * requests are read from the network into a single buffer, a separate IOBuf + * may be created for each request, all sharing the same underlying buffer. + * + * In other words, when multiple IOBufs share the same underlying buffer, the + * data() and tail() methods on each IOBuf may point to a different segment of + * the data. However, the buffer() and bufferEnd() methods will point to the + * same location for all IOBufs sharing the same underlying buffer. + * + * +-----------+ +---------+ + * | IOBuf 1 | | IOBuf 2 | + * +-----------+ +---------+ + * | | _____/ | + * data | tail |/ data | tail + * v v v + * +-------------------------------------+ + * | | | | | + * +-------------------------------------+ + * + * If you only read data from an IOBuf, you don't need to worry about other + * IOBuf objects possibly sharing the same underlying buffer. However, if you + * ever write to the buffer you need to first ensure that no other IOBufs point + * to the same buffer. The unshare() method may be used to ensure that you + * have an unshared buffer. + * + * + * IOBuf Chains + * ------------ + * + * IOBuf objects also contain pointers to next and previous IOBuf objects. + * This can be used to represent a single logical piece of data that its stored + * in non-contiguous chunks in separate buffers. + * + * A single IOBuf object can only belong to one chain at a time. + * + * IOBuf chains are always circular. The "prev" pointer in the head of the + * chain points to the tail of the chain. However, it is up to the user to + * decide which IOBuf is the head. Internally the IOBuf code does not care + * which element is the head. + * + * The lifetime of all IOBufs in the chain are linked: when one element in the + * chain is deleted, all other chained elements are also deleted. Conceptually + * it is simplest to treat this as if the head of the chain owns all other + * IOBufs in the chain. When you delete the head of the chain, it will delete + * the other elements as well. For this reason, prependChain() and + * appendChain() take ownership of of the new elements being added to this + * chain. + * + * When the coalesce() method is used to coalesce an entire IOBuf chain into a + * single IOBuf, all other IOBufs in the chain are eliminated and automatically + * deleted. The unshare() method may coalesce the chain; if it does it will + * similarly delete all IOBufs eliminated from the chain. + * + * As discussed in the following section, it is up to the user to maintain a + * lock around the entire IOBuf chain if multiple threads need to access the + * chain. IOBuf does not provide any internal locking. + * + * + * Synchronization + * --------------- + * + * When used in multithread programs, a single IOBuf object should only be used + * in a single thread at a time. If a caller uses a single IOBuf across + * multiple threads the caller is responsible for using an external lock to + * synchronize access to the IOBuf. + * + * Two separate IOBuf objects may be accessed concurrently in separate threads + * without locking, even if they point to the same underlying buffer. The + * buffer reference count is always accessed atomically, and no other + * operations should affect other IOBufs that point to the same data segment. + * The caller is responsible for using unshare() to ensure that the data buffer + * is not shared by other IOBufs before writing to it, and this ensures that + * the data itself is not modified in one thread while also being accessed from + * another thread. + * + * For IOBuf chains, no two IOBufs in the same chain should be accessed + * simultaneously in separate threads. The caller must maintain a lock around + * the entire chain if the chain, or individual IOBufs in the chain, may be + * accessed by multiple threads. + * + * + * IOBuf Object Allocation/Sharing + * ------------------------------- + * + * IOBuf objects themselves are always allocated on the heap. The IOBuf + * constructors are private, so IOBuf objects may not be created on the stack. + * In part this is done since some IOBuf objects use small-buffer optimization + * and contain the buffer data immediately after the IOBuf object itself. The + * coalesce() and unshare() methods also expect to be able to delete subsequent + * IOBuf objects in the chain if they are no longer needed due to coalescing. + * + * The IOBuf structure also does not provide room for an intrusive refcount on + * the IOBuf object itself, only the underlying data buffer is reference + * counted. If users want to share the same IOBuf object between multiple + * parts of the code, they are responsible for managing this sharing on their + * own. (For example, by using a shared_ptr. Alternatively, users always have + * the option of using clone() to create a second IOBuf that points to the same + * underlying buffer.) + * + * With jemalloc, allocating small objects like IOBuf objects should be + * relatively fast, and the cost of allocating IOBuf objects on the heap and + * cloning new IOBufs should be relatively cheap. + */ +namespace detail { +// Is T a unique_ptr<> to a standard-layout type? +template struct IsUniquePtrToSL + : public std::false_type { }; +template +struct IsUniquePtrToSL< + std::unique_ptr, + typename std::enable_if::value>::type> + : public std::true_type { }; +} // namespace detail + +class IOBuf { + public: + typedef void (*FreeFunction)(void* buf, void* userData); + + /** + * Allocate a new IOBuf object with the requested capacity. + * + * Returns a new IOBuf object that must be (eventually) deleted by the + * caller. The returned IOBuf may actually have slightly more capacity than + * requested. + * + * The data pointer will initially point to the start of the newly allocated + * buffer, and will have a data length of 0. + * + * Throws std::bad_alloc on error. + */ + static std::unique_ptr create(uint32_t capacity); + + /** + * Create a new IOBuf pointing to an existing data buffer. + * + * The new IOBuffer will assume ownership of the buffer, and free it by + * calling the specified FreeFunction when the last IOBuf pointing to this + * buffer is destroyed. The function will be called with a pointer to the + * buffer as the first argument, and the supplied userData value as the + * second argument. The free function must never throw exceptions. + * + * If no FreeFunction is specified, the buffer will be freed using free(). + * + * The IOBuf data pointer will initially point to the start of the buffer, + * and the length will be the full capacity of the buffer. + * + * On error, std::bad_alloc will be thrown. If freeOnError is true (the + * default) the buffer will be freed before throwing the error. + */ + static std::unique_ptr takeOwnership(void* buf, uint32_t capacity, + FreeFunction freeFn = NULL, + void* userData = NULL, + bool freeOnError = true); + + /** + * Create a new IOBuf pointing to an existing data buffer made up of + * count objects of a given standard-layout type. + * + * This is dangerous -- it is essentially equivalent to doing + * reinterpret_cast on your data -- but it's often useful + * for serialization / deserialization. + * + * The new IOBuffer will assume ownership of the buffer, and free it + * appropriately (by calling the UniquePtr's custom deleter, or by calling + * delete or delete[] appropriately if there is no custom deleter) + * when the buffer is destroyed. The custom deleter, if any, must never + * throw exceptions. + * + * The IOBuf data pointer will initially point to the start of the buffer, + * and the length will be the full capacity of the buffer (count * + * sizeof(T)). + * + * On error, std::bad_alloc will be thrown, and the buffer will be freed + * before throwing the error. + */ + template + static typename std::enable_if::value, + std::unique_ptr>::type + takeOwnership(UniquePtr&& buf, size_t count=1); + + /** + * Create a new IOBuf object that points to an existing user-owned buffer. + * + * This should only be used when the caller knows the lifetime of the IOBuf + * object ahead of time and can ensure that all IOBuf objects that will point + * to this buffer will be destroyed before the buffer itself is destroyed. + * + * This buffer will not be freed automatically when the last IOBuf + * referencing it is destroyed. It is the caller's responsibility to free + * the buffer after the last IOBuf has been destroyed. + * + * The IOBuf data pointer will initially point to the start of the buffer, + * and the length will be the full capacity of the buffer. + * + * An IOBuf created using wrapBuffer() will always be reported as shared. + * unshare() may be used to create a writable copy of the buffer. + * + * On error, std::bad_alloc will be thrown. + */ + static std::unique_ptr wrapBuffer(const void* buf, uint32_t capacity); + + /** + * Convenience function to create a new IOBuf object that copies data from a + * user-supplied buffer, optionally allocating a given amount of + * headroom and tailroom. + */ + static std::unique_ptr copyBuffer(const void* buf, uint32_t size, + uint32_t headroom=0, + uint32_t minTailroom=0); + + /** + * Convenience function to free a chain of IOBufs held by a unique_ptr. + */ + static void destroy(std::unique_ptr&& data) { + auto destroyer = std::move(data); + } + + /** + * Destroy this IOBuf. + * + * Deleting an IOBuf will automatically destroy all IOBufs in the chain. + * (See the comments above regarding the ownership model of IOBuf chains. + * All subsequent IOBufs in the chain are considered to be owned by the head + * of the chain. Users should only explicitly delete the head of a chain.) + * + * When each individual IOBuf is destroyed, it will release its reference + * count on the underlying buffer. If it was the last user of the buffer, + * the buffer will be freed. + */ + ~IOBuf(); + + /** + * Check whether the chain is empty (i.e., whether the IOBufs in the + * chain have a total data length of zero). + * + * This method is semantically equivalent to + * i->computeChainDataLength()==0 + * but may run faster because it can short-circuit as soon as it + * encounters a buffer with length()!=0 + */ + bool empty() const; + + /** + * Get the pointer to the start of the data. + */ + const uint8_t* data() const { + return data_; + } + + /** + * Get a writable pointer to the start of the data. + * + * The caller is responsible for calling unshare() first to ensure that it is + * actually safe to write to the buffer. + */ + uint8_t* writableData() { + return data_; + } + + /** + * Get the pointer to the end of the data. + */ + const uint8_t* tail() const { + return data_ + length_; + } + + /** + * Get a writable pointer to the end of the data. + * + * The caller is responsible for calling unshare() first to ensure that it is + * actually safe to write to the buffer. + */ + uint8_t* writableTail() { + return data_ + length_; + } + + /** + * Get the data length. + */ + uint32_t length() const { + return length_; + } + + /** + * Get the amount of head room. + * + * Returns the number of bytes in the buffer before the start of the data. + */ + uint32_t headroom() const { + return data_ - buffer(); + } + + /** + * Get the amount of tail room. + * + * Returns the number of bytes in the buffer after the end of the data. + */ + uint32_t tailroom() const { + return bufferEnd() - tail(); + } + + /** + * Get the pointer to the start of the buffer. + * + * Note that this is the pointer to the very beginning of the usable buffer, + * not the start of valid data within the buffer. Use the data() method to + * get a pointer to the start of the data within the buffer. + */ + const uint8_t* buffer() const { + return (flags_ & kFlagExt) ? ext_.buf : int_.buf; + } + + /** + * Get a writable pointer to the start of the buffer. + * + * The caller is responsible for calling unshare() first to ensure that it is + * actually safe to write to the buffer. + */ + uint8_t* writableBuffer() { + return (flags_ & kFlagExt) ? ext_.buf : int_.buf; + } + + /** + * Get the pointer to the end of the buffer. + * + * Note that this is the pointer to the very end of the usable buffer, + * not the end of valid data within the buffer. Use the tail() method to + * get a pointer to the end of the data within the buffer. + */ + const uint8_t* bufferEnd() const { + return (flags_ & kFlagExt) ? + ext_.buf + ext_.capacity : + int_.buf + kMaxInternalDataSize; + } + + /** + * Get the total size of the buffer. + * + * This returns the total usable length of the buffer. Use the length() + * method to get the length of the actual valid data in this IOBuf. + */ + uint32_t capacity() const { + return (flags_ & kFlagExt) ? ext_.capacity : kMaxInternalDataSize; + } + + /** + * Get a pointer to the next IOBuf in this chain. + */ + IOBuf* next() { + return next_; + } + const IOBuf* next() const { + return next_; + } + + /** + * Get a pointer to the previous IOBuf in this chain. + */ + IOBuf* prev() { + return prev_; + } + const IOBuf* prev() const { + return prev_; + } + + /** + * Shift the data forwards in the buffer. + * + * This shifts the data pointer forwards in the buffer to increase the + * headroom. This is commonly used to increase the headroom in a newly + * allocated buffer. + * + * The caller is responsible for ensuring that there is sufficient + * tailroom in the buffer before calling advance(). + * + * If there is a non-zero data length, advance() will use memmove() to shift + * the data forwards in the buffer. In this case, the caller is responsible + * for making sure the buffer is unshared, so it will not affect other IOBufs + * that may be sharing the same underlying buffer. + */ + void advance(uint32_t amount) { + // In debug builds, assert if there is a problem. + assert(amount <= tailroom()); + + if (length_ > 0) { + memmove(data_ + amount, data_, length_); + } + data_ += amount; + } + + /** + * Shift the data backwards in the buffer. + * + * The caller is responsible for ensuring that there is sufficient headroom + * in the buffer before calling retreat(). + * + * If there is a non-zero data length, retreat() will use memmove() to shift + * the data backwards in the buffer. In this case, the caller is responsible + * for making sure the buffer is unshared, so it will not affect other IOBufs + * that may be sharing the same underlying buffer. + */ + void retreat(uint32_t amount) { + // In debug builds, assert if there is a problem. + assert(amount <= headroom()); + + if (length_ > 0) { + memmove(data_ - amount, data_, length_); + } + data_ -= amount; + } + + /** + * Adjust the data pointer to include more valid data at the beginning. + * + * This moves the data pointer backwards to include more of the available + * buffer. The caller is responsible for ensuring that there is sufficient + * headroom for the new data. The caller is also responsible for populating + * this section with valid data. + * + * This does not modify any actual data in the buffer. + */ + void prepend(uint32_t amount) { + CHECK(amount <= headroom()); + data_ -= amount; + } + + /** + * Adjust the tail pointer to include more valid data at the end. + * + * This moves the tail pointer forwards to include more of the available + * buffer. The caller is responsible for ensuring that there is sufficient + * tailroom for the new data. The caller is also responsible for populating + * this section with valid data. + * + * This does not modify any actual data in the buffer. + */ + void append(uint32_t amount) { + CHECK(amount <= tailroom()); + length_ += amount; + } + + /** + * Adjust the data pointer forwards to include less valid data. + * + * This moves the data pointer forwards so that the first amount bytes are no + * longer considered valid data. The caller is responsible for ensuring that + * amount is less than or equal to the actual data length. + * + * This does not modify any actual data in the buffer. + */ + void trimStart(uint32_t amount) { + CHECK(amount <= length_); + data_ += amount; + length_ -= amount; + } + + /** + * Adjust the tail pointer backwards to include less valid data. + * + * This moves the tail pointer backwards so that the last amount bytes are no + * longer considered valid data. The caller is responsible for ensuring that + * amount is less than or equal to the actual data length. + * + * This does not modify any actual data in the buffer. + */ + void trimEnd(uint32_t amount) { + CHECK(amount <= length_); + length_ -= amount; + } + + /** + * Clear the buffer. + * + * Postcondition: headroom() == 0, length() == 0, tailroom() == capacity() + */ + void clear() { + data_ = writableBuffer(); + length_ = 0; + } + + /** + * Ensure that this buffer has at least minHeadroom headroom bytes and at + * least minTailroom tailroom bytes. The buffer must be writable + * (you must call unshare() before this, if necessary). + * + * Postcondition: headroom() >= minHeadroom, tailroom() >= minTailroom, + * the data (between data() and data() + length()) is preserved. + */ + void reserve(uint32_t minHeadroom, uint32_t minTailroom) { + // Maybe we don't need to do anything. + if (headroom() >= minHeadroom && tailroom() >= minTailroom) { + return; + } + // If the buffer is empty but we have enough total room (head + tail), + // move the data_ pointer around. + if (length() == 0 && + headroom() + tailroom() >= minHeadroom + minTailroom) { + data_ = writableBuffer() + minHeadroom; + return; + } + // Bah, we have to do actual work. + reserveSlow(minHeadroom, minTailroom); + } + + /** + * Return true if this IOBuf is part of a chain of multiple IOBufs, or false + * if this is the only IOBuf in its chain. + */ + bool isChained() const { + assert((next_ == this) == (prev_ == this)); + return next_ != this; + } + + /** + * Get the number of IOBufs in this chain. + * + * Beware that this method has to walk the entire chain. + * Use isChained() if you just want to check if this IOBuf is part of a chain + * or not. + */ + uint32_t countChainElements() const; + + /** + * Get the length of all the data in this IOBuf chain. + * + * Beware that this method has to walk the entire chain. + */ + uint64_t computeChainDataLength() const; + + /** + * Insert another IOBuf chain immediately before this IOBuf. + * + * For example, if there are two IOBuf chains (A, B, C) and (D, E, F), + * and B->prependChain(D) is called, the (D, E, F) chain will be subsumed + * and become part of the chain starting at A, which will now look like + * (A, D, E, F, B, C) + * + * Note that since IOBuf chains are circular, head->prependChain(other) can + * be used to append the other chain at the very end of the chain pointed to + * by head. For example, if there are two IOBuf chains (A, B, C) and + * (D, E, F), and A->prependChain(D) is called, the chain starting at A will + * now consist of (A, B, C, D, E, F) + * + * The elements in the specified IOBuf chain will become part of this chain, + * and will be owned by the head of this chain. When this chain is + * destroyed, all elements in the supplied chain will also be destroyed. + * + * For this reason, appendChain() only accepts an rvalue-reference to a + * unique_ptr(), to make it clear that it is taking ownership of the supplied + * chain. If you have a raw pointer, you can pass in a new temporary + * unique_ptr around the raw pointer. If you have an existing, + * non-temporary unique_ptr, you must call std::move(ptr) to make it clear + * that you are destroying the original pointer. + */ + void prependChain(std::unique_ptr&& iobuf); + + /** + * Append another IOBuf chain immediately after this IOBuf. + * + * For example, if there are two IOBuf chains (A, B, C) and (D, E, F), + * and B->appendChain(D) is called, the (D, E, F) chain will be subsumed + * and become part of the chain starting at A, which will now look like + * (A, B, D, E, F, C) + * + * The elements in the specified IOBuf chain will become part of this chain, + * and will be owned by the head of this chain. When this chain is + * destroyed, all elements in the supplied chain will also be destroyed. + * + * For this reason, appendChain() only accepts an rvalue-reference to a + * unique_ptr(), to make it clear that it is taking ownership of the supplied + * chain. If you have a raw pointer, you can pass in a new temporary + * unique_ptr around the raw pointer. If you have an existing, + * non-temporary unique_ptr, you must call std::move(ptr) to make it clear + * that you are destroying the original pointer. + */ + void appendChain(std::unique_ptr&& iobuf) { + // Just use prependChain() on the next element in our chain + next_->prependChain(std::move(iobuf)); + } + + /** + * Remove this IOBuf from its current chain. + * + * Since ownership of all elements an IOBuf chain is normally maintained by + * the head of the chain, unlink() transfers ownership of this IOBuf from the + * chain and gives it to the caller. A new unique_ptr to the IOBuf is + * returned to the caller. The caller must store the returned unique_ptr (or + * call release() on it) to take ownership, otherwise the IOBuf will be + * immediately destroyed. + * + * Since unlink transfers ownership of the IOBuf to the caller, be careful + * not to call unlink() on the head of a chain if you already maintain + * ownership on the head of the chain via other means. The pop() method + * is a better choice for that situation. + */ + std::unique_ptr unlink() { + next_->prev_ = prev_; + prev_->next_ = next_; + prev_ = this; + next_ = this; + return std::unique_ptr(this); + } + + /** + * Remove this IOBuf from its current chain and return a unique_ptr to + * the IOBuf that formerly followed it in the chain. + */ + std::unique_ptr pop() { + IOBuf *next = next_; + next_->prev_ = prev_; + prev_->next_ = next_; + prev_ = this; + next_ = this; + return std::unique_ptr((next == this) ? NULL : next); + } + + /** + * Remove a subchain from this chain. + * + * Remove the subchain starting at head and ending at tail from this chain. + * + * Returns a unique_ptr pointing to head. (In other words, ownership of the + * head of the subchain is transferred to the caller.) If the caller ignores + * the return value and lets the unique_ptr be destroyed, the subchain will + * be immediately destroyed. + * + * The subchain referenced by the specified head and tail must be part of the + * same chain as the current IOBuf, but must not contain the current IOBuf. + * However, the specified head and tail may be equal to each other (i.e., + * they may be a subchain of length 1). + */ + std::unique_ptr separateChain(IOBuf* head, IOBuf* tail) { + assert(head != this); + assert(tail != this); + + head->prev_->next_ = tail->next_; + tail->next_->prev_ = head->prev_; + + head->prev_ = tail; + tail->next_ = head; + + return std::unique_ptr(head); + } + + /** + * Return true if at least one of the IOBufs in this chain are shared, + * or false if all of the IOBufs point to unique buffers. + * + * Use isSharedOne() to only check this IOBuf rather than the entire chain. + */ + bool isShared() const { + const IOBuf* current = this; + while (true) { + if (current->isSharedOne()) { + return true; + } + current = current->next_; + if (current == this) { + return false; + } + } + } + + /** + * Return true if other IOBufs are also pointing to the buffer used by this + * IOBuf, and false otherwise. + * + * If this IOBuf points at a buffer owned by another (non-IOBuf) part of the + * code (i.e., if the IOBuf was created using wrapBuffer(), or was cloned + * from such an IOBuf), it is always considered shared. + * + * This only checks the current IOBuf, and not other IOBufs in the chain. + */ + bool isSharedOne() const { + // If this is a user-owned buffer, it is always considered shared + if (flags_ & kFlagUserOwned) { + return true; + } + + if (flags_ & kFlagExt) { + return ext_.sharedInfo->refcount.load(std::memory_order_acquire) > 1; + } else { + return false; + } + } + + /** + * Ensure that this IOBuf has a unique buffer that is not shared by other + * IOBufs. + * + * unshare() operates on an entire chain of IOBuf objects. If the chain is + * shared, it may also coalesce the chain when making it unique. If the + * chain is coalesced, subsequent IOBuf objects in the current chain will be + * automatically deleted. + * + * Note that buffers owned by other (non-IOBuf) users are automatically + * considered shared. + * + * Throws std::bad_alloc on error. On error the IOBuf chain will be + * unmodified. + * + * Currently unshare may also throw std::overflow_error if it tries to + * coalesce. (TODO: In the future it would be nice if unshare() were smart + * enough not to coalesce the entire buffer if the data is too large. + * However, in practice this seems unlikely to become an issue.) + */ + void unshare() { + if (isChained()) { + unshareChained(); + } else { + unshareOne(); + } + } + + /** + * Ensure that this IOBuf has a unique buffer that is not shared by other + * IOBufs. + * + * unshareOne() operates on a single IOBuf object. This IOBuf will have a + * unique buffer after unshareOne() returns, but other IOBufs in the chain + * may still be shared after unshareOne() returns. + * + * Throws std::bad_alloc on error. On error the IOBuf will be unmodified. + */ + void unshareOne() { + if (isSharedOne()) { + unshareOneSlow(); + } + } + + /** + * Coalesce this IOBuf chain into a single buffer. + * + * This method moves all of the data in this IOBuf chain into a single + * contiguous buffer, if it is not already in one buffer. After coalesce() + * returns, this IOBuf will be a chain of length one. Other IOBufs in the + * chain will be automatically deleted. + * + * After coalescing, the IOBuf will have at least as much headroom as the + * first IOBuf in the chain, and at least as much tailroom as the last IOBuf + * in the chain. + * + * Throws std::bad_alloc on error. On error the IOBuf chain will be + * unmodified. Throws std::overflow_error if the length of the entire chain + * larger than can be described by a uint32_t capacity. + */ + void coalesce() { + if (!isChained()) { + return; + } + coalesceSlow(); + } + + /** + * Ensure that this chain has at least maxLength bytes available as a + * contiguous memory range. + * + * This method coalesces whole buffers in the chain into this buffer as + * necessary until this buffer's length() is at least maxLength. + * + * After coalescing, the IOBuf will have at least as much headroom as the + * first IOBuf in the chain, and at least as much tailroom as the last IOBuf + * that was coalesced. + * + * Throws std::bad_alloc on error. On error the IOBuf chain will be + * unmodified. Throws std::overflow_error if the length of the coalesced + * portion of the chain is larger than can be described by a uint32_t + * capacity. (Although maxLength is uint32_t, gather() doesn't split + * buffers, so coalescing whole buffers may result in a capacity that can't + * be described in uint32_t. + * + * Upon return, either enough of the chain was coalesced into a contiguous + * region, or the entire chain was coalesced. That is, + * length() >= maxLength || !isChained() is true. + */ + void gather(uint32_t maxLength) { + if (!isChained() || length_ >= maxLength) { + return; + } + coalesceSlow(maxLength); + } + + /** + * Return a new IOBuf chain sharing the same data as this chain. + * + * The new IOBuf chain will normally point to the same underlying data + * buffers as the original chain. (The one exception to this is if some of + * the IOBufs in this chain contain small internal data buffers which cannot + * be shared.) + */ + std::unique_ptr clone() const; + + /** + * Return a new IOBuf with the same data as this IOBuf. + * + * The new IOBuf returned will not be part of a chain (even if this IOBuf is + * part of a larger chain). + */ + std::unique_ptr cloneOne() const; + + // Overridden operator new and delete. + // These directly use malloc() and free() to allocate the space for IOBuf + // objects. This is needed since IOBuf::create() manually uses malloc when + // allocating IOBuf objects with an internal buffer. + void* operator new(size_t size); + void* operator new(size_t size, void* ptr); + void operator delete(void* ptr); + + private: + enum FlagsEnum { + kFlagExt = 0x1, + kFlagUserOwned = 0x2, + kFlagFreeSharedInfo = 0x4, + }; + + // Values for the ExternalBuf type field. + // We currently don't really use this for anything, other than to have it + // around for debugging purposes. We store it at the moment just because we + // have the 4 extra bytes in the ExternalBuf struct that would just be + // padding otherwise. + enum ExtBufTypeEnum { + kExtAllocated = 0, + kExtUserSupplied = 1, + kExtUserOwned = 2, + }; + + struct SharedInfo { + SharedInfo(); + SharedInfo(FreeFunction fn, void* arg); + + // A pointer to a function to call to free the buffer when the refcount + // hits 0. If this is NULL, free() will be used instead. + FreeFunction freeFn; + void* userData; + std::atomic refcount; + }; + struct ExternalBuf { + uint32_t capacity; + uint32_t type; + uint8_t* buf; + // SharedInfo may be NULL if kFlagUserOwned is set. It is non-NULL + // in all other cases. + SharedInfo* sharedInfo; + }; + struct InternalBuf { + uint8_t buf[] __attribute__((aligned)); + }; + + // The maximum size for an IOBuf object, including any internal data buffer + static const uint32_t kMaxIOBufSize = 256; + static const uint32_t kMaxInternalDataSize; + + // Forbidden copy constructor and assignment opererator + IOBuf(IOBuf const &); + IOBuf& operator=(IOBuf const &); + + /** + * Create a new IOBuf with internal data. + * + * end is a pointer to the end of the IOBuf's internal data buffer. + */ + explicit IOBuf(uint8_t* end); + + /** + * Create a new IOBuf pointing to an external buffer. + * + * The caller is responsible for holding a reference count for this new + * IOBuf. The IOBuf constructor does not automatically increment the + * reference count. + */ + IOBuf(ExtBufTypeEnum type, uint32_t flags, + uint8_t* buf, uint32_t capacity, + uint8_t* data, uint32_t length, + SharedInfo* sharedInfo); + + void unshareOneSlow(); + void unshareChained(); + void coalesceSlow(size_t maxLength=std::numeric_limits::max()); + void decrementRefcount(); + void reserveSlow(uint32_t minHeadroom, uint32_t minTailroom); + + static size_t goodExtBufferSize(uint32_t minCapacity); + static void initExtBuffer(uint8_t* buf, size_t mallocSize, + SharedInfo** infoReturn, + uint32_t* capacityReturn); + static void allocExtBuffer(uint32_t minCapacity, + uint8_t** bufReturn, + SharedInfo** infoReturn, + uint32_t* capacityReturn); + + /* + * Member variables + */ + + /* + * Links to the next and the previous IOBuf in this chain. + * + * The chain is circularly linked (the last element in the chain points back + * at the head), and next_ and prev_ can never be NULL. If this IOBuf is the + * only element in the chain, next_ and prev_ will both point to this. + */ + IOBuf* next_; + IOBuf* prev_; + + /* + * A pointer to the start of the data referenced by this IOBuf, and the + * length of the data. + * + * This may refer to any subsection of the actual buffer capacity. + */ + uint8_t* data_; + uint32_t length_; + uint32_t flags_; + + union { + ExternalBuf ext_; + InternalBuf int_; + }; + + struct DeleterBase { + virtual ~DeleterBase() { } + virtual void dispose(void* p) = 0; + }; + + template + struct UniquePtrDeleter : public DeleterBase { + typedef typename UniquePtr::pointer Pointer; + typedef typename UniquePtr::deleter_type Deleter; + + explicit UniquePtrDeleter(Deleter deleter) : deleter_(std::move(deleter)){ } + void dispose(void* p) { + try { + deleter_(static_cast(p)); + delete this; + } catch (...) { + abort(); + } + } + + private: + Deleter deleter_; + }; + + static void freeUniquePtrBuffer(void* ptr, void* userData) { + static_cast(userData)->dispose(ptr); + } +}; + +template +typename std::enable_if::value, + std::unique_ptr>::type +IOBuf::takeOwnership(UniquePtr&& buf, size_t count) { + size_t size = count * sizeof(typename UniquePtr::element_type); + CHECK_LT(size, size_t(std::numeric_limits::max())); + auto deleter = new UniquePtrDeleter(buf.get_deleter()); + return takeOwnership(buf.release(), + size, + &IOBuf::freeUniquePtrBuffer, + deleter); +} + +inline std::unique_ptr IOBuf::copyBuffer( + const void* data, uint32_t size, uint32_t headroom, + uint32_t minTailroom) { + uint32_t capacity = headroom + size + minTailroom; + std::unique_ptr buf = create(capacity); + buf->advance(headroom); + memcpy(buf->writableData(), data, size); + buf->append(size); + return buf; +} + +} // folly + +#endif // FOLLY_IO_IOBUF_H_ diff --git a/thrift/folly/experimental/io/IOBufQueue.h b/thrift/folly/experimental/io/IOBufQueue.h new file mode 100644 index 00000000..283cd3ac --- /dev/null +++ b/thrift/folly/experimental/io/IOBufQueue.h @@ -0,0 +1,201 @@ +/* + * Copyright 2012 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOLLY_IO_IOBUF_QUEUE_H +#define FOLLY_IO_IOBUF_QUEUE_H + +#include "folly/experimental/io/IOBuf.h" + +#include +#include + +namespace folly { + +/** + * An IOBufQueue encapsulates a chain of IOBufs and provides + * convenience functions to append data to the back of the chain + * and remove data from the front. + */ +class IOBufQueue { + public: + struct Options { + Options() : cacheChainLength(false) { } + bool cacheChainLength; + }; + + explicit IOBufQueue(const Options& options = Options()); + + /** + * Add a buffer or buffer chain to the end of this queue. The + * queue takes ownership of buf. + */ + void append(std::unique_ptr&& buf); + + /** + * Add a queue to the end of this queue. The queue takes ownership of + * all buffers from the other queue. + */ + void append(IOBufQueue& other); + void append(IOBufQueue&& other) { + append(other); // call lvalue reference overload, above + } + + /** + * Copy len bytes, starting at buf, to the end of this queue. + * The caller retains ownership of the source data. + */ + void append(const void* buf, size_t len); + + /** + * Copy a string to the end of this queue. + * The caller retains ownership of the source data. + */ + void append(const std::string& buf) { + append(buf.data(), buf.length()); + } + + /** + * Append a chain of IOBuf objects that point to consecutive regions + * within buf. + * + * Just like IOBuf::wrapBuffer, this should only be used when the caller + * knows ahead of time and can ensure that all IOBuf objects that will point + * to this buffer will be destroyed before the buffer itself is destroyed; + * all other caveats from wrapBuffer also apply. + * + * Every buffer except for the last will wrap exactly blockSize bytes. + * Importantly, this method may be used to wrap buffers larger than 4GB. + */ + void wrapBuffer(const void* buf, size_t len, + uint32_t blockSize=(1U << 31)); // default block size: 2GB + + /** + * Obtain a writable block of contiguous bytes at the end of this + * queue, allocating more space if necessary. The amount of space + * reserved will be between min and max, inclusive; the IOBufQueue + * implementation may pick a value in that range that makes efficient + * use of already-allocated internal space. + * + * If the caller subsequently writes anything into the returned space, + * it must call the postallocate() method. + * + * @return The starting address of the block and the length in bytes. + * + * @note The point of the preallocate()/postallocate() mechanism is + * to support I/O APIs such as Thrift's TAsyncSocket::ReadCallback + * that request a buffer from the application and then, in a later + * callback, tell the application how much of the buffer they've + * filled with data. + */ + std::pair preallocate(uint32_t min, uint32_t max); + + /** + * Tell the queue that the caller has written data into the first n + * bytes provided by the previous preallocate() call. + * + * @note n should be less than or equal to the size returned by + * preallocate(). If n is zero, the caller may skip the call + * to postallocate(). If n is nonzero, the caller must not + * invoke any other non-const methods on this IOBufQueue between + * the call to preallocate and the call to postallocate(). + */ + void postallocate(uint32_t n); + + /** + * Obtain a writable block of n contiguous bytes, allocating more space + * if necessary, and mark it as used. The caller can fill it later. + */ + void* allocate(uint32_t n) { + void* p = preallocate(n, n).first; + postallocate(n); + return p; + } + + /** + * Split off the first n bytes of the queue into a separate IOBuf chain, + * and transfer ownership of the new chain to the caller. The IOBufQueue + * retains ownership of everything after the split point. + * + * @warning If the split point lies in the middle of some IOBuf within + * the chain, this function may, as an implementation detail, + * clone that IOBuf. + * + * @throws std::underflow_error if n exceeds the number of bytes + * in the queue. + */ + std::unique_ptr split(size_t n); + + /** + * Similar to IOBuf::trimStart, but works on the whole queue. Will + * pop off buffers that have been completely trimmed. + */ + void trimStart(size_t amount); + + /** + * Similar to IOBuf::trimEnd, but works on the whole queue. Will + * pop off buffers that have been completely trimmed. + */ + void trimEnd(size_t amount); + + /** + * Transfer ownership of the queue's entire IOBuf chain to the caller. + */ + std::unique_ptr&& move() { + chainLength_ = 0; + return std::move(head_); + } + + /** + * Access + */ + const folly::IOBuf* front() const { + return head_.get(); + } + + /** + * Total chain length, only valid if cacheLength was specified in the + * constructor. + */ + size_t chainLength() const { + if (!options_.cacheChainLength) { + throw std::invalid_argument("IOBufQueue: chain length not cached"); + } + return chainLength_; + } + + const Options& options() const { + return options_; + } + + /** Movable */ + IOBufQueue(IOBufQueue&&); + IOBufQueue& operator=(IOBufQueue&&); + + private: + static const size_t kChainLengthNotCached = (size_t)-1; + /** Not copyable */ + IOBufQueue(const IOBufQueue&) = delete; + IOBufQueue& operator=(const IOBufQueue&) = delete; + + Options options_; + size_t chainLength_; + /** Everything that has been appended but not yet discarded or moved out */ + std::unique_ptr head_; +}; + +} // folly + +#endif // FOLLY_IO_IOBUF_QUEUE_H diff --git a/thrift/folly/experimental/io/check.h b/thrift/folly/experimental/io/check.h new file mode 100644 index 00000000..52324a39 --- /dev/null +++ b/thrift/folly/experimental/io/check.h @@ -0,0 +1,2 @@ +#define CHECK(a) +#define CHECK_LT(a, b) diff --git a/thrift/gen-cpp/AssocService.cpp b/thrift/gen-cpp/AssocService.cpp new file mode 100644 index 00000000..006a426e --- /dev/null +++ b/thrift/gen-cpp/AssocService.cpp @@ -0,0 +1,2135 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "AssocService.h" +#include "folly/ScopeGuard.h" + +namespace Tleveldb { + +uint32_t AssocService_taoAssocPut_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->tableName); + this->__isset.tableName = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->assocType); + this->__isset.assocType = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->id1); + this->__isset.id1 = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->id2); + this->__isset.id2 = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 5: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->id1Type); + this->__isset.id1Type = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 6: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->id2Type); + this->__isset.id2Type = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 7: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->timestamp); + this->__isset.timestamp = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 8: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast41; + xfer += iprot->readI32(ecast41); + this->visibility = (AssocVisibility)ecast41; + this->__isset.visibility = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 9: + if (ftype == apache::thrift::protocol::T_BOOL) { + xfer += iprot->readBool(this->update_count); + this->__isset.update_count = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 10: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->dataVersion); + this->__isset.dataVersion = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 11: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->data); + this->__isset.data = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 12: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->wormhole_comment); + this->__isset.wormhole_comment = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t AssocService_taoAssocPut_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("AssocService_taoAssocPut_args"); + xfer += oprot->writeFieldBegin("tableName", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary(this->tableName); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("assocType", apache::thrift::protocol::T_I64, 2); + xfer += oprot->writeI64(this->assocType); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id1", apache::thrift::protocol::T_I64, 3); + xfer += oprot->writeI64(this->id1); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id2", apache::thrift::protocol::T_I64, 4); + xfer += oprot->writeI64(this->id2); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id1Type", apache::thrift::protocol::T_I64, 5); + xfer += oprot->writeI64(this->id1Type); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id2Type", apache::thrift::protocol::T_I64, 6); + xfer += oprot->writeI64(this->id2Type); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("timestamp", apache::thrift::protocol::T_I64, 7); + xfer += oprot->writeI64(this->timestamp); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("visibility", apache::thrift::protocol::T_I32, 8); + xfer += oprot->writeI32((int32_t)this->visibility); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("update_count", apache::thrift::protocol::T_BOOL, 9); + xfer += oprot->writeBool(this->update_count); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("dataVersion", apache::thrift::protocol::T_I64, 10); + xfer += oprot->writeI64(this->dataVersion); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("data", apache::thrift::protocol::T_STRING, 11); + xfer += oprot->writeBinary(this->data); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("wormhole_comment", apache::thrift::protocol::T_STRING, 12); + xfer += oprot->writeBinary(this->wormhole_comment); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t AssocService_taoAssocPut_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("AssocService_taoAssocPut_pargs"); + xfer += oprot->writeFieldBegin("tableName", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary((*(this->tableName))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("assocType", apache::thrift::protocol::T_I64, 2); + xfer += oprot->writeI64((*(this->assocType))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id1", apache::thrift::protocol::T_I64, 3); + xfer += oprot->writeI64((*(this->id1))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id2", apache::thrift::protocol::T_I64, 4); + xfer += oprot->writeI64((*(this->id2))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id1Type", apache::thrift::protocol::T_I64, 5); + xfer += oprot->writeI64((*(this->id1Type))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id2Type", apache::thrift::protocol::T_I64, 6); + xfer += oprot->writeI64((*(this->id2Type))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("timestamp", apache::thrift::protocol::T_I64, 7); + xfer += oprot->writeI64((*(this->timestamp))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("visibility", apache::thrift::protocol::T_I32, 8); + xfer += oprot->writeI32((int32_t)(*(this->visibility))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("update_count", apache::thrift::protocol::T_BOOL, 9); + xfer += oprot->writeBool((*(this->update_count))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("dataVersion", apache::thrift::protocol::T_I64, 10); + xfer += oprot->writeI64((*(this->dataVersion))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("data", apache::thrift::protocol::T_STRING, 11); + xfer += oprot->writeBinary((*(this->data))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("wormhole_comment", apache::thrift::protocol::T_STRING, 12); + xfer += oprot->writeBinary((*(this->wormhole_comment))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t AssocService_taoAssocPut_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->success); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->io.read(iprot); + this->__isset.io = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t AssocService_taoAssocPut_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("AssocService_taoAssocPut_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_I64, 0); + xfer += oprot->writeI64(this->success); + xfer += oprot->writeFieldEnd(); + } else if (this->__isset.io) { + xfer += oprot->writeFieldBegin("io", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->io.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t AssocService_taoAssocPut_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64((*(this->success))); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->io.read(iprot); + this->__isset.io = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t AssocService_taoAssocDelete_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->tableName); + this->__isset.tableName = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->assocType); + this->__isset.assocType = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->id1); + this->__isset.id1 = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->id2); + this->__isset.id2 = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 5: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast42; + xfer += iprot->readI32(ecast42); + this->visibility = (AssocVisibility)ecast42; + this->__isset.visibility = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 6: + if (ftype == apache::thrift::protocol::T_BOOL) { + xfer += iprot->readBool(this->update_count); + this->__isset.update_count = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 7: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->wormhole_comment); + this->__isset.wormhole_comment = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t AssocService_taoAssocDelete_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("AssocService_taoAssocDelete_args"); + xfer += oprot->writeFieldBegin("tableName", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary(this->tableName); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("assocType", apache::thrift::protocol::T_I64, 2); + xfer += oprot->writeI64(this->assocType); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id1", apache::thrift::protocol::T_I64, 3); + xfer += oprot->writeI64(this->id1); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id2", apache::thrift::protocol::T_I64, 4); + xfer += oprot->writeI64(this->id2); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("visibility", apache::thrift::protocol::T_I32, 5); + xfer += oprot->writeI32((int32_t)this->visibility); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("update_count", apache::thrift::protocol::T_BOOL, 6); + xfer += oprot->writeBool(this->update_count); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("wormhole_comment", apache::thrift::protocol::T_STRING, 7); + xfer += oprot->writeBinary(this->wormhole_comment); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t AssocService_taoAssocDelete_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("AssocService_taoAssocDelete_pargs"); + xfer += oprot->writeFieldBegin("tableName", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary((*(this->tableName))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("assocType", apache::thrift::protocol::T_I64, 2); + xfer += oprot->writeI64((*(this->assocType))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id1", apache::thrift::protocol::T_I64, 3); + xfer += oprot->writeI64((*(this->id1))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id2", apache::thrift::protocol::T_I64, 4); + xfer += oprot->writeI64((*(this->id2))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("visibility", apache::thrift::protocol::T_I32, 5); + xfer += oprot->writeI32((int32_t)(*(this->visibility))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("update_count", apache::thrift::protocol::T_BOOL, 6); + xfer += oprot->writeBool((*(this->update_count))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("wormhole_comment", apache::thrift::protocol::T_STRING, 7); + xfer += oprot->writeBinary((*(this->wormhole_comment))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t AssocService_taoAssocDelete_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->success); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->io.read(iprot); + this->__isset.io = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t AssocService_taoAssocDelete_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("AssocService_taoAssocDelete_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_I64, 0); + xfer += oprot->writeI64(this->success); + xfer += oprot->writeFieldEnd(); + } else if (this->__isset.io) { + xfer += oprot->writeFieldBegin("io", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->io.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t AssocService_taoAssocDelete_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64((*(this->success))); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->io.read(iprot); + this->__isset.io = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t AssocService_taoAssocRangeGet_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->tableName); + this->__isset.tableName = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->assocType); + this->__isset.assocType = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->id1); + this->__isset.id1 = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->start_time); + this->__isset.start_time = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 5: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->end_time); + this->__isset.end_time = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 6: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->offset); + this->__isset.offset = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 7: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->limit); + this->__isset.limit = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t AssocService_taoAssocRangeGet_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("AssocService_taoAssocRangeGet_args"); + xfer += oprot->writeFieldBegin("tableName", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary(this->tableName); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("assocType", apache::thrift::protocol::T_I64, 2); + xfer += oprot->writeI64(this->assocType); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id1", apache::thrift::protocol::T_I64, 3); + xfer += oprot->writeI64(this->id1); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("start_time", apache::thrift::protocol::T_I64, 4); + xfer += oprot->writeI64(this->start_time); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("end_time", apache::thrift::protocol::T_I64, 5); + xfer += oprot->writeI64(this->end_time); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("offset", apache::thrift::protocol::T_I64, 6); + xfer += oprot->writeI64(this->offset); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("limit", apache::thrift::protocol::T_I64, 7); + xfer += oprot->writeI64(this->limit); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t AssocService_taoAssocRangeGet_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("AssocService_taoAssocRangeGet_pargs"); + xfer += oprot->writeFieldBegin("tableName", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary((*(this->tableName))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("assocType", apache::thrift::protocol::T_I64, 2); + xfer += oprot->writeI64((*(this->assocType))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id1", apache::thrift::protocol::T_I64, 3); + xfer += oprot->writeI64((*(this->id1))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("start_time", apache::thrift::protocol::T_I64, 4); + xfer += oprot->writeI64((*(this->start_time))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("end_time", apache::thrift::protocol::T_I64, 5); + xfer += oprot->writeI64((*(this->end_time))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("offset", apache::thrift::protocol::T_I64, 6); + xfer += oprot->writeI64((*(this->offset))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("limit", apache::thrift::protocol::T_I64, 7); + xfer += oprot->writeI64((*(this->limit))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t AssocService_taoAssocRangeGet_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_LIST) { + { + this->success.clear(); + uint32_t _size43; + apache::thrift::protocol::TType _etype46; + xfer += iprot->readListBegin(_etype46, _size43); + this->success.resize(_size43); + uint32_t _i47; + for (_i47 = 0; _i47 < _size43; ++_i47) + { + xfer += this->success[_i47].read(iprot); + } + xfer += iprot->readListEnd(); + } + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->io.read(iprot); + this->__isset.io = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t AssocService_taoAssocRangeGet_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("AssocService_taoAssocRangeGet_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_LIST, 0); + { + xfer += oprot->writeListBegin(apache::thrift::protocol::T_STRUCT, this->success.size()); + std::vector ::const_iterator _iter48; + for (_iter48 = this->success.begin(); _iter48 != this->success.end(); ++_iter48) + { + xfer += (*_iter48).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + } else if (this->__isset.io) { + xfer += oprot->writeFieldBegin("io", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->io.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t AssocService_taoAssocRangeGet_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_LIST) { + { + (*(this->success)).clear(); + uint32_t _size49; + apache::thrift::protocol::TType _etype52; + xfer += iprot->readListBegin(_etype52, _size49); + (*(this->success)).resize(_size49); + uint32_t _i53; + for (_i53 = 0; _i53 < _size49; ++_i53) + { + xfer += (*(this->success))[_i53].read(iprot); + } + xfer += iprot->readListEnd(); + } + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->io.read(iprot); + this->__isset.io = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t AssocService_taoAssocGet_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->tableName); + this->__isset.tableName = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->assocType); + this->__isset.assocType = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->id1); + this->__isset.id1 = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == apache::thrift::protocol::T_LIST) { + { + this->id2s.clear(); + uint32_t _size54; + apache::thrift::protocol::TType _etype57; + xfer += iprot->readListBegin(_etype57, _size54); + this->id2s.resize(_size54); + uint32_t _i58; + for (_i58 = 0; _i58 < _size54; ++_i58) + { + xfer += iprot->readI64(this->id2s[_i58]); + } + xfer += iprot->readListEnd(); + } + this->__isset.id2s = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t AssocService_taoAssocGet_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("AssocService_taoAssocGet_args"); + xfer += oprot->writeFieldBegin("tableName", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary(this->tableName); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("assocType", apache::thrift::protocol::T_I64, 2); + xfer += oprot->writeI64(this->assocType); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id1", apache::thrift::protocol::T_I64, 3); + xfer += oprot->writeI64(this->id1); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id2s", apache::thrift::protocol::T_LIST, 4); + { + xfer += oprot->writeListBegin(apache::thrift::protocol::T_I64, this->id2s.size()); + std::vector ::const_iterator _iter59; + for (_iter59 = this->id2s.begin(); _iter59 != this->id2s.end(); ++_iter59) + { + xfer += oprot->writeI64((*_iter59)); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t AssocService_taoAssocGet_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("AssocService_taoAssocGet_pargs"); + xfer += oprot->writeFieldBegin("tableName", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary((*(this->tableName))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("assocType", apache::thrift::protocol::T_I64, 2); + xfer += oprot->writeI64((*(this->assocType))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id1", apache::thrift::protocol::T_I64, 3); + xfer += oprot->writeI64((*(this->id1))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id2s", apache::thrift::protocol::T_LIST, 4); + { + xfer += oprot->writeListBegin(apache::thrift::protocol::T_I64, (*(this->id2s)).size()); + std::vector ::const_iterator _iter60; + for (_iter60 = (*(this->id2s)).begin(); _iter60 != (*(this->id2s)).end(); ++_iter60) + { + xfer += oprot->writeI64((*_iter60)); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t AssocService_taoAssocGet_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_LIST) { + { + this->success.clear(); + uint32_t _size61; + apache::thrift::protocol::TType _etype64; + xfer += iprot->readListBegin(_etype64, _size61); + this->success.resize(_size61); + uint32_t _i65; + for (_i65 = 0; _i65 < _size61; ++_i65) + { + xfer += this->success[_i65].read(iprot); + } + xfer += iprot->readListEnd(); + } + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->io.read(iprot); + this->__isset.io = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t AssocService_taoAssocGet_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("AssocService_taoAssocGet_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_LIST, 0); + { + xfer += oprot->writeListBegin(apache::thrift::protocol::T_STRUCT, this->success.size()); + std::vector ::const_iterator _iter66; + for (_iter66 = this->success.begin(); _iter66 != this->success.end(); ++_iter66) + { + xfer += (*_iter66).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + } else if (this->__isset.io) { + xfer += oprot->writeFieldBegin("io", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->io.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t AssocService_taoAssocGet_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_LIST) { + { + (*(this->success)).clear(); + uint32_t _size67; + apache::thrift::protocol::TType _etype70; + xfer += iprot->readListBegin(_etype70, _size67); + (*(this->success)).resize(_size67); + uint32_t _i71; + for (_i71 = 0; _i71 < _size67; ++_i71) + { + xfer += (*(this->success))[_i71].read(iprot); + } + xfer += iprot->readListEnd(); + } + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->io.read(iprot); + this->__isset.io = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t AssocService_taoAssocCount_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->tableName); + this->__isset.tableName = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->assocType); + this->__isset.assocType = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->id1); + this->__isset.id1 = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t AssocService_taoAssocCount_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("AssocService_taoAssocCount_args"); + xfer += oprot->writeFieldBegin("tableName", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary(this->tableName); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("assocType", apache::thrift::protocol::T_I64, 2); + xfer += oprot->writeI64(this->assocType); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id1", apache::thrift::protocol::T_I64, 3); + xfer += oprot->writeI64(this->id1); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t AssocService_taoAssocCount_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("AssocService_taoAssocCount_pargs"); + xfer += oprot->writeFieldBegin("tableName", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary((*(this->tableName))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("assocType", apache::thrift::protocol::T_I64, 2); + xfer += oprot->writeI64((*(this->assocType))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id1", apache::thrift::protocol::T_I64, 3); + xfer += oprot->writeI64((*(this->id1))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t AssocService_taoAssocCount_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->success); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->io.read(iprot); + this->__isset.io = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t AssocService_taoAssocCount_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("AssocService_taoAssocCount_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_I64, 0); + xfer += oprot->writeI64(this->success); + xfer += oprot->writeFieldEnd(); + } else if (this->__isset.io) { + xfer += oprot->writeFieldBegin("io", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->io.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t AssocService_taoAssocCount_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64((*(this->success))); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->io.read(iprot); + this->__isset.io = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +int32_t AssocServiceClient::getNextSendSequenceId() +{ + return nextSendSequenceId_++; +} + +int32_t AssocServiceClient::getNextRecvSequenceId() +{ + return nextRecvSequenceId_++; +} + +int64_t AssocServiceClient::taoAssocPut(const Text& tableName, int64_t assocType, int64_t id1, int64_t id2, int64_t id1Type, int64_t id2Type, int64_t timestamp, AssocVisibility visibility, bool update_count, int64_t dataVersion, const Text& data, const Text& wormhole_comment) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("AssocService.taoAssocPut", NULL); + + try { + send_taoAssocPut(tableName, assocType, id1, id2, id1Type, id2Type, timestamp, visibility, update_count, dataVersion, data, wormhole_comment); + return recv_taoAssocPut(); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "AssocService.taoAssocPut"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "AssocService.taoAssocPut"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void AssocServiceClient::send_taoAssocPut(const Text& tableName, int64_t assocType, int64_t id1, int64_t id2, int64_t id1Type, int64_t id2Type, int64_t timestamp, AssocVisibility visibility, bool update_count, int64_t dataVersion, const Text& data, const Text& wormhole_comment) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "AssocService.taoAssocPut"); + oprot_->writeMessageBegin("taoAssocPut", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + AssocService_taoAssocPut_pargs args; + args.tableName = &tableName; + args.assocType = &assocType; + args.id1 = &id1; + args.id2 = &id2; + args.id1Type = &id1Type; + args.id2Type = &id2Type; + args.timestamp = ×tamp; + args.visibility = &visibility; + args.update_count = &update_count; + args.dataVersion = &dataVersion; + args.data = &data; + args.wormhole_comment = &wormhole_comment; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes72 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "AssocService.taoAssocPut", _bytes72); + return; +} + +int64_t AssocServiceClient::recv_taoAssocPut() +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "AssocService.taoAssocPut"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("taoAssocPut") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + int64_t _return; + AssocService_taoAssocPut_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "AssocService.taoAssocPut", bytes); + + if (result.__isset.success) { + return _return; + } + if (result.__isset.io) { + throw result.io; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "taoAssocPut failed: unknown result"); +} + +int64_t AssocServiceClient::taoAssocDelete(const Text& tableName, int64_t assocType, int64_t id1, int64_t id2, AssocVisibility visibility, bool update_count, const Text& wormhole_comment) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("AssocService.taoAssocDelete", NULL); + + try { + send_taoAssocDelete(tableName, assocType, id1, id2, visibility, update_count, wormhole_comment); + return recv_taoAssocDelete(); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "AssocService.taoAssocDelete"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "AssocService.taoAssocDelete"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void AssocServiceClient::send_taoAssocDelete(const Text& tableName, int64_t assocType, int64_t id1, int64_t id2, AssocVisibility visibility, bool update_count, const Text& wormhole_comment) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "AssocService.taoAssocDelete"); + oprot_->writeMessageBegin("taoAssocDelete", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + AssocService_taoAssocDelete_pargs args; + args.tableName = &tableName; + args.assocType = &assocType; + args.id1 = &id1; + args.id2 = &id2; + args.visibility = &visibility; + args.update_count = &update_count; + args.wormhole_comment = &wormhole_comment; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes73 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "AssocService.taoAssocDelete", _bytes73); + return; +} + +int64_t AssocServiceClient::recv_taoAssocDelete() +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "AssocService.taoAssocDelete"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("taoAssocDelete") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + int64_t _return; + AssocService_taoAssocDelete_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "AssocService.taoAssocDelete", bytes); + + if (result.__isset.success) { + return _return; + } + if (result.__isset.io) { + throw result.io; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "taoAssocDelete failed: unknown result"); +} + +void AssocServiceClient::taoAssocRangeGet(std::vector & _return, const Text& tableName, int64_t assocType, int64_t id1, int64_t start_time, int64_t end_time, int64_t offset, int64_t limit) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("AssocService.taoAssocRangeGet", NULL); + + try { + send_taoAssocRangeGet(tableName, assocType, id1, start_time, end_time, offset, limit); + recv_taoAssocRangeGet(_return); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "AssocService.taoAssocRangeGet"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "AssocService.taoAssocRangeGet"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void AssocServiceClient::send_taoAssocRangeGet(const Text& tableName, int64_t assocType, int64_t id1, int64_t start_time, int64_t end_time, int64_t offset, int64_t limit) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "AssocService.taoAssocRangeGet"); + oprot_->writeMessageBegin("taoAssocRangeGet", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + AssocService_taoAssocRangeGet_pargs args; + args.tableName = &tableName; + args.assocType = &assocType; + args.id1 = &id1; + args.start_time = &start_time; + args.end_time = &end_time; + args.offset = &offset; + args.limit = &limit; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes74 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "AssocService.taoAssocRangeGet", _bytes74); + return; +} + +void AssocServiceClient::recv_taoAssocRangeGet(std::vector & _return) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "AssocService.taoAssocRangeGet"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("taoAssocRangeGet") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + AssocService_taoAssocRangeGet_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "AssocService.taoAssocRangeGet", bytes); + + if (result.__isset.success) { + // _return pointer has now been filled + return; + } + if (result.__isset.io) { + throw result.io; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "taoAssocRangeGet failed: unknown result"); +} + +void AssocServiceClient::taoAssocGet(std::vector & _return, const Text& tableName, int64_t assocType, int64_t id1, const std::vector & id2s) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("AssocService.taoAssocGet", NULL); + + try { + send_taoAssocGet(tableName, assocType, id1, id2s); + recv_taoAssocGet(_return); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "AssocService.taoAssocGet"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "AssocService.taoAssocGet"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void AssocServiceClient::send_taoAssocGet(const Text& tableName, int64_t assocType, int64_t id1, const std::vector & id2s) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "AssocService.taoAssocGet"); + oprot_->writeMessageBegin("taoAssocGet", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + AssocService_taoAssocGet_pargs args; + args.tableName = &tableName; + args.assocType = &assocType; + args.id1 = &id1; + args.id2s = &id2s; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes75 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "AssocService.taoAssocGet", _bytes75); + return; +} + +void AssocServiceClient::recv_taoAssocGet(std::vector & _return) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "AssocService.taoAssocGet"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("taoAssocGet") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + AssocService_taoAssocGet_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "AssocService.taoAssocGet", bytes); + + if (result.__isset.success) { + // _return pointer has now been filled + return; + } + if (result.__isset.io) { + throw result.io; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "taoAssocGet failed: unknown result"); +} + +int64_t AssocServiceClient::taoAssocCount(const Text& tableName, int64_t assocType, int64_t id1) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("AssocService.taoAssocCount", NULL); + + try { + send_taoAssocCount(tableName, assocType, id1); + return recv_taoAssocCount(); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "AssocService.taoAssocCount"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "AssocService.taoAssocCount"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void AssocServiceClient::send_taoAssocCount(const Text& tableName, int64_t assocType, int64_t id1) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "AssocService.taoAssocCount"); + oprot_->writeMessageBegin("taoAssocCount", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + AssocService_taoAssocCount_pargs args; + args.tableName = &tableName; + args.assocType = &assocType; + args.id1 = &id1; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes76 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "AssocService.taoAssocCount", _bytes76); + return; +} + +int64_t AssocServiceClient::recv_taoAssocCount() +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "AssocService.taoAssocCount"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("taoAssocCount") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + int64_t _return; + AssocService_taoAssocCount_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "AssocService.taoAssocCount", bytes); + + if (result.__isset.success) { + return _return; + } + if (result.__isset.io) { + throw result.io; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "taoAssocCount failed: unknown result"); +} + +bool AssocServiceProcessor::dispatchCall(::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, const std::string& fname, int32_t seqid, apache::thrift::server::TConnectionContext* connectionContext) { + ProcessMap::iterator pfn; + pfn = processMap_.find(fname); + if (pfn == processMap_.end()) { + iprot->skip(apache::thrift::protocol::T_STRUCT); + iprot->readMessageEnd(); + iprot->getTransport()->readEnd(); + apache::thrift::TApplicationException x(apache::thrift::TApplicationException::UNKNOWN_METHOD, "Invalid method name: '"+fname+"'"); + oprot->writeMessageBegin(fname, apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return true; + } + const ProcessFunction& pf = pfn->second; + (this->*pf)(seqid, iprot, oprot, connectionContext); + return true; +} + +void AssocServiceProcessor::process_taoAssocPut(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("AssocService.taoAssocPut", connectionContext)); + + this->preRead(ctx.get(), "AssocService.taoAssocPut"); + AssocService_taoAssocPut_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "AssocService.taoAssocPut", bytes); + + AssocService_taoAssocPut_result result; + try { + result.success = iface_->taoAssocPut(args.tableName, args.assocType, args.id1, args.id2, args.id1Type, args.id2Type, args.timestamp, args.visibility, args.update_count, args.dataVersion, args.data, args.wormhole_comment); + result.__isset.success = true; + } catch (IOError &io) { + result.io = io; + result.__isset.io = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "AssocService.taoAssocPut"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("taoAssocPut", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "AssocService.taoAssocPut"); + oprot->writeMessageBegin("taoAssocPut", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "AssocService.taoAssocPut", bytes); + +} + +void AssocServiceProcessor::process_taoAssocDelete(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("AssocService.taoAssocDelete", connectionContext)); + + this->preRead(ctx.get(), "AssocService.taoAssocDelete"); + AssocService_taoAssocDelete_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "AssocService.taoAssocDelete", bytes); + + AssocService_taoAssocDelete_result result; + try { + result.success = iface_->taoAssocDelete(args.tableName, args.assocType, args.id1, args.id2, args.visibility, args.update_count, args.wormhole_comment); + result.__isset.success = true; + } catch (IOError &io) { + result.io = io; + result.__isset.io = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "AssocService.taoAssocDelete"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("taoAssocDelete", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "AssocService.taoAssocDelete"); + oprot->writeMessageBegin("taoAssocDelete", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "AssocService.taoAssocDelete", bytes); + +} + +void AssocServiceProcessor::process_taoAssocRangeGet(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("AssocService.taoAssocRangeGet", connectionContext)); + + this->preRead(ctx.get(), "AssocService.taoAssocRangeGet"); + AssocService_taoAssocRangeGet_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "AssocService.taoAssocRangeGet", bytes); + + AssocService_taoAssocRangeGet_result result; + try { + iface_->taoAssocRangeGet(result.success, args.tableName, args.assocType, args.id1, args.start_time, args.end_time, args.offset, args.limit); + result.__isset.success = true; + } catch (IOError &io) { + result.io = io; + result.__isset.io = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "AssocService.taoAssocRangeGet"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("taoAssocRangeGet", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "AssocService.taoAssocRangeGet"); + oprot->writeMessageBegin("taoAssocRangeGet", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "AssocService.taoAssocRangeGet", bytes); + +} + +void AssocServiceProcessor::process_taoAssocGet(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("AssocService.taoAssocGet", connectionContext)); + + this->preRead(ctx.get(), "AssocService.taoAssocGet"); + AssocService_taoAssocGet_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "AssocService.taoAssocGet", bytes); + + AssocService_taoAssocGet_result result; + try { + iface_->taoAssocGet(result.success, args.tableName, args.assocType, args.id1, args.id2s); + result.__isset.success = true; + } catch (IOError &io) { + result.io = io; + result.__isset.io = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "AssocService.taoAssocGet"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("taoAssocGet", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "AssocService.taoAssocGet"); + oprot->writeMessageBegin("taoAssocGet", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "AssocService.taoAssocGet", bytes); + +} + +void AssocServiceProcessor::process_taoAssocCount(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("AssocService.taoAssocCount", connectionContext)); + + this->preRead(ctx.get(), "AssocService.taoAssocCount"); + AssocService_taoAssocCount_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "AssocService.taoAssocCount", bytes); + + AssocService_taoAssocCount_result result; + try { + result.success = iface_->taoAssocCount(args.tableName, args.assocType, args.id1); + result.__isset.success = true; + } catch (IOError &io) { + result.io = io; + result.__isset.io = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "AssocService.taoAssocCount"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("taoAssocCount", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "AssocService.taoAssocCount"); + oprot->writeMessageBegin("taoAssocCount", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "AssocService.taoAssocCount", bytes); + +} + +::boost::shared_ptr< ::apache::thrift::TProcessor > AssocServiceProcessorFactory::getProcessor(::apache::thrift::server::TConnectionContext* ctx) { + ::apache::thrift::ReleaseHandler< AssocServiceIfFactory > cleanup(handlerFactory_); + ::boost::shared_ptr< AssocServiceIf > handler(handlerFactory_->getHandler(ctx), cleanup); + ::boost::shared_ptr< ::apache::thrift::TProcessor > processor(new AssocServiceProcessor(handler)); + return processor; +} +} // namespace + diff --git a/thrift/gen-cpp/AssocService.h b/thrift/gen-cpp/AssocService.h new file mode 100644 index 00000000..ad588eac --- /dev/null +++ b/thrift/gen-cpp/AssocService.h @@ -0,0 +1,1132 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef _Tleveldb_AssocService_H +#define _Tleveldb_AssocService_H + +#include +#include "leveldb_types.h" + +namespace Tleveldb { + +class AssocServiceIf { + public: + virtual ~AssocServiceIf() {} + virtual int64_t taoAssocPut(const Text& tableName, int64_t assocType, int64_t id1, int64_t id2, int64_t id1Type, int64_t id2Type, int64_t timestamp, AssocVisibility visibility, bool update_count, int64_t dataVersion, const Text& data, const Text& wormhole_comment) = 0; + virtual int64_t taoAssocDelete(const Text& tableName, int64_t assocType, int64_t id1, int64_t id2, AssocVisibility visibility, bool update_count, const Text& wormhole_comment) = 0; + virtual void taoAssocRangeGet(std::vector & _return, const Text& tableName, int64_t assocType, int64_t id1, int64_t start_time, int64_t end_time, int64_t offset, int64_t limit) = 0; + virtual void taoAssocGet(std::vector & _return, const Text& tableName, int64_t assocType, int64_t id1, const std::vector & id2s) = 0; + virtual int64_t taoAssocCount(const Text& tableName, int64_t assocType, int64_t id1) = 0; +}; + +class AssocServiceIfFactory { + public: + typedef AssocServiceIf Handler; + + virtual ~AssocServiceIfFactory() {} + + virtual AssocServiceIf* getHandler(::apache::thrift::server::TConnectionContext* ctx) = 0; + virtual void releaseHandler(AssocServiceIf* handler) = 0; +}; + +class AssocServiceIfSingletonFactory : virtual public AssocServiceIfFactory { + public: + AssocServiceIfSingletonFactory(const boost::shared_ptr& iface) : iface_(iface) {} + virtual ~AssocServiceIfSingletonFactory() {} + + virtual AssocServiceIf* getHandler(::apache::thrift::server::TConnectionContext*) { + return iface_.get(); + } + virtual void releaseHandler(AssocServiceIf* handler) {} + + protected: + boost::shared_ptr iface_; +}; + +class AssocServiceNull : virtual public AssocServiceIf { + public: + virtual ~AssocServiceNull() {} + int64_t taoAssocPut(const Text& /* tableName */, int64_t /* assocType */, int64_t /* id1 */, int64_t /* id2 */, int64_t /* id1Type */, int64_t /* id2Type */, int64_t /* timestamp */, AssocVisibility /* visibility */, bool /* update_count */, int64_t /* dataVersion */, const Text& /* data */, const Text& /* wormhole_comment */) { + int64_t _return = 0; + return _return; + } + int64_t taoAssocDelete(const Text& /* tableName */, int64_t /* assocType */, int64_t /* id1 */, int64_t /* id2 */, AssocVisibility /* visibility */, bool /* update_count */, const Text& /* wormhole_comment */) { + int64_t _return = 0; + return _return; + } + void taoAssocRangeGet(std::vector & /* _return */, const Text& /* tableName */, int64_t /* assocType */, int64_t /* id1 */, int64_t /* start_time */, int64_t /* end_time */, int64_t /* offset */, int64_t /* limit */) { + return; + } + void taoAssocGet(std::vector & /* _return */, const Text& /* tableName */, int64_t /* assocType */, int64_t /* id1 */, const std::vector & /* id2s */) { + return; + } + int64_t taoAssocCount(const Text& /* tableName */, int64_t /* assocType */, int64_t /* id1 */) { + int64_t _return = 0; + return _return; + } +}; + +class AssocService_taoAssocPut_args { + public: + + static const uint64_t _reflection_id = 3290305132890847884U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + AssocService_taoAssocPut_args() : tableName(""), assocType(0), id1(0), id2(0), id1Type(0), id2Type(0), timestamp(0), visibility(static_cast(0)), update_count(0), dataVersion(0), data(""), wormhole_comment("") { + } + + AssocService_taoAssocPut_args(const AssocService_taoAssocPut_args&) = default; + AssocService_taoAssocPut_args& operator=(const AssocService_taoAssocPut_args&) = default; + AssocService_taoAssocPut_args(AssocService_taoAssocPut_args&&) = default; + AssocService_taoAssocPut_args& operator=(AssocService_taoAssocPut_args&&) = default; + + void __clear() { + tableName = ""; + assocType = 0; + id1 = 0; + id2 = 0; + id1Type = 0; + id2Type = 0; + timestamp = 0; + visibility = static_cast(0); + update_count = 0; + dataVersion = 0; + data = ""; + wormhole_comment = ""; + __isset.__clear(); + } + + virtual ~AssocService_taoAssocPut_args() throw() {} + + Text tableName; + int64_t assocType; + int64_t id1; + int64_t id2; + int64_t id1Type; + int64_t id2Type; + int64_t timestamp; + AssocVisibility visibility; + bool update_count; + int64_t dataVersion; + Text data; + Text wormhole_comment; + + struct __isset { + __isset() { __clear(); } + void __clear() { + tableName = false; + assocType = false; + id1 = false; + id2 = false; + id1Type = false; + id2Type = false; + timestamp = false; + visibility = false; + update_count = false; + dataVersion = false; + data = false; + wormhole_comment = false; + } + bool tableName; + bool assocType; + bool id1; + bool id2; + bool id1Type; + bool id2Type; + bool timestamp; + bool visibility; + bool update_count; + bool dataVersion; + bool data; + bool wormhole_comment; + } __isset; + + bool operator == (const AssocService_taoAssocPut_args & rhs) const + { + if (!(this->tableName == rhs.tableName)) + return false; + if (!(this->assocType == rhs.assocType)) + return false; + if (!(this->id1 == rhs.id1)) + return false; + if (!(this->id2 == rhs.id2)) + return false; + if (!(this->id1Type == rhs.id1Type)) + return false; + if (!(this->id2Type == rhs.id2Type)) + return false; + if (!(this->timestamp == rhs.timestamp)) + return false; + if (!(this->visibility == rhs.visibility)) + return false; + if (!(this->update_count == rhs.update_count)) + return false; + if (!(this->dataVersion == rhs.dataVersion)) + return false; + if (!(this->data == rhs.data)) + return false; + if (!(this->wormhole_comment == rhs.wormhole_comment)) + return false; + return true; + } + bool operator != (const AssocService_taoAssocPut_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const AssocService_taoAssocPut_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class AssocService_taoAssocPut_pargs { + public: + + static const uint64_t _reflection_id = 7425952401724740620U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~AssocService_taoAssocPut_pargs() throw() {} + + const Text* tableName; + const int64_t* assocType; + const int64_t* id1; + const int64_t* id2; + const int64_t* id1Type; + const int64_t* id2Type; + const int64_t* timestamp; + const AssocVisibility* visibility; + const bool* update_count; + const int64_t* dataVersion; + const Text* data; + const Text* wormhole_comment; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class AssocService_taoAssocPut_result { + public: + + static const uint64_t _reflection_id = 6526721986074776780U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + AssocService_taoAssocPut_result() : success(0) { + } + + AssocService_taoAssocPut_result(const AssocService_taoAssocPut_result&) = default; + AssocService_taoAssocPut_result& operator=(const AssocService_taoAssocPut_result&) = default; + AssocService_taoAssocPut_result(AssocService_taoAssocPut_result&&) = default; + AssocService_taoAssocPut_result& operator=(AssocService_taoAssocPut_result&&) = default; + + void __clear() { + success = 0; + io.__clear(); + __isset.__clear(); + } + + virtual ~AssocService_taoAssocPut_result() throw() {} + + int64_t success; + IOError io; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + io = false; + } + bool success; + bool io; + } __isset; + + bool operator == (const AssocService_taoAssocPut_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + if (!(this->io == rhs.io)) + return false; + return true; + } + bool operator != (const AssocService_taoAssocPut_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const AssocService_taoAssocPut_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class AssocService_taoAssocPut_presult { + public: + + static const uint64_t _reflection_id = 12671665598022141484U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~AssocService_taoAssocPut_presult() throw() {} + + int64_t* success; + IOError io; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + io = false; + } + bool success; + bool io; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class AssocService_taoAssocDelete_args { + public: + + static const uint64_t _reflection_id = 10270079889653832204U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + AssocService_taoAssocDelete_args() : tableName(""), assocType(0), id1(0), id2(0), visibility(static_cast(0)), update_count(0), wormhole_comment("") { + } + + AssocService_taoAssocDelete_args(const AssocService_taoAssocDelete_args&) = default; + AssocService_taoAssocDelete_args& operator=(const AssocService_taoAssocDelete_args&) = default; + AssocService_taoAssocDelete_args(AssocService_taoAssocDelete_args&&) = default; + AssocService_taoAssocDelete_args& operator=(AssocService_taoAssocDelete_args&&) = default; + + void __clear() { + tableName = ""; + assocType = 0; + id1 = 0; + id2 = 0; + visibility = static_cast(0); + update_count = 0; + wormhole_comment = ""; + __isset.__clear(); + } + + virtual ~AssocService_taoAssocDelete_args() throw() {} + + Text tableName; + int64_t assocType; + int64_t id1; + int64_t id2; + AssocVisibility visibility; + bool update_count; + Text wormhole_comment; + + struct __isset { + __isset() { __clear(); } + void __clear() { + tableName = false; + assocType = false; + id1 = false; + id2 = false; + visibility = false; + update_count = false; + wormhole_comment = false; + } + bool tableName; + bool assocType; + bool id1; + bool id2; + bool visibility; + bool update_count; + bool wormhole_comment; + } __isset; + + bool operator == (const AssocService_taoAssocDelete_args & rhs) const + { + if (!(this->tableName == rhs.tableName)) + return false; + if (!(this->assocType == rhs.assocType)) + return false; + if (!(this->id1 == rhs.id1)) + return false; + if (!(this->id2 == rhs.id2)) + return false; + if (!(this->visibility == rhs.visibility)) + return false; + if (!(this->update_count == rhs.update_count)) + return false; + if (!(this->wormhole_comment == rhs.wormhole_comment)) + return false; + return true; + } + bool operator != (const AssocService_taoAssocDelete_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const AssocService_taoAssocDelete_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class AssocService_taoAssocDelete_pargs { + public: + + static const uint64_t _reflection_id = 4795542044867620812U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~AssocService_taoAssocDelete_pargs() throw() {} + + const Text* tableName; + const int64_t* assocType; + const int64_t* id1; + const int64_t* id2; + const AssocVisibility* visibility; + const bool* update_count; + const Text* wormhole_comment; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class AssocService_taoAssocDelete_result { + public: + + static const uint64_t _reflection_id = 12133907334276134572U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + AssocService_taoAssocDelete_result() : success(0) { + } + + AssocService_taoAssocDelete_result(const AssocService_taoAssocDelete_result&) = default; + AssocService_taoAssocDelete_result& operator=(const AssocService_taoAssocDelete_result&) = default; + AssocService_taoAssocDelete_result(AssocService_taoAssocDelete_result&&) = default; + AssocService_taoAssocDelete_result& operator=(AssocService_taoAssocDelete_result&&) = default; + + void __clear() { + success = 0; + io.__clear(); + __isset.__clear(); + } + + virtual ~AssocService_taoAssocDelete_result() throw() {} + + int64_t success; + IOError io; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + io = false; + } + bool success; + bool io; + } __isset; + + bool operator == (const AssocService_taoAssocDelete_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + if (!(this->io == rhs.io)) + return false; + return true; + } + bool operator != (const AssocService_taoAssocDelete_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const AssocService_taoAssocDelete_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class AssocService_taoAssocDelete_presult { + public: + + static const uint64_t _reflection_id = 14125941752039435212U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~AssocService_taoAssocDelete_presult() throw() {} + + int64_t* success; + IOError io; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + io = false; + } + bool success; + bool io; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class AssocService_taoAssocRangeGet_args { + public: + + static const uint64_t _reflection_id = 1735721774207336108U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + AssocService_taoAssocRangeGet_args() : tableName(""), assocType(0), id1(0), start_time(0), end_time(0), offset(0), limit(0) { + } + + AssocService_taoAssocRangeGet_args(const AssocService_taoAssocRangeGet_args&) = default; + AssocService_taoAssocRangeGet_args& operator=(const AssocService_taoAssocRangeGet_args&) = default; + AssocService_taoAssocRangeGet_args(AssocService_taoAssocRangeGet_args&&) = default; + AssocService_taoAssocRangeGet_args& operator=(AssocService_taoAssocRangeGet_args&&) = default; + + void __clear() { + tableName = ""; + assocType = 0; + id1 = 0; + start_time = 0; + end_time = 0; + offset = 0; + limit = 0; + __isset.__clear(); + } + + virtual ~AssocService_taoAssocRangeGet_args() throw() {} + + Text tableName; + int64_t assocType; + int64_t id1; + int64_t start_time; + int64_t end_time; + int64_t offset; + int64_t limit; + + struct __isset { + __isset() { __clear(); } + void __clear() { + tableName = false; + assocType = false; + id1 = false; + start_time = false; + end_time = false; + offset = false; + limit = false; + } + bool tableName; + bool assocType; + bool id1; + bool start_time; + bool end_time; + bool offset; + bool limit; + } __isset; + + bool operator == (const AssocService_taoAssocRangeGet_args & rhs) const + { + if (!(this->tableName == rhs.tableName)) + return false; + if (!(this->assocType == rhs.assocType)) + return false; + if (!(this->id1 == rhs.id1)) + return false; + if (!(this->start_time == rhs.start_time)) + return false; + if (!(this->end_time == rhs.end_time)) + return false; + if (!(this->offset == rhs.offset)) + return false; + if (!(this->limit == rhs.limit)) + return false; + return true; + } + bool operator != (const AssocService_taoAssocRangeGet_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const AssocService_taoAssocRangeGet_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class AssocService_taoAssocRangeGet_pargs { + public: + + static const uint64_t _reflection_id = 5056015852824808108U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~AssocService_taoAssocRangeGet_pargs() throw() {} + + const Text* tableName; + const int64_t* assocType; + const int64_t* id1; + const int64_t* start_time; + const int64_t* end_time; + const int64_t* offset; + const int64_t* limit; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class AssocService_taoAssocRangeGet_result { + public: + + static const uint64_t _reflection_id = 100254754914408876U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + AssocService_taoAssocRangeGet_result() { + } + + AssocService_taoAssocRangeGet_result(const AssocService_taoAssocRangeGet_result&) = default; + AssocService_taoAssocRangeGet_result& operator=(const AssocService_taoAssocRangeGet_result&) = default; + AssocService_taoAssocRangeGet_result(AssocService_taoAssocRangeGet_result&&) = default; + AssocService_taoAssocRangeGet_result& operator=(AssocService_taoAssocRangeGet_result&&) = default; + + void __clear() { + success.clear(); + io.__clear(); + __isset.__clear(); + } + + virtual ~AssocService_taoAssocRangeGet_result() throw() {} + + std::vector success; + IOError io; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + io = false; + } + bool success; + bool io; + } __isset; + + bool operator == (const AssocService_taoAssocRangeGet_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + if (!(this->io == rhs.io)) + return false; + return true; + } + bool operator != (const AssocService_taoAssocRangeGet_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const AssocService_taoAssocRangeGet_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class AssocService_taoAssocRangeGet_presult { + public: + + static const uint64_t _reflection_id = 10811387055164057228U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~AssocService_taoAssocRangeGet_presult() throw() {} + + std::vector * success; + IOError io; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + io = false; + } + bool success; + bool io; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class AssocService_taoAssocGet_args { + public: + + static const uint64_t _reflection_id = 16546497730627888492U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + AssocService_taoAssocGet_args() : tableName(""), assocType(0), id1(0) { + } + + AssocService_taoAssocGet_args(const AssocService_taoAssocGet_args&) = default; + AssocService_taoAssocGet_args& operator=(const AssocService_taoAssocGet_args&) = default; + AssocService_taoAssocGet_args(AssocService_taoAssocGet_args&&) = default; + AssocService_taoAssocGet_args& operator=(AssocService_taoAssocGet_args&&) = default; + + void __clear() { + tableName = ""; + assocType = 0; + id1 = 0; + id2s.clear(); + __isset.__clear(); + } + + virtual ~AssocService_taoAssocGet_args() throw() {} + + Text tableName; + int64_t assocType; + int64_t id1; + std::vector id2s; + + struct __isset { + __isset() { __clear(); } + void __clear() { + tableName = false; + assocType = false; + id1 = false; + id2s = false; + } + bool tableName; + bool assocType; + bool id1; + bool id2s; + } __isset; + + bool operator == (const AssocService_taoAssocGet_args & rhs) const + { + if (!(this->tableName == rhs.tableName)) + return false; + if (!(this->assocType == rhs.assocType)) + return false; + if (!(this->id1 == rhs.id1)) + return false; + if (!(this->id2s == rhs.id2s)) + return false; + return true; + } + bool operator != (const AssocService_taoAssocGet_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const AssocService_taoAssocGet_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class AssocService_taoAssocGet_pargs { + public: + + static const uint64_t _reflection_id = 9292472387579296684U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~AssocService_taoAssocGet_pargs() throw() {} + + const Text* tableName; + const int64_t* assocType; + const int64_t* id1; + const std::vector * id2s; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class AssocService_taoAssocGet_result { + public: + + static const uint64_t _reflection_id = 330126441639238892U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + AssocService_taoAssocGet_result() { + } + + AssocService_taoAssocGet_result(const AssocService_taoAssocGet_result&) = default; + AssocService_taoAssocGet_result& operator=(const AssocService_taoAssocGet_result&) = default; + AssocService_taoAssocGet_result(AssocService_taoAssocGet_result&&) = default; + AssocService_taoAssocGet_result& operator=(AssocService_taoAssocGet_result&&) = default; + + void __clear() { + success.clear(); + io.__clear(); + __isset.__clear(); + } + + virtual ~AssocService_taoAssocGet_result() throw() {} + + std::vector success; + IOError io; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + io = false; + } + bool success; + bool io; + } __isset; + + bool operator == (const AssocService_taoAssocGet_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + if (!(this->io == rhs.io)) + return false; + return true; + } + bool operator != (const AssocService_taoAssocGet_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const AssocService_taoAssocGet_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class AssocService_taoAssocGet_presult { + public: + + static const uint64_t _reflection_id = 230475374475192236U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~AssocService_taoAssocGet_presult() throw() {} + + std::vector * success; + IOError io; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + io = false; + } + bool success; + bool io; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class AssocService_taoAssocCount_args { + public: + + static const uint64_t _reflection_id = 769199732449473196U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + AssocService_taoAssocCount_args() : tableName(""), assocType(0), id1(0) { + } + + AssocService_taoAssocCount_args(const AssocService_taoAssocCount_args&) = default; + AssocService_taoAssocCount_args& operator=(const AssocService_taoAssocCount_args&) = default; + AssocService_taoAssocCount_args(AssocService_taoAssocCount_args&&) = default; + AssocService_taoAssocCount_args& operator=(AssocService_taoAssocCount_args&&) = default; + + void __clear() { + tableName = ""; + assocType = 0; + id1 = 0; + __isset.__clear(); + } + + virtual ~AssocService_taoAssocCount_args() throw() {} + + Text tableName; + int64_t assocType; + int64_t id1; + + struct __isset { + __isset() { __clear(); } + void __clear() { + tableName = false; + assocType = false; + id1 = false; + } + bool tableName; + bool assocType; + bool id1; + } __isset; + + bool operator == (const AssocService_taoAssocCount_args & rhs) const + { + if (!(this->tableName == rhs.tableName)) + return false; + if (!(this->assocType == rhs.assocType)) + return false; + if (!(this->id1 == rhs.id1)) + return false; + return true; + } + bool operator != (const AssocService_taoAssocCount_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const AssocService_taoAssocCount_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class AssocService_taoAssocCount_pargs { + public: + + static const uint64_t _reflection_id = 4871158744897524556U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~AssocService_taoAssocCount_pargs() throw() {} + + const Text* tableName; + const int64_t* assocType; + const int64_t* id1; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class AssocService_taoAssocCount_result { + public: + + static const uint64_t _reflection_id = 824429928060194060U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + AssocService_taoAssocCount_result() : success(0) { + } + + AssocService_taoAssocCount_result(const AssocService_taoAssocCount_result&) = default; + AssocService_taoAssocCount_result& operator=(const AssocService_taoAssocCount_result&) = default; + AssocService_taoAssocCount_result(AssocService_taoAssocCount_result&&) = default; + AssocService_taoAssocCount_result& operator=(AssocService_taoAssocCount_result&&) = default; + + void __clear() { + success = 0; + io.__clear(); + __isset.__clear(); + } + + virtual ~AssocService_taoAssocCount_result() throw() {} + + int64_t success; + IOError io; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + io = false; + } + bool success; + bool io; + } __isset; + + bool operator == (const AssocService_taoAssocCount_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + if (!(this->io == rhs.io)) + return false; + return true; + } + bool operator != (const AssocService_taoAssocCount_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const AssocService_taoAssocCount_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class AssocService_taoAssocCount_presult { + public: + + static const uint64_t _reflection_id = 7130695620086441804U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~AssocService_taoAssocCount_presult() throw() {} + + int64_t* success; + IOError io; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + io = false; + } + bool success; + bool io; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class AssocServiceClient : virtual public AssocServiceIf, virtual public apache::thrift::TClientBase { + public: + AssocServiceClient(boost::shared_ptr prot) : + checkSeqid_(true), + nextSendSequenceId_(1), + nextRecvSequenceId_(1), + piprot_(prot), + poprot_(prot) { + iprot_ = prot.get(); + oprot_ = prot.get(); + } + AssocServiceClient(boost::shared_ptr iprot, boost::shared_ptr oprot) : + checkSeqid_(true), + nextSendSequenceId_(1), + nextRecvSequenceId_(1), + piprot_(iprot), + poprot_(oprot) { + iprot_ = iprot.get(); + oprot_ = oprot.get(); + } + boost::shared_ptr getInputProtocol() { + return piprot_; + } + boost::shared_ptr getOutputProtocol() { + return poprot_; + } + int64_t taoAssocPut(const Text& tableName, int64_t assocType, int64_t id1, int64_t id2, int64_t id1Type, int64_t id2Type, int64_t timestamp, AssocVisibility visibility, bool update_count, int64_t dataVersion, const Text& data, const Text& wormhole_comment); + void send_taoAssocPut(const Text& tableName, int64_t assocType, int64_t id1, int64_t id2, int64_t id1Type, int64_t id2Type, int64_t timestamp, AssocVisibility visibility, bool update_count, int64_t dataVersion, const Text& data, const Text& wormhole_comment); + int64_t recv_taoAssocPut(); + int64_t taoAssocDelete(const Text& tableName, int64_t assocType, int64_t id1, int64_t id2, AssocVisibility visibility, bool update_count, const Text& wormhole_comment); + void send_taoAssocDelete(const Text& tableName, int64_t assocType, int64_t id1, int64_t id2, AssocVisibility visibility, bool update_count, const Text& wormhole_comment); + int64_t recv_taoAssocDelete(); + void taoAssocRangeGet(std::vector & _return, const Text& tableName, int64_t assocType, int64_t id1, int64_t start_time, int64_t end_time, int64_t offset, int64_t limit); + void send_taoAssocRangeGet(const Text& tableName, int64_t assocType, int64_t id1, int64_t start_time, int64_t end_time, int64_t offset, int64_t limit); + void recv_taoAssocRangeGet(std::vector & _return); + void taoAssocGet(std::vector & _return, const Text& tableName, int64_t assocType, int64_t id1, const std::vector & id2s); + void send_taoAssocGet(const Text& tableName, int64_t assocType, int64_t id1, const std::vector & id2s); + void recv_taoAssocGet(std::vector & _return); + int64_t taoAssocCount(const Text& tableName, int64_t assocType, int64_t id1); + void send_taoAssocCount(const Text& tableName, int64_t assocType, int64_t id1); + int64_t recv_taoAssocCount(); + + /** + * Disable checking the seqid field in server responses. + * + * This should only be used with broken servers that return incorrect seqid values. + */ + void _disableSequenceIdChecks() { + checkSeqid_ = false; + } + + protected: + bool checkSeqid_; + int32_t nextSendSequenceId_; + int32_t nextRecvSequenceId_; + int32_t getNextSendSequenceId(); + int32_t getNextRecvSequenceId(); + boost::shared_ptr piprot_; + boost::shared_ptr poprot_; + apache::thrift::protocol::TProtocol* iprot_; + apache::thrift::protocol::TProtocol* oprot_; +}; + +class AssocServiceProcessor : public ::apache::thrift::TDispatchProcessor { + protected: + boost::shared_ptr iface_; + virtual bool dispatchCall(apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, const std::string& fname, int32_t seqid, apache::thrift::server::TConnectionContext* connectionContext); + private: + typedef void (AssocServiceProcessor::*ProcessFunction)(int32_t, apache::thrift::protocol::TProtocol*, apache::thrift::protocol::TProtocol*, apache::thrift::server::TConnectionContext*); + typedef std::map ProcessMap; + ProcessMap processMap_; + void process_taoAssocPut(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + void process_taoAssocDelete(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + void process_taoAssocRangeGet(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + void process_taoAssocGet(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + void process_taoAssocCount(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + public: + AssocServiceProcessor(boost::shared_ptr iface) : + iface_(iface) { + processMap_["taoAssocPut"] = &AssocServiceProcessor::process_taoAssocPut; + processMap_["taoAssocDelete"] = &AssocServiceProcessor::process_taoAssocDelete; + processMap_["taoAssocRangeGet"] = &AssocServiceProcessor::process_taoAssocRangeGet; + processMap_["taoAssocGet"] = &AssocServiceProcessor::process_taoAssocGet; + processMap_["taoAssocCount"] = &AssocServiceProcessor::process_taoAssocCount; + } + + virtual ~AssocServiceProcessor() {} + + boost::shared_ptr > getProcessFunctions() { + boost::shared_ptr > rSet(new std::set()); + rSet->insert("AssocService.taoAssocPut"); + rSet->insert("AssocService.taoAssocDelete"); + rSet->insert("AssocService.taoAssocRangeGet"); + rSet->insert("AssocService.taoAssocGet"); + rSet->insert("AssocService.taoAssocCount"); + return rSet; + } +}; + +class AssocServiceProcessorFactory : public ::apache::thrift::TProcessorFactory { + public: + AssocServiceProcessorFactory(const ::boost::shared_ptr< AssocServiceIfFactory >& handlerFactory) : + handlerFactory_(handlerFactory) {} + + ::boost::shared_ptr< ::apache::thrift::TProcessor > getProcessor(::apache::thrift::server::TConnectionContext* ctx); + + protected: + ::boost::shared_ptr< AssocServiceIfFactory > handlerFactory_; +}; + +class AssocServiceMultiface : virtual public AssocServiceIf { + public: + AssocServiceMultiface(std::vector >& ifaces) : ifaces_(ifaces) { + } + virtual ~AssocServiceMultiface() {} + protected: + std::vector > ifaces_; + AssocServiceMultiface() {} + void add(boost::shared_ptr iface) { + ifaces_.push_back(iface); + } + public: + int64_t taoAssocPut(const Text& tableName, int64_t assocType, int64_t id1, int64_t id2, int64_t id1Type, int64_t id2Type, int64_t timestamp, AssocVisibility visibility, bool update_count, int64_t dataVersion, const Text& data, const Text& wormhole_comment) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz - 1; ++i) { + ifaces_[i]->taoAssocPut(tableName, assocType, id1, id2, id1Type, id2Type, timestamp, visibility, update_count, dataVersion, data, wormhole_comment); + } + return ifaces_[i]->taoAssocPut(tableName, assocType, id1, id2, id1Type, id2Type, timestamp, visibility, update_count, dataVersion, data, wormhole_comment); + } + + int64_t taoAssocDelete(const Text& tableName, int64_t assocType, int64_t id1, int64_t id2, AssocVisibility visibility, bool update_count, const Text& wormhole_comment) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz - 1; ++i) { + ifaces_[i]->taoAssocDelete(tableName, assocType, id1, id2, visibility, update_count, wormhole_comment); + } + return ifaces_[i]->taoAssocDelete(tableName, assocType, id1, id2, visibility, update_count, wormhole_comment); + } + + void taoAssocRangeGet(std::vector & _return, const Text& tableName, int64_t assocType, int64_t id1, int64_t start_time, int64_t end_time, int64_t offset, int64_t limit) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz; ++i) { + ifaces_[i]->taoAssocRangeGet(_return, tableName, assocType, id1, start_time, end_time, offset, limit); + } + } + + void taoAssocGet(std::vector & _return, const Text& tableName, int64_t assocType, int64_t id1, const std::vector & id2s) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz; ++i) { + ifaces_[i]->taoAssocGet(_return, tableName, assocType, id1, id2s); + } + } + + int64_t taoAssocCount(const Text& tableName, int64_t assocType, int64_t id1) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz - 1; ++i) { + ifaces_[i]->taoAssocCount(tableName, assocType, id1); + } + return ifaces_[i]->taoAssocCount(tableName, assocType, id1); + } + +}; + +} // namespace + +#endif diff --git a/thrift/gen-cpp/DB.cpp b/thrift/gen-cpp/DB.cpp new file mode 100644 index 00000000..c82cbf24 --- /dev/null +++ b/thrift/gen-cpp/DB.cpp @@ -0,0 +1,4162 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "DB.h" +#include "folly/ScopeGuard.h" + +namespace Tleveldb { + +uint32_t DB_Open_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->dbname); + this->__isset.dbname = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->dboptions.read(iprot); + this->__isset.dboptions = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_Open_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_Open_args"); + xfer += oprot->writeFieldBegin("dbname", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary(this->dbname); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("dboptions", apache::thrift::protocol::T_STRUCT, 2); + xfer += this->dboptions.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_Open_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_Open_pargs"); + xfer += oprot->writeFieldBegin("dbname", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary((*(this->dbname))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("dboptions", apache::thrift::protocol::T_STRUCT, 2); + xfer += (*(this->dboptions)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_Open_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->success.read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->se.read(iprot); + this->__isset.se = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_Open_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("DB_Open_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_STRUCT, 0); + xfer += this->success.write(oprot); + xfer += oprot->writeFieldEnd(); + } else if (this->__isset.se) { + xfer += oprot->writeFieldBegin("se", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->se.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_Open_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += (*(this->success)).read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->se.read(iprot); + this->__isset.se = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_Close_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->dbhandle.read(iprot); + this->__isset.dbhandle = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->dbname); + this->__isset.dbname = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_Close_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_Close_args"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->dbhandle.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("dbname", apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeBinary(this->dbname); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_Close_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_Close_pargs"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += (*(this->dbhandle)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("dbname", apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeBinary((*(this->dbname))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_Close_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast6; + xfer += iprot->readI32(ecast6); + this->success = (Code)ecast6; + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_Close_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("DB_Close_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_I32, 0); + xfer += oprot->writeI32((int32_t)this->success); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_Close_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast7; + xfer += iprot->readI32(ecast7); + (*(this->success)) = (Code)ecast7; + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_Put_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->dbhandle.read(iprot); + this->__isset.dbhandle = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->keyvalue.read(iprot); + this->__isset.keyvalue = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->options.read(iprot); + this->__isset.options = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_Put_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_Put_args"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->dbhandle.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("keyvalue", apache::thrift::protocol::T_STRUCT, 2); + xfer += this->keyvalue.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("options", apache::thrift::protocol::T_STRUCT, 3); + xfer += this->options.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_Put_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_Put_pargs"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += (*(this->dbhandle)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("keyvalue", apache::thrift::protocol::T_STRUCT, 2); + xfer += (*(this->keyvalue)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("options", apache::thrift::protocol::T_STRUCT, 3); + xfer += (*(this->options)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_Put_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast8; + xfer += iprot->readI32(ecast8); + this->success = (Code)ecast8; + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_Put_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("DB_Put_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_I32, 0); + xfer += oprot->writeI32((int32_t)this->success); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_Put_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast9; + xfer += iprot->readI32(ecast9); + (*(this->success)) = (Code)ecast9; + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_Delete_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->dbhandle.read(iprot); + this->__isset.dbhandle = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->key.read(iprot); + this->__isset.key = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->options.read(iprot); + this->__isset.options = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_Delete_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_Delete_args"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->dbhandle.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("key", apache::thrift::protocol::T_STRUCT, 2); + xfer += this->key.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("options", apache::thrift::protocol::T_STRUCT, 3); + xfer += this->options.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_Delete_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_Delete_pargs"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += (*(this->dbhandle)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("key", apache::thrift::protocol::T_STRUCT, 2); + xfer += (*(this->key)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("options", apache::thrift::protocol::T_STRUCT, 3); + xfer += (*(this->options)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_Delete_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast10; + xfer += iprot->readI32(ecast10); + this->success = (Code)ecast10; + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_Delete_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("DB_Delete_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_I32, 0); + xfer += oprot->writeI32((int32_t)this->success); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_Delete_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast11; + xfer += iprot->readI32(ecast11); + (*(this->success)) = (Code)ecast11; + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_Write_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->dbhandle.read(iprot); + this->__isset.dbhandle = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_LIST) { + { + this->batch.clear(); + uint32_t _size12; + apache::thrift::protocol::TType _etype15; + xfer += iprot->readListBegin(_etype15, _size12); + this->batch.resize(_size12); + uint32_t _i16; + for (_i16 = 0; _i16 < _size12; ++_i16) + { + xfer += this->batch[_i16].read(iprot); + } + xfer += iprot->readListEnd(); + } + this->__isset.batch = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->options.read(iprot); + this->__isset.options = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_Write_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_Write_args"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->dbhandle.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("batch", apache::thrift::protocol::T_LIST, 2); + { + xfer += oprot->writeListBegin(apache::thrift::protocol::T_STRUCT, this->batch.size()); + std::vector ::const_iterator _iter17; + for (_iter17 = this->batch.begin(); _iter17 != this->batch.end(); ++_iter17) + { + xfer += (*_iter17).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("options", apache::thrift::protocol::T_STRUCT, 3); + xfer += this->options.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_Write_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_Write_pargs"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += (*(this->dbhandle)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("batch", apache::thrift::protocol::T_LIST, 2); + { + xfer += oprot->writeListBegin(apache::thrift::protocol::T_STRUCT, (*(this->batch)).size()); + std::vector ::const_iterator _iter18; + for (_iter18 = (*(this->batch)).begin(); _iter18 != (*(this->batch)).end(); ++_iter18) + { + xfer += (*_iter18).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("options", apache::thrift::protocol::T_STRUCT, 3); + xfer += (*(this->options)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_Write_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast19; + xfer += iprot->readI32(ecast19); + this->success = (Code)ecast19; + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_Write_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("DB_Write_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_I32, 0); + xfer += oprot->writeI32((int32_t)this->success); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_Write_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast20; + xfer += iprot->readI32(ecast20); + (*(this->success)) = (Code)ecast20; + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_Get_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->dbhandle.read(iprot); + this->__isset.dbhandle = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->inputkey.read(iprot); + this->__isset.inputkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->options.read(iprot); + this->__isset.options = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_Get_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_Get_args"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->dbhandle.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("inputkey", apache::thrift::protocol::T_STRUCT, 2); + xfer += this->inputkey.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("options", apache::thrift::protocol::T_STRUCT, 3); + xfer += this->options.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_Get_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_Get_pargs"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += (*(this->dbhandle)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("inputkey", apache::thrift::protocol::T_STRUCT, 2); + xfer += (*(this->inputkey)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("options", apache::thrift::protocol::T_STRUCT, 3); + xfer += (*(this->options)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_Get_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->success.read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_Get_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("DB_Get_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_STRUCT, 0); + xfer += this->success.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_Get_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += (*(this->success)).read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_NewIterator_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->dbhandle.read(iprot); + this->__isset.dbhandle = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->options.read(iprot); + this->__isset.options = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast21; + xfer += iprot->readI32(ecast21); + this->iteratorType = (IteratorType)ecast21; + this->__isset.iteratorType = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->target.read(iprot); + this->__isset.target = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_NewIterator_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_NewIterator_args"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->dbhandle.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("options", apache::thrift::protocol::T_STRUCT, 2); + xfer += this->options.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("iteratorType", apache::thrift::protocol::T_I32, 3); + xfer += oprot->writeI32((int32_t)this->iteratorType); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("target", apache::thrift::protocol::T_STRUCT, 4); + xfer += this->target.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_NewIterator_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_NewIterator_pargs"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += (*(this->dbhandle)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("options", apache::thrift::protocol::T_STRUCT, 2); + xfer += (*(this->options)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("iteratorType", apache::thrift::protocol::T_I32, 3); + xfer += oprot->writeI32((int32_t)(*(this->iteratorType))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("target", apache::thrift::protocol::T_STRUCT, 4); + xfer += (*(this->target)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_NewIterator_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->success.read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_NewIterator_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("DB_NewIterator_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_STRUCT, 0); + xfer += this->success.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_NewIterator_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += (*(this->success)).read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_DeleteIterator_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->dbhandle.read(iprot); + this->__isset.dbhandle = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->iterator.read(iprot); + this->__isset.iterator = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_DeleteIterator_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_DeleteIterator_args"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->dbhandle.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("iterator", apache::thrift::protocol::T_STRUCT, 2); + xfer += this->iterator.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_DeleteIterator_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_DeleteIterator_pargs"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += (*(this->dbhandle)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("iterator", apache::thrift::protocol::T_STRUCT, 2); + xfer += (*(this->iterator)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_DeleteIterator_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast22; + xfer += iprot->readI32(ecast22); + this->success = (Code)ecast22; + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_DeleteIterator_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("DB_DeleteIterator_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_I32, 0); + xfer += oprot->writeI32((int32_t)this->success); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_DeleteIterator_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast23; + xfer += iprot->readI32(ecast23); + (*(this->success)) = (Code)ecast23; + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_GetNext_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->dbhandle.read(iprot); + this->__isset.dbhandle = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->iterator.read(iprot); + this->__isset.iterator = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_GetNext_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_GetNext_args"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->dbhandle.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("iterator", apache::thrift::protocol::T_STRUCT, 2); + xfer += this->iterator.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_GetNext_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_GetNext_pargs"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += (*(this->dbhandle)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("iterator", apache::thrift::protocol::T_STRUCT, 2); + xfer += (*(this->iterator)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_GetNext_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->success.read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_GetNext_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("DB_GetNext_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_STRUCT, 0); + xfer += this->success.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_GetNext_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += (*(this->success)).read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_GetPrev_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->dbhandle.read(iprot); + this->__isset.dbhandle = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->iterator.read(iprot); + this->__isset.iterator = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_GetPrev_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_GetPrev_args"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->dbhandle.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("iterator", apache::thrift::protocol::T_STRUCT, 2); + xfer += this->iterator.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_GetPrev_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_GetPrev_pargs"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += (*(this->dbhandle)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("iterator", apache::thrift::protocol::T_STRUCT, 2); + xfer += (*(this->iterator)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_GetPrev_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->success.read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_GetPrev_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("DB_GetPrev_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_STRUCT, 0); + xfer += this->success.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_GetPrev_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += (*(this->success)).read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_GetSnapshot_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->dbhandle.read(iprot); + this->__isset.dbhandle = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_GetSnapshot_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_GetSnapshot_args"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->dbhandle.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_GetSnapshot_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_GetSnapshot_pargs"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += (*(this->dbhandle)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_GetSnapshot_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->success.read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_GetSnapshot_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("DB_GetSnapshot_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_STRUCT, 0); + xfer += this->success.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_GetSnapshot_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += (*(this->success)).read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_ReleaseSnapshot_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->dbhandle.read(iprot); + this->__isset.dbhandle = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->snapshot.read(iprot); + this->__isset.snapshot = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_ReleaseSnapshot_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_ReleaseSnapshot_args"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->dbhandle.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("snapshot", apache::thrift::protocol::T_STRUCT, 2); + xfer += this->snapshot.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_ReleaseSnapshot_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_ReleaseSnapshot_pargs"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += (*(this->dbhandle)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("snapshot", apache::thrift::protocol::T_STRUCT, 2); + xfer += (*(this->snapshot)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_ReleaseSnapshot_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast24; + xfer += iprot->readI32(ecast24); + this->success = (Code)ecast24; + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_ReleaseSnapshot_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("DB_ReleaseSnapshot_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_I32, 0); + xfer += oprot->writeI32((int32_t)this->success); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_ReleaseSnapshot_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast25; + xfer += iprot->readI32(ecast25); + (*(this->success)) = (Code)ecast25; + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_CompactRange_args::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->dbhandle.read(iprot); + this->__isset.dbhandle = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->start.read(iprot); + this->__isset.start = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->endhere.read(iprot); + this->__isset.endhere = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_CompactRange_args::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_CompactRange_args"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->dbhandle.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("start", apache::thrift::protocol::T_STRUCT, 2); + xfer += this->start.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("endhere", apache::thrift::protocol::T_STRUCT, 3); + xfer += this->endhere.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_CompactRange_pargs::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DB_CompactRange_pargs"); + xfer += oprot->writeFieldBegin("dbhandle", apache::thrift::protocol::T_STRUCT, 1); + xfer += (*(this->dbhandle)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("start", apache::thrift::protocol::T_STRUCT, 2); + xfer += (*(this->start)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("endhere", apache::thrift::protocol::T_STRUCT, 3); + xfer += (*(this->endhere)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_CompactRange_result::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast26; + xfer += iprot->readI32(ecast26); + this->success = (Code)ecast26; + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DB_CompactRange_result::write(apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("DB_CompactRange_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", apache::thrift::protocol::T_I32, 0); + xfer += oprot->writeI32((int32_t)this->success); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t DB_CompactRange_presult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast27; + xfer += iprot->readI32(ecast27); + (*(this->success)) = (Code)ecast27; + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +int32_t DBClient::getNextSendSequenceId() +{ + return nextSendSequenceId_++; +} + +int32_t DBClient::getNextRecvSequenceId() +{ + return nextRecvSequenceId_++; +} + +void DBClient::Open(DBHandle& _return, const Text& dbname, const DBOptions& dboptions) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("DB.Open", NULL); + + try { + send_Open(dbname, dboptions); + recv_Open(_return); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "DB.Open"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "DB.Open"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void DBClient::send_Open(const Text& dbname, const DBOptions& dboptions) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "DB.Open"); + oprot_->writeMessageBegin("Open", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + DB_Open_pargs args; + args.dbname = &dbname; + args.dboptions = &dboptions; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes28 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "DB.Open", _bytes28); + return; +} + +void DBClient::recv_Open(DBHandle& _return) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "DB.Open"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("Open") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + DB_Open_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "DB.Open", bytes); + + if (result.__isset.success) { + // _return pointer has now been filled + return; + } + if (result.__isset.se) { + throw result.se; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "Open failed: unknown result"); +} + +Code DBClient::Close(const DBHandle& dbhandle, const Text& dbname) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("DB.Close", NULL); + + try { + send_Close(dbhandle, dbname); + return recv_Close(); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "DB.Close"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "DB.Close"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void DBClient::send_Close(const DBHandle& dbhandle, const Text& dbname) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "DB.Close"); + oprot_->writeMessageBegin("Close", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + DB_Close_pargs args; + args.dbhandle = &dbhandle; + args.dbname = &dbname; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes29 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "DB.Close", _bytes29); + return; +} + +Code DBClient::recv_Close() +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "DB.Close"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("Close") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + Code _return; + DB_Close_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "DB.Close", bytes); + + if (result.__isset.success) { + return _return; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "Close failed: unknown result"); +} + +Code DBClient::Put(const DBHandle& dbhandle, const kv& keyvalue, const WriteOptions& options) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("DB.Put", NULL); + + try { + send_Put(dbhandle, keyvalue, options); + return recv_Put(); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "DB.Put"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "DB.Put"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void DBClient::send_Put(const DBHandle& dbhandle, const kv& keyvalue, const WriteOptions& options) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "DB.Put"); + oprot_->writeMessageBegin("Put", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + DB_Put_pargs args; + args.dbhandle = &dbhandle; + args.keyvalue = &keyvalue; + args.options = &options; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes30 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "DB.Put", _bytes30); + return; +} + +Code DBClient::recv_Put() +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "DB.Put"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("Put") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + Code _return; + DB_Put_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "DB.Put", bytes); + + if (result.__isset.success) { + return _return; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "Put failed: unknown result"); +} + +Code DBClient::Delete(const DBHandle& dbhandle, const Slice& key, const WriteOptions& options) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("DB.Delete", NULL); + + try { + send_Delete(dbhandle, key, options); + return recv_Delete(); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "DB.Delete"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "DB.Delete"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void DBClient::send_Delete(const DBHandle& dbhandle, const Slice& key, const WriteOptions& options) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "DB.Delete"); + oprot_->writeMessageBegin("Delete", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + DB_Delete_pargs args; + args.dbhandle = &dbhandle; + args.key = &key; + args.options = &options; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes31 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "DB.Delete", _bytes31); + return; +} + +Code DBClient::recv_Delete() +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "DB.Delete"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("Delete") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + Code _return; + DB_Delete_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "DB.Delete", bytes); + + if (result.__isset.success) { + return _return; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "Delete failed: unknown result"); +} + +Code DBClient::Write(const DBHandle& dbhandle, const std::vector & batch, const WriteOptions& options) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("DB.Write", NULL); + + try { + send_Write(dbhandle, batch, options); + return recv_Write(); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "DB.Write"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "DB.Write"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void DBClient::send_Write(const DBHandle& dbhandle, const std::vector & batch, const WriteOptions& options) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "DB.Write"); + oprot_->writeMessageBegin("Write", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + DB_Write_pargs args; + args.dbhandle = &dbhandle; + args.batch = &batch; + args.options = &options; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes32 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "DB.Write", _bytes32); + return; +} + +Code DBClient::recv_Write() +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "DB.Write"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("Write") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + Code _return; + DB_Write_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "DB.Write", bytes); + + if (result.__isset.success) { + return _return; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "Write failed: unknown result"); +} + +void DBClient::Get(ResultItem& _return, const DBHandle& dbhandle, const Slice& inputkey, const ReadOptions& options) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("DB.Get", NULL); + + try { + send_Get(dbhandle, inputkey, options); + recv_Get(_return); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "DB.Get"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "DB.Get"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void DBClient::send_Get(const DBHandle& dbhandle, const Slice& inputkey, const ReadOptions& options) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "DB.Get"); + oprot_->writeMessageBegin("Get", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + DB_Get_pargs args; + args.dbhandle = &dbhandle; + args.inputkey = &inputkey; + args.options = &options; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes33 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "DB.Get", _bytes33); + return; +} + +void DBClient::recv_Get(ResultItem& _return) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "DB.Get"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("Get") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + DB_Get_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "DB.Get", bytes); + + if (result.__isset.success) { + // _return pointer has now been filled + return; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "Get failed: unknown result"); +} + +void DBClient::NewIterator(ResultIterator& _return, const DBHandle& dbhandle, const ReadOptions& options, IteratorType iteratorType, const Slice& target) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("DB.NewIterator", NULL); + + try { + send_NewIterator(dbhandle, options, iteratorType, target); + recv_NewIterator(_return); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "DB.NewIterator"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "DB.NewIterator"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void DBClient::send_NewIterator(const DBHandle& dbhandle, const ReadOptions& options, IteratorType iteratorType, const Slice& target) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "DB.NewIterator"); + oprot_->writeMessageBegin("NewIterator", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + DB_NewIterator_pargs args; + args.dbhandle = &dbhandle; + args.options = &options; + args.iteratorType = &iteratorType; + args.target = ⌖ + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes34 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "DB.NewIterator", _bytes34); + return; +} + +void DBClient::recv_NewIterator(ResultIterator& _return) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "DB.NewIterator"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("NewIterator") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + DB_NewIterator_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "DB.NewIterator", bytes); + + if (result.__isset.success) { + // _return pointer has now been filled + return; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "NewIterator failed: unknown result"); +} + +Code DBClient::DeleteIterator(const DBHandle& dbhandle, const Iterator& iterator) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("DB.DeleteIterator", NULL); + + try { + send_DeleteIterator(dbhandle, iterator); + return recv_DeleteIterator(); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "DB.DeleteIterator"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "DB.DeleteIterator"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void DBClient::send_DeleteIterator(const DBHandle& dbhandle, const Iterator& iterator) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "DB.DeleteIterator"); + oprot_->writeMessageBegin("DeleteIterator", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + DB_DeleteIterator_pargs args; + args.dbhandle = &dbhandle; + args.iterator = &iterator; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes35 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "DB.DeleteIterator", _bytes35); + return; +} + +Code DBClient::recv_DeleteIterator() +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "DB.DeleteIterator"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("DeleteIterator") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + Code _return; + DB_DeleteIterator_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "DB.DeleteIterator", bytes); + + if (result.__isset.success) { + return _return; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "DeleteIterator failed: unknown result"); +} + +void DBClient::GetNext(ResultPair& _return, const DBHandle& dbhandle, const Iterator& iterator) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("DB.GetNext", NULL); + + try { + send_GetNext(dbhandle, iterator); + recv_GetNext(_return); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "DB.GetNext"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "DB.GetNext"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void DBClient::send_GetNext(const DBHandle& dbhandle, const Iterator& iterator) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "DB.GetNext"); + oprot_->writeMessageBegin("GetNext", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + DB_GetNext_pargs args; + args.dbhandle = &dbhandle; + args.iterator = &iterator; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes36 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "DB.GetNext", _bytes36); + return; +} + +void DBClient::recv_GetNext(ResultPair& _return) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "DB.GetNext"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("GetNext") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + DB_GetNext_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "DB.GetNext", bytes); + + if (result.__isset.success) { + // _return pointer has now been filled + return; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "GetNext failed: unknown result"); +} + +void DBClient::GetPrev(ResultPair& _return, const DBHandle& dbhandle, const Iterator& iterator) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("DB.GetPrev", NULL); + + try { + send_GetPrev(dbhandle, iterator); + recv_GetPrev(_return); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "DB.GetPrev"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "DB.GetPrev"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void DBClient::send_GetPrev(const DBHandle& dbhandle, const Iterator& iterator) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "DB.GetPrev"); + oprot_->writeMessageBegin("GetPrev", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + DB_GetPrev_pargs args; + args.dbhandle = &dbhandle; + args.iterator = &iterator; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes37 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "DB.GetPrev", _bytes37); + return; +} + +void DBClient::recv_GetPrev(ResultPair& _return) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "DB.GetPrev"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("GetPrev") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + DB_GetPrev_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "DB.GetPrev", bytes); + + if (result.__isset.success) { + // _return pointer has now been filled + return; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "GetPrev failed: unknown result"); +} + +void DBClient::GetSnapshot(ResultSnapshot& _return, const DBHandle& dbhandle) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("DB.GetSnapshot", NULL); + + try { + send_GetSnapshot(dbhandle); + recv_GetSnapshot(_return); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "DB.GetSnapshot"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "DB.GetSnapshot"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void DBClient::send_GetSnapshot(const DBHandle& dbhandle) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "DB.GetSnapshot"); + oprot_->writeMessageBegin("GetSnapshot", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + DB_GetSnapshot_pargs args; + args.dbhandle = &dbhandle; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes38 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "DB.GetSnapshot", _bytes38); + return; +} + +void DBClient::recv_GetSnapshot(ResultSnapshot& _return) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "DB.GetSnapshot"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("GetSnapshot") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + DB_GetSnapshot_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "DB.GetSnapshot", bytes); + + if (result.__isset.success) { + // _return pointer has now been filled + return; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "GetSnapshot failed: unknown result"); +} + +Code DBClient::ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("DB.ReleaseSnapshot", NULL); + + try { + send_ReleaseSnapshot(dbhandle, snapshot); + return recv_ReleaseSnapshot(); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "DB.ReleaseSnapshot"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "DB.ReleaseSnapshot"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void DBClient::send_ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "DB.ReleaseSnapshot"); + oprot_->writeMessageBegin("ReleaseSnapshot", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + DB_ReleaseSnapshot_pargs args; + args.dbhandle = &dbhandle; + args.snapshot = &snapshot; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes39 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "DB.ReleaseSnapshot", _bytes39); + return; +} + +Code DBClient::recv_ReleaseSnapshot() +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "DB.ReleaseSnapshot"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("ReleaseSnapshot") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + Code _return; + DB_ReleaseSnapshot_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "DB.ReleaseSnapshot", bytes); + + if (result.__isset.success) { + return _return; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "ReleaseSnapshot failed: unknown result"); +} + +Code DBClient::CompactRange(const DBHandle& dbhandle, const Slice& start, const Slice& endhere) +{ + folly::ScopeGuard g = folly::makeGuard([&] { this->clearClientContextStack(); }); + this->generateClientContextStack("DB.CompactRange", NULL); + + try { + send_CompactRange(dbhandle, start, endhere); + return recv_CompactRange(); + } catch(apache::thrift::transport::TTransportException& ex) { + this->handlerError(this->getClientContextStack(), "DB.CompactRange"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + throw; + } catch(apache::thrift::TApplicationException& ex) { + if (ex.getType() == apache::thrift::TApplicationException::BAD_SEQUENCE_ID) { + this->handlerError(this->getClientContextStack(), "DB.CompactRange"); + iprot_->getTransport()->close(); + oprot_->getTransport()->close(); + } + throw; + } +} + +void DBClient::send_CompactRange(const DBHandle& dbhandle, const Slice& start, const Slice& endhere) +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + this->preWrite(ctx, "DB.CompactRange"); + oprot_->writeMessageBegin("CompactRange", apache::thrift::protocol::T_CALL, getNextSendSequenceId()); + + DB_CompactRange_pargs args; + args.dbhandle = &dbhandle; + args.start = &start; + args.endhere = &endhere; + args.write(oprot_); + + oprot_->writeMessageEnd(); + uint32_t _bytes40 = oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); + this->postWrite(ctx, "DB.CompactRange", _bytes40); + return; +} + +Code DBClient::recv_CompactRange() +{ + apache::thrift::ContextStack* ctx = this->getClientContextStack(); + uint32_t bytes; + int32_t rseqid = 0; + int32_t eseqid = getNextRecvSequenceId(); + std::string fname; + apache::thrift::protocol::TMessageType mtype; + this->preRead(ctx, "DB.CompactRange"); + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (this->checkSeqid_ && rseqid != eseqid) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::BAD_SEQUENCE_ID); + } + if (mtype == apache::thrift::protocol::T_EXCEPTION) { + apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != apache::thrift::protocol::T_REPLY) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + } + if (fname.compare("CompactRange") != 0) { + iprot_->skip(apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::WRONG_METHOD_NAME); + } + Code _return; + DB_CompactRange_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + bytes = iprot_->getTransport()->readEnd(); + this->postRead(ctx, "DB.CompactRange", bytes); + + if (result.__isset.success) { + return _return; + } + throw apache::thrift::TApplicationException(apache::thrift::TApplicationException::MISSING_RESULT, "CompactRange failed: unknown result"); +} + +bool DBProcessor::dispatchCall(::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, const std::string& fname, int32_t seqid, apache::thrift::server::TConnectionContext* connectionContext) { + ProcessMap::iterator pfn; + pfn = processMap_.find(fname); + if (pfn == processMap_.end()) { + iprot->skip(apache::thrift::protocol::T_STRUCT); + iprot->readMessageEnd(); + iprot->getTransport()->readEnd(); + apache::thrift::TApplicationException x(apache::thrift::TApplicationException::UNKNOWN_METHOD, "Invalid method name: '"+fname+"'"); + oprot->writeMessageBegin(fname, apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return true; + } + const ProcessFunction& pf = pfn->second; + (this->*pf)(seqid, iprot, oprot, connectionContext); + return true; +} + +void DBProcessor::process_Open(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("DB.Open", connectionContext)); + + this->preRead(ctx.get(), "DB.Open"); + DB_Open_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "DB.Open", bytes); + + DB_Open_result result; + try { + iface_->Open(result.success, args.dbname, args.dboptions); + result.__isset.success = true; + } catch (LeveldbException &se) { + result.se = se; + result.__isset.se = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "DB.Open"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("Open", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "DB.Open"); + oprot->writeMessageBegin("Open", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "DB.Open", bytes); + +} + +void DBProcessor::process_Close(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("DB.Close", connectionContext)); + + this->preRead(ctx.get(), "DB.Close"); + DB_Close_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "DB.Close", bytes); + + DB_Close_result result; + try { + result.success = iface_->Close(args.dbhandle, args.dbname); + result.__isset.success = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "DB.Close"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("Close", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "DB.Close"); + oprot->writeMessageBegin("Close", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "DB.Close", bytes); + +} + +void DBProcessor::process_Put(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("DB.Put", connectionContext)); + + this->preRead(ctx.get(), "DB.Put"); + DB_Put_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "DB.Put", bytes); + + DB_Put_result result; + try { + result.success = iface_->Put(args.dbhandle, args.keyvalue, args.options); + result.__isset.success = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "DB.Put"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("Put", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "DB.Put"); + oprot->writeMessageBegin("Put", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "DB.Put", bytes); + +} + +void DBProcessor::process_Delete(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("DB.Delete", connectionContext)); + + this->preRead(ctx.get(), "DB.Delete"); + DB_Delete_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "DB.Delete", bytes); + + DB_Delete_result result; + try { + result.success = iface_->Delete(args.dbhandle, args.key, args.options); + result.__isset.success = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "DB.Delete"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("Delete", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "DB.Delete"); + oprot->writeMessageBegin("Delete", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "DB.Delete", bytes); + +} + +void DBProcessor::process_Write(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("DB.Write", connectionContext)); + + this->preRead(ctx.get(), "DB.Write"); + DB_Write_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "DB.Write", bytes); + + DB_Write_result result; + try { + result.success = iface_->Write(args.dbhandle, args.batch, args.options); + result.__isset.success = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "DB.Write"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("Write", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "DB.Write"); + oprot->writeMessageBegin("Write", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "DB.Write", bytes); + +} + +void DBProcessor::process_Get(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("DB.Get", connectionContext)); + + this->preRead(ctx.get(), "DB.Get"); + DB_Get_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "DB.Get", bytes); + + DB_Get_result result; + try { + iface_->Get(result.success, args.dbhandle, args.inputkey, args.options); + result.__isset.success = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "DB.Get"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("Get", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "DB.Get"); + oprot->writeMessageBegin("Get", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "DB.Get", bytes); + +} + +void DBProcessor::process_NewIterator(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("DB.NewIterator", connectionContext)); + + this->preRead(ctx.get(), "DB.NewIterator"); + DB_NewIterator_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "DB.NewIterator", bytes); + + DB_NewIterator_result result; + try { + iface_->NewIterator(result.success, args.dbhandle, args.options, args.iteratorType, args.target); + result.__isset.success = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "DB.NewIterator"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("NewIterator", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "DB.NewIterator"); + oprot->writeMessageBegin("NewIterator", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "DB.NewIterator", bytes); + +} + +void DBProcessor::process_DeleteIterator(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("DB.DeleteIterator", connectionContext)); + + this->preRead(ctx.get(), "DB.DeleteIterator"); + DB_DeleteIterator_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "DB.DeleteIterator", bytes); + + DB_DeleteIterator_result result; + try { + result.success = iface_->DeleteIterator(args.dbhandle, args.iterator); + result.__isset.success = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "DB.DeleteIterator"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("DeleteIterator", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "DB.DeleteIterator"); + oprot->writeMessageBegin("DeleteIterator", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "DB.DeleteIterator", bytes); + +} + +void DBProcessor::process_GetNext(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("DB.GetNext", connectionContext)); + + this->preRead(ctx.get(), "DB.GetNext"); + DB_GetNext_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "DB.GetNext", bytes); + + DB_GetNext_result result; + try { + iface_->GetNext(result.success, args.dbhandle, args.iterator); + result.__isset.success = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "DB.GetNext"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("GetNext", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "DB.GetNext"); + oprot->writeMessageBegin("GetNext", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "DB.GetNext", bytes); + +} + +void DBProcessor::process_GetPrev(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("DB.GetPrev", connectionContext)); + + this->preRead(ctx.get(), "DB.GetPrev"); + DB_GetPrev_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "DB.GetPrev", bytes); + + DB_GetPrev_result result; + try { + iface_->GetPrev(result.success, args.dbhandle, args.iterator); + result.__isset.success = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "DB.GetPrev"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("GetPrev", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "DB.GetPrev"); + oprot->writeMessageBegin("GetPrev", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "DB.GetPrev", bytes); + +} + +void DBProcessor::process_GetSnapshot(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("DB.GetSnapshot", connectionContext)); + + this->preRead(ctx.get(), "DB.GetSnapshot"); + DB_GetSnapshot_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "DB.GetSnapshot", bytes); + + DB_GetSnapshot_result result; + try { + iface_->GetSnapshot(result.success, args.dbhandle); + result.__isset.success = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "DB.GetSnapshot"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("GetSnapshot", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "DB.GetSnapshot"); + oprot->writeMessageBegin("GetSnapshot", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "DB.GetSnapshot", bytes); + +} + +void DBProcessor::process_ReleaseSnapshot(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("DB.ReleaseSnapshot", connectionContext)); + + this->preRead(ctx.get(), "DB.ReleaseSnapshot"); + DB_ReleaseSnapshot_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "DB.ReleaseSnapshot", bytes); + + DB_ReleaseSnapshot_result result; + try { + result.success = iface_->ReleaseSnapshot(args.dbhandle, args.snapshot); + result.__isset.success = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "DB.ReleaseSnapshot"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("ReleaseSnapshot", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "DB.ReleaseSnapshot"); + oprot->writeMessageBegin("ReleaseSnapshot", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "DB.ReleaseSnapshot", bytes); + +} + +void DBProcessor::process_CompactRange(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext) +{ + std::unique_ptr ctx(this->getContextStack("DB.CompactRange", connectionContext)); + + this->preRead(ctx.get(), "DB.CompactRange"); + DB_CompactRange_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + this->postRead(ctx.get(), "DB.CompactRange", bytes); + + DB_CompactRange_result result; + try { + result.success = iface_->CompactRange(args.dbhandle, args.start, args.endhere); + result.__isset.success = true; + } catch (const std::exception& e) { + this->handlerError(ctx.get(), "DB.CompactRange"); + + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("CompactRange", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + this->preWrite(ctx.get(), "DB.CompactRange"); + oprot->writeMessageBegin("CompactRange", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + this->postWrite(ctx.get(), "DB.CompactRange", bytes); + +} + +::boost::shared_ptr< ::apache::thrift::TProcessor > DBProcessorFactory::getProcessor(::apache::thrift::server::TConnectionContext* ctx) { + ::apache::thrift::ReleaseHandler< DBIfFactory > cleanup(handlerFactory_); + ::boost::shared_ptr< DBIf > handler(handlerFactory_->getHandler(ctx), cleanup); + ::boost::shared_ptr< ::apache::thrift::TProcessor > processor(new DBProcessor(handler)); + return processor; +} +} // namespace + diff --git a/thrift/gen-cpp/DB.h b/thrift/gen-cpp/DB.h new file mode 100644 index 00000000..37cf3d1e --- /dev/null +++ b/thrift/gen-cpp/DB.h @@ -0,0 +1,2225 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef _Tleveldb_DB_H +#define _Tleveldb_DB_H + +#include +#include "leveldb_types.h" + +namespace Tleveldb { + +class DBIf { + public: + virtual ~DBIf() {} + virtual void Open(DBHandle& _return, const Text& dbname, const DBOptions& dboptions) = 0; + virtual Code Close(const DBHandle& dbhandle, const Text& dbname) = 0; + virtual Code Put(const DBHandle& dbhandle, const kv& keyvalue, const WriteOptions& options) = 0; + virtual Code Delete(const DBHandle& dbhandle, const Slice& key, const WriteOptions& options) = 0; + virtual Code Write(const DBHandle& dbhandle, const std::vector & batch, const WriteOptions& options) = 0; + virtual void Get(ResultItem& _return, const DBHandle& dbhandle, const Slice& inputkey, const ReadOptions& options) = 0; + virtual void NewIterator(ResultIterator& _return, const DBHandle& dbhandle, const ReadOptions& options, IteratorType iteratorType, const Slice& target) = 0; + virtual Code DeleteIterator(const DBHandle& dbhandle, const Iterator& iterator) = 0; + virtual void GetNext(ResultPair& _return, const DBHandle& dbhandle, const Iterator& iterator) = 0; + virtual void GetPrev(ResultPair& _return, const DBHandle& dbhandle, const Iterator& iterator) = 0; + virtual void GetSnapshot(ResultSnapshot& _return, const DBHandle& dbhandle) = 0; + virtual Code ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot) = 0; + virtual Code CompactRange(const DBHandle& dbhandle, const Slice& start, const Slice& endhere) = 0; +}; + +class DBIfFactory { + public: + typedef DBIf Handler; + + virtual ~DBIfFactory() {} + + virtual DBIf* getHandler(::apache::thrift::server::TConnectionContext* ctx) = 0; + virtual void releaseHandler(DBIf* handler) = 0; +}; + +class DBIfSingletonFactory : virtual public DBIfFactory { + public: + DBIfSingletonFactory(const boost::shared_ptr& iface) : iface_(iface) {} + virtual ~DBIfSingletonFactory() {} + + virtual DBIf* getHandler(::apache::thrift::server::TConnectionContext*) { + return iface_.get(); + } + virtual void releaseHandler(DBIf* handler) {} + + protected: + boost::shared_ptr iface_; +}; + +class DBNull : virtual public DBIf { + public: + virtual ~DBNull() {} + void Open(DBHandle& /* _return */, const Text& /* dbname */, const DBOptions& /* dboptions */) { + return; + } + Code Close(const DBHandle& /* dbhandle */, const Text& /* dbname */) { + Code _return = (Code)0; + return _return; + } + Code Put(const DBHandle& /* dbhandle */, const kv& /* keyvalue */, const WriteOptions& /* options */) { + Code _return = (Code)0; + return _return; + } + Code Delete(const DBHandle& /* dbhandle */, const Slice& /* key */, const WriteOptions& /* options */) { + Code _return = (Code)0; + return _return; + } + Code Write(const DBHandle& /* dbhandle */, const std::vector & /* batch */, const WriteOptions& /* options */) { + Code _return = (Code)0; + return _return; + } + void Get(ResultItem& /* _return */, const DBHandle& /* dbhandle */, const Slice& /* inputkey */, const ReadOptions& /* options */) { + return; + } + void NewIterator(ResultIterator& /* _return */, const DBHandle& /* dbhandle */, const ReadOptions& /* options */, IteratorType /* iteratorType */, const Slice& /* target */) { + return; + } + Code DeleteIterator(const DBHandle& /* dbhandle */, const Iterator& /* iterator */) { + Code _return = (Code)0; + return _return; + } + void GetNext(ResultPair& /* _return */, const DBHandle& /* dbhandle */, const Iterator& /* iterator */) { + return; + } + void GetPrev(ResultPair& /* _return */, const DBHandle& /* dbhandle */, const Iterator& /* iterator */) { + return; + } + void GetSnapshot(ResultSnapshot& /* _return */, const DBHandle& /* dbhandle */) { + return; + } + Code ReleaseSnapshot(const DBHandle& /* dbhandle */, const Snapshot& /* snapshot */) { + Code _return = (Code)0; + return _return; + } + Code CompactRange(const DBHandle& /* dbhandle */, const Slice& /* start */, const Slice& /* endhere */) { + Code _return = (Code)0; + return _return; + } +}; + +class DB_Open_args { + public: + + static const uint64_t _reflection_id = 5143148560683113100U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_Open_args() : dbname("") { + } + + DB_Open_args(const DB_Open_args&) = default; + DB_Open_args& operator=(const DB_Open_args&) = default; + DB_Open_args(DB_Open_args&&) = default; + DB_Open_args& operator=(DB_Open_args&&) = default; + + void __clear() { + dbname = ""; + dboptions.__clear(); + __isset.__clear(); + } + + virtual ~DB_Open_args() throw() {} + + Text dbname; + DBOptions dboptions; + + struct __isset { + __isset() { __clear(); } + void __clear() { + dbname = false; + dboptions = false; + } + bool dbname; + bool dboptions; + } __isset; + + bool operator == (const DB_Open_args & rhs) const + { + if (!(this->dbname == rhs.dbname)) + return false; + if (!(this->dboptions == rhs.dboptions)) + return false; + return true; + } + bool operator != (const DB_Open_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_Open_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_Open_pargs { + public: + + static const uint64_t _reflection_id = 5558263615018901836U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_Open_pargs() throw() {} + + const Text* dbname; + const DBOptions* dboptions; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_Open_result { + public: + + static const uint64_t _reflection_id = 585101419942616428U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_Open_result() { + } + + DB_Open_result(const DB_Open_result&) = default; + DB_Open_result& operator=(const DB_Open_result&) = default; + DB_Open_result(DB_Open_result&&) = default; + DB_Open_result& operator=(DB_Open_result&&) = default; + + void __clear() { + success.__clear(); + se.__clear(); + __isset.__clear(); + } + + virtual ~DB_Open_result() throw() {} + + DBHandle success; + LeveldbException se; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + se = false; + } + bool success; + bool se; + } __isset; + + bool operator == (const DB_Open_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + if (!(this->se == rhs.se)) + return false; + return true; + } + bool operator != (const DB_Open_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_Open_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_Open_presult { + public: + + static const uint64_t _reflection_id = 1768872265754142060U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_Open_presult() throw() {} + + DBHandle* success; + LeveldbException se; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + se = false; + } + bool success; + bool se; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class DB_Close_args { + public: + + static const uint64_t _reflection_id = 3653575979806469484U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_Close_args() : dbname("") { + } + + DB_Close_args(const DB_Close_args&) = default; + DB_Close_args& operator=(const DB_Close_args&) = default; + DB_Close_args(DB_Close_args&&) = default; + DB_Close_args& operator=(DB_Close_args&&) = default; + + void __clear() { + dbhandle.__clear(); + dbname = ""; + __isset.__clear(); + } + + virtual ~DB_Close_args() throw() {} + + DBHandle dbhandle; + Text dbname; + + struct __isset { + __isset() { __clear(); } + void __clear() { + dbhandle = false; + dbname = false; + } + bool dbhandle; + bool dbname; + } __isset; + + bool operator == (const DB_Close_args & rhs) const + { + if (!(this->dbhandle == rhs.dbhandle)) + return false; + if (!(this->dbname == rhs.dbname)) + return false; + return true; + } + bool operator != (const DB_Close_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_Close_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_Close_pargs { + public: + + static const uint64_t _reflection_id = 2939164562981598508U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_Close_pargs() throw() {} + + const DBHandle* dbhandle; + const Text* dbname; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_Close_result { + public: + + static const uint64_t _reflection_id = 11420986846439017932U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_Close_result() : success(static_cast(0)) { + } + + DB_Close_result(const DB_Close_result&) = default; + DB_Close_result& operator=(const DB_Close_result&) = default; + DB_Close_result(DB_Close_result&&) = default; + DB_Close_result& operator=(DB_Close_result&&) = default; + + void __clear() { + success = static_cast(0); + __isset.__clear(); + } + + virtual ~DB_Close_result() throw() {} + + Code success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + bool operator == (const DB_Close_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + return true; + } + bool operator != (const DB_Close_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_Close_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_Close_presult { + public: + + static const uint64_t _reflection_id = 6223865401759091820U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_Close_presult() throw() {} + + Code* success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class DB_Put_args { + public: + + static const uint64_t _reflection_id = 15095251014297097356U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_Put_args() { + } + + DB_Put_args(const DB_Put_args&) = default; + DB_Put_args& operator=(const DB_Put_args&) = default; + DB_Put_args(DB_Put_args&&) = default; + DB_Put_args& operator=(DB_Put_args&&) = default; + + void __clear() { + dbhandle.__clear(); + keyvalue.__clear(); + options.__clear(); + __isset.__clear(); + } + + virtual ~DB_Put_args() throw() {} + + DBHandle dbhandle; + kv keyvalue; + WriteOptions options; + + struct __isset { + __isset() { __clear(); } + void __clear() { + dbhandle = false; + keyvalue = false; + options = false; + } + bool dbhandle; + bool keyvalue; + bool options; + } __isset; + + bool operator == (const DB_Put_args & rhs) const + { + if (!(this->dbhandle == rhs.dbhandle)) + return false; + if (!(this->keyvalue == rhs.keyvalue)) + return false; + if (!(this->options == rhs.options)) + return false; + return true; + } + bool operator != (const DB_Put_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_Put_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_Put_pargs { + public: + + static const uint64_t _reflection_id = 5565059585805949260U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_Put_pargs() throw() {} + + const DBHandle* dbhandle; + const kv* keyvalue; + const WriteOptions* options; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_Put_result { + public: + + static const uint64_t _reflection_id = 16570405853514888204U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_Put_result() : success(static_cast(0)) { + } + + DB_Put_result(const DB_Put_result&) = default; + DB_Put_result& operator=(const DB_Put_result&) = default; + DB_Put_result(DB_Put_result&&) = default; + DB_Put_result& operator=(DB_Put_result&&) = default; + + void __clear() { + success = static_cast(0); + __isset.__clear(); + } + + virtual ~DB_Put_result() throw() {} + + Code success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + bool operator == (const DB_Put_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + return true; + } + bool operator != (const DB_Put_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_Put_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_Put_presult { + public: + + static const uint64_t _reflection_id = 10104675682455674284U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_Put_presult() throw() {} + + Code* success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class DB_Delete_args { + public: + + static const uint64_t _reflection_id = 14071755674720794316U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_Delete_args() { + } + + DB_Delete_args(const DB_Delete_args&) = default; + DB_Delete_args& operator=(const DB_Delete_args&) = default; + DB_Delete_args(DB_Delete_args&&) = default; + DB_Delete_args& operator=(DB_Delete_args&&) = default; + + void __clear() { + dbhandle.__clear(); + key.__clear(); + options.__clear(); + __isset.__clear(); + } + + virtual ~DB_Delete_args() throw() {} + + DBHandle dbhandle; + Slice key; + WriteOptions options; + + struct __isset { + __isset() { __clear(); } + void __clear() { + dbhandle = false; + key = false; + options = false; + } + bool dbhandle; + bool key; + bool options; + } __isset; + + bool operator == (const DB_Delete_args & rhs) const + { + if (!(this->dbhandle == rhs.dbhandle)) + return false; + if (!(this->key == rhs.key)) + return false; + if (!(this->options == rhs.options)) + return false; + return true; + } + bool operator != (const DB_Delete_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_Delete_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_Delete_pargs { + public: + + static const uint64_t _reflection_id = 10963630852202029196U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_Delete_pargs() throw() {} + + const DBHandle* dbhandle; + const Slice* key; + const WriteOptions* options; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_Delete_result { + public: + + static const uint64_t _reflection_id = 13146432606937654604U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_Delete_result() : success(static_cast(0)) { + } + + DB_Delete_result(const DB_Delete_result&) = default; + DB_Delete_result& operator=(const DB_Delete_result&) = default; + DB_Delete_result(DB_Delete_result&&) = default; + DB_Delete_result& operator=(DB_Delete_result&&) = default; + + void __clear() { + success = static_cast(0); + __isset.__clear(); + } + + virtual ~DB_Delete_result() throw() {} + + Code success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + bool operator == (const DB_Delete_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + return true; + } + bool operator != (const DB_Delete_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_Delete_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_Delete_presult { + public: + + static const uint64_t _reflection_id = 17322073978832327340U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_Delete_presult() throw() {} + + Code* success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class DB_Write_args { + public: + + static const uint64_t _reflection_id = 12580138032621479660U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_Write_args() { + } + + DB_Write_args(const DB_Write_args&) = default; + DB_Write_args& operator=(const DB_Write_args&) = default; + DB_Write_args(DB_Write_args&&) = default; + DB_Write_args& operator=(DB_Write_args&&) = default; + + void __clear() { + dbhandle.__clear(); + batch.clear(); + options.__clear(); + __isset.__clear(); + } + + virtual ~DB_Write_args() throw() {} + + DBHandle dbhandle; + std::vector batch; + WriteOptions options; + + struct __isset { + __isset() { __clear(); } + void __clear() { + dbhandle = false; + batch = false; + options = false; + } + bool dbhandle; + bool batch; + bool options; + } __isset; + + bool operator == (const DB_Write_args & rhs) const + { + if (!(this->dbhandle == rhs.dbhandle)) + return false; + if (!(this->batch == rhs.batch)) + return false; + if (!(this->options == rhs.options)) + return false; + return true; + } + bool operator != (const DB_Write_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_Write_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_Write_pargs { + public: + + static const uint64_t _reflection_id = 3898152651480297548U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_Write_pargs() throw() {} + + const DBHandle* dbhandle; + const std::vector * batch; + const WriteOptions* options; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_Write_result { + public: + + static const uint64_t _reflection_id = 18306458689824631724U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_Write_result() : success(static_cast(0)) { + } + + DB_Write_result(const DB_Write_result&) = default; + DB_Write_result& operator=(const DB_Write_result&) = default; + DB_Write_result(DB_Write_result&&) = default; + DB_Write_result& operator=(DB_Write_result&&) = default; + + void __clear() { + success = static_cast(0); + __isset.__clear(); + } + + virtual ~DB_Write_result() throw() {} + + Code success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + bool operator == (const DB_Write_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + return true; + } + bool operator != (const DB_Write_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_Write_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_Write_presult { + public: + + static const uint64_t _reflection_id = 11189139329514764236U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_Write_presult() throw() {} + + Code* success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class DB_Get_args { + public: + + static const uint64_t _reflection_id = 5802112698229680972U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_Get_args() { + } + + DB_Get_args(const DB_Get_args&) = default; + DB_Get_args& operator=(const DB_Get_args&) = default; + DB_Get_args(DB_Get_args&&) = default; + DB_Get_args& operator=(DB_Get_args&&) = default; + + void __clear() { + dbhandle.__clear(); + inputkey.__clear(); + options.__clear(); + __isset.__clear(); + } + + virtual ~DB_Get_args() throw() {} + + DBHandle dbhandle; + Slice inputkey; + ReadOptions options; + + struct __isset { + __isset() { __clear(); } + void __clear() { + dbhandle = false; + inputkey = false; + options = false; + } + bool dbhandle; + bool inputkey; + bool options; + } __isset; + + bool operator == (const DB_Get_args & rhs) const + { + if (!(this->dbhandle == rhs.dbhandle)) + return false; + if (!(this->inputkey == rhs.inputkey)) + return false; + if (!(this->options == rhs.options)) + return false; + return true; + } + bool operator != (const DB_Get_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_Get_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_Get_pargs { + public: + + static const uint64_t _reflection_id = 775586916617672204U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_Get_pargs() throw() {} + + const DBHandle* dbhandle; + const Slice* inputkey; + const ReadOptions* options; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_Get_result { + public: + + static const uint64_t _reflection_id = 471316346092127948U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_Get_result() { + } + + DB_Get_result(const DB_Get_result&) = default; + DB_Get_result& operator=(const DB_Get_result&) = default; + DB_Get_result(DB_Get_result&&) = default; + DB_Get_result& operator=(DB_Get_result&&) = default; + + void __clear() { + success.__clear(); + __isset.__clear(); + } + + virtual ~DB_Get_result() throw() {} + + ResultItem success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + bool operator == (const DB_Get_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + return true; + } + bool operator != (const DB_Get_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_Get_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_Get_presult { + public: + + static const uint64_t _reflection_id = 15884536389555503916U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_Get_presult() throw() {} + + ResultItem* success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class DB_NewIterator_args { + public: + + static const uint64_t _reflection_id = 6645485240268124940U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_NewIterator_args() : iteratorType(static_cast(0)) { + } + + DB_NewIterator_args(const DB_NewIterator_args&) = default; + DB_NewIterator_args& operator=(const DB_NewIterator_args&) = default; + DB_NewIterator_args(DB_NewIterator_args&&) = default; + DB_NewIterator_args& operator=(DB_NewIterator_args&&) = default; + + void __clear() { + dbhandle.__clear(); + options.__clear(); + iteratorType = static_cast(0); + target.__clear(); + __isset.__clear(); + } + + virtual ~DB_NewIterator_args() throw() {} + + DBHandle dbhandle; + ReadOptions options; + IteratorType iteratorType; + Slice target; + + struct __isset { + __isset() { __clear(); } + void __clear() { + dbhandle = false; + options = false; + iteratorType = false; + target = false; + } + bool dbhandle; + bool options; + bool iteratorType; + bool target; + } __isset; + + bool operator == (const DB_NewIterator_args & rhs) const + { + if (!(this->dbhandle == rhs.dbhandle)) + return false; + if (!(this->options == rhs.options)) + return false; + if (!(this->iteratorType == rhs.iteratorType)) + return false; + if (!(this->target == rhs.target)) + return false; + return true; + } + bool operator != (const DB_NewIterator_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_NewIterator_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_NewIterator_pargs { + public: + + static const uint64_t _reflection_id = 5353644888786218764U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_NewIterator_pargs() throw() {} + + const DBHandle* dbhandle; + const ReadOptions* options; + const IteratorType* iteratorType; + const Slice* target; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_NewIterator_result { + public: + + static const uint64_t _reflection_id = 16747725486624219692U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_NewIterator_result() { + } + + DB_NewIterator_result(const DB_NewIterator_result&) = default; + DB_NewIterator_result& operator=(const DB_NewIterator_result&) = default; + DB_NewIterator_result(DB_NewIterator_result&&) = default; + DB_NewIterator_result& operator=(DB_NewIterator_result&&) = default; + + void __clear() { + success.__clear(); + __isset.__clear(); + } + + virtual ~DB_NewIterator_result() throw() {} + + ResultIterator success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + bool operator == (const DB_NewIterator_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + return true; + } + bool operator != (const DB_NewIterator_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_NewIterator_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_NewIterator_presult { + public: + + static const uint64_t _reflection_id = 30225981924653164U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_NewIterator_presult() throw() {} + + ResultIterator* success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class DB_DeleteIterator_args { + public: + + static const uint64_t _reflection_id = 15751789239200963564U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_DeleteIterator_args() { + } + + DB_DeleteIterator_args(const DB_DeleteIterator_args&) = default; + DB_DeleteIterator_args& operator=(const DB_DeleteIterator_args&) = default; + DB_DeleteIterator_args(DB_DeleteIterator_args&&) = default; + DB_DeleteIterator_args& operator=(DB_DeleteIterator_args&&) = default; + + void __clear() { + dbhandle.__clear(); + iterator.__clear(); + __isset.__clear(); + } + + virtual ~DB_DeleteIterator_args() throw() {} + + DBHandle dbhandle; + Iterator iterator; + + struct __isset { + __isset() { __clear(); } + void __clear() { + dbhandle = false; + iterator = false; + } + bool dbhandle; + bool iterator; + } __isset; + + bool operator == (const DB_DeleteIterator_args & rhs) const + { + if (!(this->dbhandle == rhs.dbhandle)) + return false; + if (!(this->iterator == rhs.iterator)) + return false; + return true; + } + bool operator != (const DB_DeleteIterator_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_DeleteIterator_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_DeleteIterator_pargs { + public: + + static const uint64_t _reflection_id = 6515929643750099916U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_DeleteIterator_pargs() throw() {} + + const DBHandle* dbhandle; + const Iterator* iterator; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_DeleteIterator_result { + public: + + static const uint64_t _reflection_id = 567840673627283948U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_DeleteIterator_result() : success(static_cast(0)) { + } + + DB_DeleteIterator_result(const DB_DeleteIterator_result&) = default; + DB_DeleteIterator_result& operator=(const DB_DeleteIterator_result&) = default; + DB_DeleteIterator_result(DB_DeleteIterator_result&&) = default; + DB_DeleteIterator_result& operator=(DB_DeleteIterator_result&&) = default; + + void __clear() { + success = static_cast(0); + __isset.__clear(); + } + + virtual ~DB_DeleteIterator_result() throw() {} + + Code success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + bool operator == (const DB_DeleteIterator_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + return true; + } + bool operator != (const DB_DeleteIterator_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_DeleteIterator_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_DeleteIterator_presult { + public: + + static const uint64_t _reflection_id = 16445220168564239308U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_DeleteIterator_presult() throw() {} + + Code* success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class DB_GetNext_args { + public: + + static const uint64_t _reflection_id = 6184101100378654860U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_GetNext_args() { + } + + DB_GetNext_args(const DB_GetNext_args&) = default; + DB_GetNext_args& operator=(const DB_GetNext_args&) = default; + DB_GetNext_args(DB_GetNext_args&&) = default; + DB_GetNext_args& operator=(DB_GetNext_args&&) = default; + + void __clear() { + dbhandle.__clear(); + iterator.__clear(); + __isset.__clear(); + } + + virtual ~DB_GetNext_args() throw() {} + + DBHandle dbhandle; + Iterator iterator; + + struct __isset { + __isset() { __clear(); } + void __clear() { + dbhandle = false; + iterator = false; + } + bool dbhandle; + bool iterator; + } __isset; + + bool operator == (const DB_GetNext_args & rhs) const + { + if (!(this->dbhandle == rhs.dbhandle)) + return false; + if (!(this->iterator == rhs.iterator)) + return false; + return true; + } + bool operator != (const DB_GetNext_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_GetNext_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_GetNext_pargs { + public: + + static const uint64_t _reflection_id = 14242404761042565548U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_GetNext_pargs() throw() {} + + const DBHandle* dbhandle; + const Iterator* iterator; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_GetNext_result { + public: + + static const uint64_t _reflection_id = 824363650095435948U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_GetNext_result() { + } + + DB_GetNext_result(const DB_GetNext_result&) = default; + DB_GetNext_result& operator=(const DB_GetNext_result&) = default; + DB_GetNext_result(DB_GetNext_result&&) = default; + DB_GetNext_result& operator=(DB_GetNext_result&&) = default; + + void __clear() { + success.__clear(); + __isset.__clear(); + } + + virtual ~DB_GetNext_result() throw() {} + + ResultPair success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + bool operator == (const DB_GetNext_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + return true; + } + bool operator != (const DB_GetNext_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_GetNext_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_GetNext_presult { + public: + + static const uint64_t _reflection_id = 17974802380941600588U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_GetNext_presult() throw() {} + + ResultPair* success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class DB_GetPrev_args { + public: + + static const uint64_t _reflection_id = 8870271973715332140U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_GetPrev_args() { + } + + DB_GetPrev_args(const DB_GetPrev_args&) = default; + DB_GetPrev_args& operator=(const DB_GetPrev_args&) = default; + DB_GetPrev_args(DB_GetPrev_args&&) = default; + DB_GetPrev_args& operator=(DB_GetPrev_args&&) = default; + + void __clear() { + dbhandle.__clear(); + iterator.__clear(); + __isset.__clear(); + } + + virtual ~DB_GetPrev_args() throw() {} + + DBHandle dbhandle; + Iterator iterator; + + struct __isset { + __isset() { __clear(); } + void __clear() { + dbhandle = false; + iterator = false; + } + bool dbhandle; + bool iterator; + } __isset; + + bool operator == (const DB_GetPrev_args & rhs) const + { + if (!(this->dbhandle == rhs.dbhandle)) + return false; + if (!(this->iterator == rhs.iterator)) + return false; + return true; + } + bool operator != (const DB_GetPrev_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_GetPrev_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_GetPrev_pargs { + public: + + static const uint64_t _reflection_id = 16552208169457784972U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_GetPrev_pargs() throw() {} + + const DBHandle* dbhandle; + const Iterator* iterator; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_GetPrev_result { + public: + + static const uint64_t _reflection_id = 17005837545637039820U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_GetPrev_result() { + } + + DB_GetPrev_result(const DB_GetPrev_result&) = default; + DB_GetPrev_result& operator=(const DB_GetPrev_result&) = default; + DB_GetPrev_result(DB_GetPrev_result&&) = default; + DB_GetPrev_result& operator=(DB_GetPrev_result&&) = default; + + void __clear() { + success.__clear(); + __isset.__clear(); + } + + virtual ~DB_GetPrev_result() throw() {} + + ResultPair success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + bool operator == (const DB_GetPrev_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + return true; + } + bool operator != (const DB_GetPrev_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_GetPrev_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_GetPrev_presult { + public: + + static const uint64_t _reflection_id = 12518588444439336556U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_GetPrev_presult() throw() {} + + ResultPair* success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class DB_GetSnapshot_args { + public: + + static const uint64_t _reflection_id = 14984968825961323724U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_GetSnapshot_args() { + } + + DB_GetSnapshot_args(const DB_GetSnapshot_args&) = default; + DB_GetSnapshot_args& operator=(const DB_GetSnapshot_args&) = default; + DB_GetSnapshot_args(DB_GetSnapshot_args&&) = default; + DB_GetSnapshot_args& operator=(DB_GetSnapshot_args&&) = default; + + void __clear() { + dbhandle.__clear(); + __isset.__clear(); + } + + virtual ~DB_GetSnapshot_args() throw() {} + + DBHandle dbhandle; + + struct __isset { + __isset() { __clear(); } + void __clear() { + dbhandle = false; + } + bool dbhandle; + } __isset; + + bool operator == (const DB_GetSnapshot_args & rhs) const + { + if (!(this->dbhandle == rhs.dbhandle)) + return false; + return true; + } + bool operator != (const DB_GetSnapshot_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_GetSnapshot_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_GetSnapshot_pargs { + public: + + static const uint64_t _reflection_id = 7188867685881890956U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_GetSnapshot_pargs() throw() {} + + const DBHandle* dbhandle; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_GetSnapshot_result { + public: + + static const uint64_t _reflection_id = 18029040421792131212U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_GetSnapshot_result() { + } + + DB_GetSnapshot_result(const DB_GetSnapshot_result&) = default; + DB_GetSnapshot_result& operator=(const DB_GetSnapshot_result&) = default; + DB_GetSnapshot_result(DB_GetSnapshot_result&&) = default; + DB_GetSnapshot_result& operator=(DB_GetSnapshot_result&&) = default; + + void __clear() { + success.__clear(); + __isset.__clear(); + } + + virtual ~DB_GetSnapshot_result() throw() {} + + ResultSnapshot success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + bool operator == (const DB_GetSnapshot_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + return true; + } + bool operator != (const DB_GetSnapshot_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_GetSnapshot_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_GetSnapshot_presult { + public: + + static const uint64_t _reflection_id = 10451056179121017996U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_GetSnapshot_presult() throw() {} + + ResultSnapshot* success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class DB_ReleaseSnapshot_args { + public: + + static const uint64_t _reflection_id = 14945627971981075500U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_ReleaseSnapshot_args() { + } + + DB_ReleaseSnapshot_args(const DB_ReleaseSnapshot_args&) = default; + DB_ReleaseSnapshot_args& operator=(const DB_ReleaseSnapshot_args&) = default; + DB_ReleaseSnapshot_args(DB_ReleaseSnapshot_args&&) = default; + DB_ReleaseSnapshot_args& operator=(DB_ReleaseSnapshot_args&&) = default; + + void __clear() { + dbhandle.__clear(); + snapshot.__clear(); + __isset.__clear(); + } + + virtual ~DB_ReleaseSnapshot_args() throw() {} + + DBHandle dbhandle; + Snapshot snapshot; + + struct __isset { + __isset() { __clear(); } + void __clear() { + dbhandle = false; + snapshot = false; + } + bool dbhandle; + bool snapshot; + } __isset; + + bool operator == (const DB_ReleaseSnapshot_args & rhs) const + { + if (!(this->dbhandle == rhs.dbhandle)) + return false; + if (!(this->snapshot == rhs.snapshot)) + return false; + return true; + } + bool operator != (const DB_ReleaseSnapshot_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_ReleaseSnapshot_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_ReleaseSnapshot_pargs { + public: + + static const uint64_t _reflection_id = 8283387247692679788U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_ReleaseSnapshot_pargs() throw() {} + + const DBHandle* dbhandle; + const Snapshot* snapshot; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_ReleaseSnapshot_result { + public: + + static const uint64_t _reflection_id = 15486363403695239660U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_ReleaseSnapshot_result() : success(static_cast(0)) { + } + + DB_ReleaseSnapshot_result(const DB_ReleaseSnapshot_result&) = default; + DB_ReleaseSnapshot_result& operator=(const DB_ReleaseSnapshot_result&) = default; + DB_ReleaseSnapshot_result(DB_ReleaseSnapshot_result&&) = default; + DB_ReleaseSnapshot_result& operator=(DB_ReleaseSnapshot_result&&) = default; + + void __clear() { + success = static_cast(0); + __isset.__clear(); + } + + virtual ~DB_ReleaseSnapshot_result() throw() {} + + Code success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + bool operator == (const DB_ReleaseSnapshot_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + return true; + } + bool operator != (const DB_ReleaseSnapshot_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_ReleaseSnapshot_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_ReleaseSnapshot_presult { + public: + + static const uint64_t _reflection_id = 13925350785061977420U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_ReleaseSnapshot_presult() throw() {} + + Code* success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class DB_CompactRange_args { + public: + + static const uint64_t _reflection_id = 6075170995358567596U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_CompactRange_args() { + } + + DB_CompactRange_args(const DB_CompactRange_args&) = default; + DB_CompactRange_args& operator=(const DB_CompactRange_args&) = default; + DB_CompactRange_args(DB_CompactRange_args&&) = default; + DB_CompactRange_args& operator=(DB_CompactRange_args&&) = default; + + void __clear() { + dbhandle.__clear(); + start.__clear(); + endhere.__clear(); + __isset.__clear(); + } + + virtual ~DB_CompactRange_args() throw() {} + + DBHandle dbhandle; + Slice start; + Slice endhere; + + struct __isset { + __isset() { __clear(); } + void __clear() { + dbhandle = false; + start = false; + endhere = false; + } + bool dbhandle; + bool start; + bool endhere; + } __isset; + + bool operator == (const DB_CompactRange_args & rhs) const + { + if (!(this->dbhandle == rhs.dbhandle)) + return false; + if (!(this->start == rhs.start)) + return false; + if (!(this->endhere == rhs.endhere)) + return false; + return true; + } + bool operator != (const DB_CompactRange_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_CompactRange_args & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_CompactRange_pargs { + public: + + static const uint64_t _reflection_id = 11177200356381642316U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_CompactRange_pargs() throw() {} + + const DBHandle* dbhandle; + const Slice* start; + const Slice* endhere; + + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_CompactRange_result { + public: + + static const uint64_t _reflection_id = 12835198829390966636U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DB_CompactRange_result() : success(static_cast(0)) { + } + + DB_CompactRange_result(const DB_CompactRange_result&) = default; + DB_CompactRange_result& operator=(const DB_CompactRange_result&) = default; + DB_CompactRange_result(DB_CompactRange_result&&) = default; + DB_CompactRange_result& operator=(DB_CompactRange_result&&) = default; + + void __clear() { + success = static_cast(0); + __isset.__clear(); + } + + virtual ~DB_CompactRange_result() throw() {} + + Code success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + bool operator == (const DB_CompactRange_result & rhs) const + { + if (!(this->success == rhs.success)) + return false; + return true; + } + bool operator != (const DB_CompactRange_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DB_CompactRange_result & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DB_CompactRange_presult { + public: + + static const uint64_t _reflection_id = 14927478234826947852U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + + virtual ~DB_CompactRange_presult() throw() {} + + Code* success; + + struct __isset { + __isset() { __clear(); } + void __clear() { + success = false; + } + bool success; + } __isset; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + +}; + +class DBClient : virtual public DBIf, virtual public apache::thrift::TClientBase { + public: + DBClient(boost::shared_ptr prot) : + checkSeqid_(true), + nextSendSequenceId_(1), + nextRecvSequenceId_(1), + piprot_(prot), + poprot_(prot) { + iprot_ = prot.get(); + oprot_ = prot.get(); + } + DBClient(boost::shared_ptr iprot, boost::shared_ptr oprot) : + checkSeqid_(true), + nextSendSequenceId_(1), + nextRecvSequenceId_(1), + piprot_(iprot), + poprot_(oprot) { + iprot_ = iprot.get(); + oprot_ = oprot.get(); + } + boost::shared_ptr getInputProtocol() { + return piprot_; + } + boost::shared_ptr getOutputProtocol() { + return poprot_; + } + void Open(DBHandle& _return, const Text& dbname, const DBOptions& dboptions); + void send_Open(const Text& dbname, const DBOptions& dboptions); + void recv_Open(DBHandle& _return); + Code Close(const DBHandle& dbhandle, const Text& dbname); + void send_Close(const DBHandle& dbhandle, const Text& dbname); + Code recv_Close(); + Code Put(const DBHandle& dbhandle, const kv& keyvalue, const WriteOptions& options); + void send_Put(const DBHandle& dbhandle, const kv& keyvalue, const WriteOptions& options); + Code recv_Put(); + Code Delete(const DBHandle& dbhandle, const Slice& key, const WriteOptions& options); + void send_Delete(const DBHandle& dbhandle, const Slice& key, const WriteOptions& options); + Code recv_Delete(); + Code Write(const DBHandle& dbhandle, const std::vector & batch, const WriteOptions& options); + void send_Write(const DBHandle& dbhandle, const std::vector & batch, const WriteOptions& options); + Code recv_Write(); + void Get(ResultItem& _return, const DBHandle& dbhandle, const Slice& inputkey, const ReadOptions& options); + void send_Get(const DBHandle& dbhandle, const Slice& inputkey, const ReadOptions& options); + void recv_Get(ResultItem& _return); + void NewIterator(ResultIterator& _return, const DBHandle& dbhandle, const ReadOptions& options, IteratorType iteratorType, const Slice& target); + void send_NewIterator(const DBHandle& dbhandle, const ReadOptions& options, IteratorType iteratorType, const Slice& target); + void recv_NewIterator(ResultIterator& _return); + Code DeleteIterator(const DBHandle& dbhandle, const Iterator& iterator); + void send_DeleteIterator(const DBHandle& dbhandle, const Iterator& iterator); + Code recv_DeleteIterator(); + void GetNext(ResultPair& _return, const DBHandle& dbhandle, const Iterator& iterator); + void send_GetNext(const DBHandle& dbhandle, const Iterator& iterator); + void recv_GetNext(ResultPair& _return); + void GetPrev(ResultPair& _return, const DBHandle& dbhandle, const Iterator& iterator); + void send_GetPrev(const DBHandle& dbhandle, const Iterator& iterator); + void recv_GetPrev(ResultPair& _return); + void GetSnapshot(ResultSnapshot& _return, const DBHandle& dbhandle); + void send_GetSnapshot(const DBHandle& dbhandle); + void recv_GetSnapshot(ResultSnapshot& _return); + Code ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot); + void send_ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot); + Code recv_ReleaseSnapshot(); + Code CompactRange(const DBHandle& dbhandle, const Slice& start, const Slice& endhere); + void send_CompactRange(const DBHandle& dbhandle, const Slice& start, const Slice& endhere); + Code recv_CompactRange(); + + /** + * Disable checking the seqid field in server responses. + * + * This should only be used with broken servers that return incorrect seqid values. + */ + void _disableSequenceIdChecks() { + checkSeqid_ = false; + } + + protected: + bool checkSeqid_; + int32_t nextSendSequenceId_; + int32_t nextRecvSequenceId_; + int32_t getNextSendSequenceId(); + int32_t getNextRecvSequenceId(); + boost::shared_ptr piprot_; + boost::shared_ptr poprot_; + apache::thrift::protocol::TProtocol* iprot_; + apache::thrift::protocol::TProtocol* oprot_; +}; + +class DBProcessor : public ::apache::thrift::TDispatchProcessor { + protected: + boost::shared_ptr iface_; + virtual bool dispatchCall(apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, const std::string& fname, int32_t seqid, apache::thrift::server::TConnectionContext* connectionContext); + private: + typedef void (DBProcessor::*ProcessFunction)(int32_t, apache::thrift::protocol::TProtocol*, apache::thrift::protocol::TProtocol*, apache::thrift::server::TConnectionContext*); + typedef std::map ProcessMap; + ProcessMap processMap_; + void process_Open(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + void process_Close(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + void process_Put(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + void process_Delete(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + void process_Write(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + void process_Get(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + void process_NewIterator(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + void process_DeleteIterator(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + void process_GetNext(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + void process_GetPrev(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + void process_GetSnapshot(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + void process_ReleaseSnapshot(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + void process_CompactRange(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, apache::thrift::server::TConnectionContext* connectionContext); + public: + DBProcessor(boost::shared_ptr iface) : + iface_(iface) { + processMap_["Open"] = &DBProcessor::process_Open; + processMap_["Close"] = &DBProcessor::process_Close; + processMap_["Put"] = &DBProcessor::process_Put; + processMap_["Delete"] = &DBProcessor::process_Delete; + processMap_["Write"] = &DBProcessor::process_Write; + processMap_["Get"] = &DBProcessor::process_Get; + processMap_["NewIterator"] = &DBProcessor::process_NewIterator; + processMap_["DeleteIterator"] = &DBProcessor::process_DeleteIterator; + processMap_["GetNext"] = &DBProcessor::process_GetNext; + processMap_["GetPrev"] = &DBProcessor::process_GetPrev; + processMap_["GetSnapshot"] = &DBProcessor::process_GetSnapshot; + processMap_["ReleaseSnapshot"] = &DBProcessor::process_ReleaseSnapshot; + processMap_["CompactRange"] = &DBProcessor::process_CompactRange; + } + + virtual ~DBProcessor() {} + + boost::shared_ptr > getProcessFunctions() { + boost::shared_ptr > rSet(new std::set()); + rSet->insert("DB.Open"); + rSet->insert("DB.Close"); + rSet->insert("DB.Put"); + rSet->insert("DB.Delete"); + rSet->insert("DB.Write"); + rSet->insert("DB.Get"); + rSet->insert("DB.NewIterator"); + rSet->insert("DB.DeleteIterator"); + rSet->insert("DB.GetNext"); + rSet->insert("DB.GetPrev"); + rSet->insert("DB.GetSnapshot"); + rSet->insert("DB.ReleaseSnapshot"); + rSet->insert("DB.CompactRange"); + return rSet; + } +}; + +class DBProcessorFactory : public ::apache::thrift::TProcessorFactory { + public: + DBProcessorFactory(const ::boost::shared_ptr< DBIfFactory >& handlerFactory) : + handlerFactory_(handlerFactory) {} + + ::boost::shared_ptr< ::apache::thrift::TProcessor > getProcessor(::apache::thrift::server::TConnectionContext* ctx); + + protected: + ::boost::shared_ptr< DBIfFactory > handlerFactory_; +}; + +class DBMultiface : virtual public DBIf { + public: + DBMultiface(std::vector >& ifaces) : ifaces_(ifaces) { + } + virtual ~DBMultiface() {} + protected: + std::vector > ifaces_; + DBMultiface() {} + void add(boost::shared_ptr iface) { + ifaces_.push_back(iface); + } + public: + void Open(DBHandle& _return, const Text& dbname, const DBOptions& dboptions) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz; ++i) { + ifaces_[i]->Open(_return, dbname, dboptions); + } + } + + Code Close(const DBHandle& dbhandle, const Text& dbname) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz - 1; ++i) { + ifaces_[i]->Close(dbhandle, dbname); + } + return ifaces_[i]->Close(dbhandle, dbname); + } + + Code Put(const DBHandle& dbhandle, const kv& keyvalue, const WriteOptions& options) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz - 1; ++i) { + ifaces_[i]->Put(dbhandle, keyvalue, options); + } + return ifaces_[i]->Put(dbhandle, keyvalue, options); + } + + Code Delete(const DBHandle& dbhandle, const Slice& key, const WriteOptions& options) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz - 1; ++i) { + ifaces_[i]->Delete(dbhandle, key, options); + } + return ifaces_[i]->Delete(dbhandle, key, options); + } + + Code Write(const DBHandle& dbhandle, const std::vector & batch, const WriteOptions& options) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz - 1; ++i) { + ifaces_[i]->Write(dbhandle, batch, options); + } + return ifaces_[i]->Write(dbhandle, batch, options); + } + + void Get(ResultItem& _return, const DBHandle& dbhandle, const Slice& inputkey, const ReadOptions& options) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz; ++i) { + ifaces_[i]->Get(_return, dbhandle, inputkey, options); + } + } + + void NewIterator(ResultIterator& _return, const DBHandle& dbhandle, const ReadOptions& options, IteratorType iteratorType, const Slice& target) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz; ++i) { + ifaces_[i]->NewIterator(_return, dbhandle, options, iteratorType, target); + } + } + + Code DeleteIterator(const DBHandle& dbhandle, const Iterator& iterator) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz - 1; ++i) { + ifaces_[i]->DeleteIterator(dbhandle, iterator); + } + return ifaces_[i]->DeleteIterator(dbhandle, iterator); + } + + void GetNext(ResultPair& _return, const DBHandle& dbhandle, const Iterator& iterator) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz; ++i) { + ifaces_[i]->GetNext(_return, dbhandle, iterator); + } + } + + void GetPrev(ResultPair& _return, const DBHandle& dbhandle, const Iterator& iterator) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz; ++i) { + ifaces_[i]->GetPrev(_return, dbhandle, iterator); + } + } + + void GetSnapshot(ResultSnapshot& _return, const DBHandle& dbhandle) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz; ++i) { + ifaces_[i]->GetSnapshot(_return, dbhandle); + } + } + + Code ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz - 1; ++i) { + ifaces_[i]->ReleaseSnapshot(dbhandle, snapshot); + } + return ifaces_[i]->ReleaseSnapshot(dbhandle, snapshot); + } + + Code CompactRange(const DBHandle& dbhandle, const Slice& start, const Slice& endhere) { + uint32_t i; + uint32_t sz = ifaces_.size(); + for (i = 0; i < sz - 1; ++i) { + ifaces_[i]->CompactRange(dbhandle, start, endhere); + } + return ifaces_[i]->CompactRange(dbhandle, start, endhere); + } + +}; + +} // namespace + +#endif diff --git a/thrift/gen-cpp/leveldb_constants.cpp b/thrift/gen-cpp/leveldb_constants.cpp new file mode 100644 index 00000000..383e58a4 --- /dev/null +++ b/thrift/gen-cpp/leveldb_constants.cpp @@ -0,0 +1,17 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "leveldb_constants.h" + +namespace Tleveldb { + +const leveldbConstants g_leveldb_constants; + +leveldbConstants::leveldbConstants() { +} + +} // namespace + diff --git a/thrift/gen-cpp/leveldb_constants.h b/thrift/gen-cpp/leveldb_constants.h new file mode 100644 index 00000000..d219f263 --- /dev/null +++ b/thrift/gen-cpp/leveldb_constants.h @@ -0,0 +1,24 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef leveldb_CONSTANTS_H +#define leveldb_CONSTANTS_H + +#include "leveldb_types.h" + +namespace Tleveldb { + +class leveldbConstants { + public: + leveldbConstants(); + +}; + +extern const leveldbConstants g_leveldb_constants; + +} // namespace + +#endif diff --git a/thrift/gen-cpp/leveldb_types.cpp b/thrift/gen-cpp/leveldb_types.cpp new file mode 100644 index 00000000..4654ee21 --- /dev/null +++ b/thrift/gen-cpp/leveldb_types.cpp @@ -0,0 +1,2143 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "leveldb_types.h" + +#include +#include +#include + +namespace Tleveldb { + +int _kCompressionTypeValues[] = { + kNoCompression, + kSnappyCompression +}; + +const char* _kCompressionTypeNames[] = { + "kNoCompression", + "kSnappyCompression" +}; + +const std::map _CompressionType_VALUES_TO_NAMES(apache::thrift::TEnumIterator(2, _kCompressionTypeValues, _kCompressionTypeNames), apache::thrift::TEnumIterator(-1, NULL, NULL)); + +const std::map _CompressionType_NAMES_TO_VALUES(apache::thrift::TEnumInverseIterator(2, _kCompressionTypeValues, _kCompressionTypeNames), apache::thrift::TEnumInverseIterator(-1, NULL, NULL)); + +} // namespace +namespace apache { namespace thrift { +template<> +const char* TEnumTraits< ::Tleveldb::CompressionType>::findName( ::Tleveldb::CompressionType value) { +return findName( ::Tleveldb::_CompressionType_VALUES_TO_NAMES, value); +} + +template<> +bool TEnumTraits< ::Tleveldb::CompressionType>::findValue(const char* name, ::Tleveldb::CompressionType* out) { +return findValue( ::Tleveldb::_CompressionType_NAMES_TO_VALUES, name, out); +} +}} // apache::thrift + +namespace Tleveldb { +int _kCodeValues[] = { + kOk, + kNotFound, + kCorruption, + kNotSupported, + kInvalidArgument, + kIOError, + kEnd +}; + +const char* _kCodeNames[] = { + "kOk", + "kNotFound", + "kCorruption", + "kNotSupported", + "kInvalidArgument", + "kIOError", + "kEnd" +}; + +const std::map _Code_VALUES_TO_NAMES(apache::thrift::TEnumIterator(7, _kCodeValues, _kCodeNames), apache::thrift::TEnumIterator(-1, NULL, NULL)); + +const std::map _Code_NAMES_TO_VALUES(apache::thrift::TEnumInverseIterator(7, _kCodeValues, _kCodeNames), apache::thrift::TEnumInverseIterator(-1, NULL, NULL)); + +} // namespace +namespace apache { namespace thrift { +template<> +const char* TEnumTraits< ::Tleveldb::Code>::findName( ::Tleveldb::Code value) { +return findName( ::Tleveldb::_Code_VALUES_TO_NAMES, value); +} + +template<> +bool TEnumTraits< ::Tleveldb::Code>::findValue(const char* name, ::Tleveldb::Code* out) { +return findValue( ::Tleveldb::_Code_NAMES_TO_VALUES, name, out); +} +}} // apache::thrift + +namespace Tleveldb { +int _kIteratorTypeValues[] = { + seekToFirst, + seekToLast, + seekToKey +}; + +const char* _kIteratorTypeNames[] = { + "seekToFirst", + "seekToLast", + "seekToKey" +}; + +const std::map _IteratorType_VALUES_TO_NAMES(apache::thrift::TEnumIterator(3, _kIteratorTypeValues, _kIteratorTypeNames), apache::thrift::TEnumIterator(-1, NULL, NULL)); + +const std::map _IteratorType_NAMES_TO_VALUES(apache::thrift::TEnumInverseIterator(3, _kIteratorTypeValues, _kIteratorTypeNames), apache::thrift::TEnumInverseIterator(-1, NULL, NULL)); + +} // namespace +namespace apache { namespace thrift { +template<> +const char* TEnumTraits< ::Tleveldb::IteratorType>::findName( ::Tleveldb::IteratorType value) { +return findName( ::Tleveldb::_IteratorType_VALUES_TO_NAMES, value); +} + +template<> +bool TEnumTraits< ::Tleveldb::IteratorType>::findValue(const char* name, ::Tleveldb::IteratorType* out) { +return findValue( ::Tleveldb::_IteratorType_NAMES_TO_VALUES, name, out); +} +}} // apache::thrift + +namespace Tleveldb { +int _kAssocVisibilityValues[] = { + VISIBLE, + DELETED, + UNUSED1, + HIDDEN, + UNUSED2, + HARD_DELETE +}; + +const char* _kAssocVisibilityNames[] = { + "VISIBLE", + "DELETED", + "UNUSED1", + "HIDDEN", + "UNUSED2", + "HARD_DELETE" +}; + +const std::map _AssocVisibility_VALUES_TO_NAMES(apache::thrift::TEnumIterator(6, _kAssocVisibilityValues, _kAssocVisibilityNames), apache::thrift::TEnumIterator(-1, NULL, NULL)); + +const std::map _AssocVisibility_NAMES_TO_VALUES(apache::thrift::TEnumInverseIterator(6, _kAssocVisibilityValues, _kAssocVisibilityNames), apache::thrift::TEnumInverseIterator(-1, NULL, NULL)); + +} // namespace +namespace apache { namespace thrift { +template<> +const char* TEnumTraits< ::Tleveldb::AssocVisibility>::findName( ::Tleveldb::AssocVisibility value) { +return findName( ::Tleveldb::_AssocVisibility_VALUES_TO_NAMES, value); +} + +template<> +bool TEnumTraits< ::Tleveldb::AssocVisibility>::findValue(const char* name, ::Tleveldb::AssocVisibility* out) { +return findValue( ::Tleveldb::_AssocVisibility_NAMES_TO_VALUES, name, out); +} +}} // apache::thrift + +namespace Tleveldb { +// Reflection initializer for struct leveldb.Slice +namespace { +void reflectionInitializer_2199896239461470156(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 2199896239461470156U; + if (schema.dataTypes.count(id)) return; + ::apache::thrift::reflection::DataType dt; + dt.name = "struct leveldb.Slice"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 1U; + f.name = "data"; + dt.fields[1] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 5U; + f.name = "size"; + dt.fields[2] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t Slice::_reflection_id; +void Slice::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_2199896239461470156(schema); +} +uint32_t Slice::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->data); + this->__isset.data = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->size); + this->__isset.size = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t Slice::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("Slice"); + xfer += oprot->writeFieldBegin("data", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary(this->data); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("size", apache::thrift::protocol::T_I32, 2); + xfer += oprot->writeI32(this->size); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(Slice &a, Slice &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.data, b.data); + swap(a.size, b.size); + swap(a.__isset, b.__isset); +} + +// Reflection initializer for struct leveldb.Range +namespace { +void reflectionInitializer_6170219570187881516(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 6170219570187881516U; + if (schema.dataTypes.count(id)) return; + reflectionInitializer_2199896239461470156(schema); // struct leveldb.Slice + ::apache::thrift::reflection::DataType dt; + dt.name = "struct leveldb.Range"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 2199896239461470156U; + f.name = "start"; + dt.fields[1] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 2199896239461470156U; + f.name = "limit"; + dt.fields[2] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t Range::_reflection_id; +void Range::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_6170219570187881516(schema); +} +uint32_t Range::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->start.read(iprot); + this->__isset.start = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->limit.read(iprot); + this->__isset.limit = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t Range::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("Range"); + xfer += oprot->writeFieldBegin("start", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->start.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("limit", apache::thrift::protocol::T_STRUCT, 2); + xfer += this->limit.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(Range &a, Range &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.start, b.start); + swap(a.limit, b.limit); + swap(a.__isset, b.__isset); +} + +// Reflection initializer for enum leveldb.CompressionType +namespace { +void reflectionInitializer_13050266898380890824(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 13050266898380890824U; + if (schema.dataTypes.count(id)) return; + ::apache::thrift::reflection::DataType dt; + dt.name = "enum leveldb.CompressionType"; + dt.__isset.enumValues = true; + dt.enumValues["kNoCompression"] = 0; + dt.enumValues["kSnappyCompression"] = 1; + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +// Reflection initializer for struct leveldb.DBOptions +namespace { +void reflectionInitializer_6731746507948871532(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 6731746507948871532U; + if (schema.dataTypes.count(id)) return; + reflectionInitializer_13050266898380890824(schema); // enum leveldb.CompressionType + ::apache::thrift::reflection::DataType dt; + dt.name = "struct leveldb.DBOptions"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 2U; + f.name = "create_if_missing"; + dt.fields[1] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 2U; + f.name = "error_if_exists"; + dt.fields[2] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 5U; + f.name = "write_buffer_size"; + dt.fields[3] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 5U; + f.name = "max_open_files"; + dt.fields[4] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 5U; + f.name = "block_size"; + dt.fields[5] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 5U; + f.name = "block_restart_interval"; + dt.fields[6] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 13050266898380890824U; + f.name = "compression"; + dt.fields[7] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 5U; + f.name = "num_levels"; + dt.fields[8] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 5U; + f.name = "level0_file_num_compaction_trigger"; + dt.fields[9] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 5U; + f.name = "level0_slowdown_writes_trigger"; + dt.fields[10] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 5U; + f.name = "level0_stop_writes_trigger"; + dt.fields[11] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 5U; + f.name = "target_file_size_base"; + dt.fields[12] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 5U; + f.name = "target_file_size_multiplier"; + dt.fields[13] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 5U; + f.name = "max_bytes_for_level_base"; + dt.fields[14] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 5U; + f.name = "max_bytes_for_level_multiplier"; + dt.fields[15] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 5U; + f.name = "max_grandparent_overlap_factor"; + dt.fields[16] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 2U; + f.name = "disableDataSync"; + dt.fields[17] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t DBOptions::_reflection_id; +void DBOptions::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_6731746507948871532(schema); +} +uint32_t DBOptions::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_BOOL) { + xfer += iprot->readBool(this->create_if_missing); + this->__isset.create_if_missing = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_BOOL) { + xfer += iprot->readBool(this->error_if_exists); + this->__isset.error_if_exists = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->write_buffer_size); + this->__isset.write_buffer_size = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->max_open_files); + this->__isset.max_open_files = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 5: + if (ftype == apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->block_size); + this->__isset.block_size = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 6: + if (ftype == apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->block_restart_interval); + this->__isset.block_restart_interval = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 7: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast0; + xfer += iprot->readI32(ecast0); + this->compression = (CompressionType)ecast0; + this->__isset.compression = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 8: + if (ftype == apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->num_levels); + this->__isset.num_levels = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 9: + if (ftype == apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->level0_file_num_compaction_trigger); + this->__isset.level0_file_num_compaction_trigger = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 10: + if (ftype == apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->level0_slowdown_writes_trigger); + this->__isset.level0_slowdown_writes_trigger = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 11: + if (ftype == apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->level0_stop_writes_trigger); + this->__isset.level0_stop_writes_trigger = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 12: + if (ftype == apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->target_file_size_base); + this->__isset.target_file_size_base = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 13: + if (ftype == apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->target_file_size_multiplier); + this->__isset.target_file_size_multiplier = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 14: + if (ftype == apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->max_bytes_for_level_base); + this->__isset.max_bytes_for_level_base = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 15: + if (ftype == apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->max_bytes_for_level_multiplier); + this->__isset.max_bytes_for_level_multiplier = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 16: + if (ftype == apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->max_grandparent_overlap_factor); + this->__isset.max_grandparent_overlap_factor = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 17: + if (ftype == apache::thrift::protocol::T_BOOL) { + xfer += iprot->readBool(this->disableDataSync); + this->__isset.disableDataSync = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DBOptions::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DBOptions"); + xfer += oprot->writeFieldBegin("create_if_missing", apache::thrift::protocol::T_BOOL, 1); + xfer += oprot->writeBool(this->create_if_missing); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("error_if_exists", apache::thrift::protocol::T_BOOL, 2); + xfer += oprot->writeBool(this->error_if_exists); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("write_buffer_size", apache::thrift::protocol::T_I32, 3); + xfer += oprot->writeI32(this->write_buffer_size); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("max_open_files", apache::thrift::protocol::T_I32, 4); + xfer += oprot->writeI32(this->max_open_files); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("block_size", apache::thrift::protocol::T_I32, 5); + xfer += oprot->writeI32(this->block_size); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("block_restart_interval", apache::thrift::protocol::T_I32, 6); + xfer += oprot->writeI32(this->block_restart_interval); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("compression", apache::thrift::protocol::T_I32, 7); + xfer += oprot->writeI32((int32_t)this->compression); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("num_levels", apache::thrift::protocol::T_I32, 8); + xfer += oprot->writeI32(this->num_levels); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("level0_file_num_compaction_trigger", apache::thrift::protocol::T_I32, 9); + xfer += oprot->writeI32(this->level0_file_num_compaction_trigger); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("level0_slowdown_writes_trigger", apache::thrift::protocol::T_I32, 10); + xfer += oprot->writeI32(this->level0_slowdown_writes_trigger); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("level0_stop_writes_trigger", apache::thrift::protocol::T_I32, 11); + xfer += oprot->writeI32(this->level0_stop_writes_trigger); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("target_file_size_base", apache::thrift::protocol::T_I32, 12); + xfer += oprot->writeI32(this->target_file_size_base); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("target_file_size_multiplier", apache::thrift::protocol::T_I32, 13); + xfer += oprot->writeI32(this->target_file_size_multiplier); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("max_bytes_for_level_base", apache::thrift::protocol::T_I32, 14); + xfer += oprot->writeI32(this->max_bytes_for_level_base); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("max_bytes_for_level_multiplier", apache::thrift::protocol::T_I32, 15); + xfer += oprot->writeI32(this->max_bytes_for_level_multiplier); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("max_grandparent_overlap_factor", apache::thrift::protocol::T_I32, 16); + xfer += oprot->writeI32(this->max_grandparent_overlap_factor); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("disableDataSync", apache::thrift::protocol::T_BOOL, 17); + xfer += oprot->writeBool(this->disableDataSync); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(DBOptions &a, DBOptions &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.create_if_missing, b.create_if_missing); + swap(a.error_if_exists, b.error_if_exists); + swap(a.write_buffer_size, b.write_buffer_size); + swap(a.max_open_files, b.max_open_files); + swap(a.block_size, b.block_size); + swap(a.block_restart_interval, b.block_restart_interval); + swap(a.compression, b.compression); + swap(a.num_levels, b.num_levels); + swap(a.level0_file_num_compaction_trigger, b.level0_file_num_compaction_trigger); + swap(a.level0_slowdown_writes_trigger, b.level0_slowdown_writes_trigger); + swap(a.level0_stop_writes_trigger, b.level0_stop_writes_trigger); + swap(a.target_file_size_base, b.target_file_size_base); + swap(a.target_file_size_multiplier, b.target_file_size_multiplier); + swap(a.max_bytes_for_level_base, b.max_bytes_for_level_base); + swap(a.max_bytes_for_level_multiplier, b.max_bytes_for_level_multiplier); + swap(a.max_grandparent_overlap_factor, b.max_grandparent_overlap_factor); + swap(a.disableDataSync, b.disableDataSync); + swap(a.__isset, b.__isset); +} + +// Reflection initializer for struct leveldb.WriteOptions +namespace { +void reflectionInitializer_8830325115029814540(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 8830325115029814540U; + if (schema.dataTypes.count(id)) return; + ::apache::thrift::reflection::DataType dt; + dt.name = "struct leveldb.WriteOptions"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 2U; + f.name = "sync"; + dt.fields[1] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 2U; + f.name = "disableWAL"; + dt.fields[2] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t WriteOptions::_reflection_id; +void WriteOptions::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_8830325115029814540(schema); +} +uint32_t WriteOptions::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_BOOL) { + xfer += iprot->readBool(this->sync); + this->__isset.sync = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_BOOL) { + xfer += iprot->readBool(this->disableWAL); + this->__isset.disableWAL = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t WriteOptions::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("WriteOptions"); + xfer += oprot->writeFieldBegin("sync", apache::thrift::protocol::T_BOOL, 1); + xfer += oprot->writeBool(this->sync); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("disableWAL", apache::thrift::protocol::T_BOOL, 2); + xfer += oprot->writeBool(this->disableWAL); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(WriteOptions &a, WriteOptions &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.sync, b.sync); + swap(a.disableWAL, b.disableWAL); + swap(a.__isset, b.__isset); +} + +// Reflection initializer for struct leveldb.Snapshot +namespace { +void reflectionInitializer_15670548806217660204(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 15670548806217660204U; + if (schema.dataTypes.count(id)) return; + ::apache::thrift::reflection::DataType dt; + dt.name = "struct leveldb.Snapshot"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 6U; + f.name = "snapshotid"; + dt.fields[1] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t Snapshot::_reflection_id; +void Snapshot::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_15670548806217660204(schema); +} +uint32_t Snapshot::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->snapshotid); + this->__isset.snapshotid = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t Snapshot::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("Snapshot"); + xfer += oprot->writeFieldBegin("snapshotid", apache::thrift::protocol::T_I64, 1); + xfer += oprot->writeI64(this->snapshotid); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(Snapshot &a, Snapshot &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.snapshotid, b.snapshotid); + swap(a.__isset, b.__isset); +} + +// Reflection initializer for struct leveldb.ReadOptions +namespace { +void reflectionInitializer_1092669993626789804(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 1092669993626789804U; + if (schema.dataTypes.count(id)) return; + reflectionInitializer_15670548806217660204(schema); // struct leveldb.Snapshot + ::apache::thrift::reflection::DataType dt; + dt.name = "struct leveldb.ReadOptions"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 2U; + f.name = "verify_checksums"; + dt.fields[1] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 2U; + f.name = "fill_cache"; + dt.fields[2] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 15670548806217660204U; + f.name = "snapshot"; + dt.fields[3] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t ReadOptions::_reflection_id; +void ReadOptions::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_1092669993626789804(schema); +} +uint32_t ReadOptions::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_BOOL) { + xfer += iprot->readBool(this->verify_checksums); + this->__isset.verify_checksums = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_BOOL) { + xfer += iprot->readBool(this->fill_cache); + this->__isset.fill_cache = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->snapshot.read(iprot); + this->__isset.snapshot = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ReadOptions::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ReadOptions"); + xfer += oprot->writeFieldBegin("verify_checksums", apache::thrift::protocol::T_BOOL, 1); + xfer += oprot->writeBool(this->verify_checksums); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("fill_cache", apache::thrift::protocol::T_BOOL, 2); + xfer += oprot->writeBool(this->fill_cache); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("snapshot", apache::thrift::protocol::T_STRUCT, 3); + xfer += this->snapshot.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(ReadOptions &a, ReadOptions &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.verify_checksums, b.verify_checksums); + swap(a.fill_cache, b.fill_cache); + swap(a.snapshot, b.snapshot); + swap(a.__isset, b.__isset); +} + +// Reflection initializer for struct leveldb.DBHandle +namespace { +void reflectionInitializer_8973827971994157004(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 8973827971994157004U; + if (schema.dataTypes.count(id)) return; + ::apache::thrift::reflection::DataType dt; + dt.name = "struct leveldb.DBHandle"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 1U; + f.name = "dbname"; + dt.fields[1] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t DBHandle::_reflection_id; +void DBHandle::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_8973827971994157004(schema); +} +uint32_t DBHandle::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->dbname); + this->__isset.dbname = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t DBHandle::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("DBHandle"); + xfer += oprot->writeFieldBegin("dbname", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary(this->dbname); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(DBHandle &a, DBHandle &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.dbname, b.dbname); + swap(a.__isset, b.__isset); +} + +// Reflection initializer for struct leveldb.Iterator +namespace { +void reflectionInitializer_11184146435197093740(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 11184146435197093740U; + if (schema.dataTypes.count(id)) return; + ::apache::thrift::reflection::DataType dt; + dt.name = "struct leveldb.Iterator"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 6U; + f.name = "iteratorid"; + dt.fields[1] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t Iterator::_reflection_id; +void Iterator::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_11184146435197093740(schema); +} +uint32_t Iterator::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->iteratorid); + this->__isset.iteratorid = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t Iterator::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("Iterator"); + xfer += oprot->writeFieldBegin("iteratorid", apache::thrift::protocol::T_I64, 1); + xfer += oprot->writeI64(this->iteratorid); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(Iterator &a, Iterator &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.iteratorid, b.iteratorid); + swap(a.__isset, b.__isset); +} + +// Reflection initializer for struct leveldb.kv +namespace { +void reflectionInitializer_16082992224095104076(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 16082992224095104076U; + if (schema.dataTypes.count(id)) return; + reflectionInitializer_2199896239461470156(schema); // struct leveldb.Slice + ::apache::thrift::reflection::DataType dt; + dt.name = "struct leveldb.kv"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 2199896239461470156U; + f.name = "key"; + dt.fields[1] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 2199896239461470156U; + f.name = "value"; + dt.fields[2] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t kv::_reflection_id; +void kv::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_16082992224095104076(schema); +} +uint32_t kv::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->key.read(iprot); + this->__isset.key = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->value.read(iprot); + this->__isset.value = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t kv::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("kv"); + xfer += oprot->writeFieldBegin("key", apache::thrift::protocol::T_STRUCT, 1); + xfer += this->key.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("value", apache::thrift::protocol::T_STRUCT, 2); + xfer += this->value.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(kv &a, kv &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.key, b.key); + swap(a.value, b.value); + swap(a.__isset, b.__isset); +} + +// Reflection initializer for enum leveldb.Code +namespace { +void reflectionInitializer_13230961887206242376(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 13230961887206242376U; + if (schema.dataTypes.count(id)) return; + ::apache::thrift::reflection::DataType dt; + dt.name = "enum leveldb.Code"; + dt.__isset.enumValues = true; + dt.enumValues["kCorruption"] = 2; + dt.enumValues["kEnd"] = 6; + dt.enumValues["kIOError"] = 5; + dt.enumValues["kInvalidArgument"] = 4; + dt.enumValues["kNotFound"] = 1; + dt.enumValues["kNotSupported"] = 3; + dt.enumValues["kOk"] = 0; + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +// Reflection initializer for struct leveldb.ResultItem +namespace { +void reflectionInitializer_13211316281207238796(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 13211316281207238796U; + if (schema.dataTypes.count(id)) return; + reflectionInitializer_13230961887206242376(schema); // enum leveldb.Code + reflectionInitializer_2199896239461470156(schema); // struct leveldb.Slice + ::apache::thrift::reflection::DataType dt; + dt.name = "struct leveldb.ResultItem"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 13230961887206242376U; + f.name = "status"; + dt.fields[1] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 2199896239461470156U; + f.name = "value"; + dt.fields[2] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t ResultItem::_reflection_id; +void ResultItem::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_13211316281207238796(schema); +} +uint32_t ResultItem::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast1; + xfer += iprot->readI32(ecast1); + this->status = (Code)ecast1; + this->__isset.status = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->value.read(iprot); + this->__isset.value = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ResultItem::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ResultItem"); + xfer += oprot->writeFieldBegin("status", apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32((int32_t)this->status); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("value", apache::thrift::protocol::T_STRUCT, 2); + xfer += this->value.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(ResultItem &a, ResultItem &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.status, b.status); + swap(a.value, b.value); + swap(a.__isset, b.__isset); +} + +// Reflection initializer for struct leveldb.ResultPair +namespace { +void reflectionInitializer_14875242256166808460(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 14875242256166808460U; + if (schema.dataTypes.count(id)) return; + reflectionInitializer_13230961887206242376(schema); // enum leveldb.Code + reflectionInitializer_16082992224095104076(schema); // struct leveldb.kv + ::apache::thrift::reflection::DataType dt; + dt.name = "struct leveldb.ResultPair"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 13230961887206242376U; + f.name = "status"; + dt.fields[1] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 16082992224095104076U; + f.name = "keyvalue"; + dt.fields[2] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t ResultPair::_reflection_id; +void ResultPair::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_14875242256166808460(schema); +} +uint32_t ResultPair::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast2; + xfer += iprot->readI32(ecast2); + this->status = (Code)ecast2; + this->__isset.status = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->keyvalue.read(iprot); + this->__isset.keyvalue = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ResultPair::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ResultPair"); + xfer += oprot->writeFieldBegin("status", apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32((int32_t)this->status); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("keyvalue", apache::thrift::protocol::T_STRUCT, 2); + xfer += this->keyvalue.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(ResultPair &a, ResultPair &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.status, b.status); + swap(a.keyvalue, b.keyvalue); + swap(a.__isset, b.__isset); +} + +// Reflection initializer for struct leveldb.ResultSnapshot +namespace { +void reflectionInitializer_16627180600575569004(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 16627180600575569004U; + if (schema.dataTypes.count(id)) return; + reflectionInitializer_13230961887206242376(schema); // enum leveldb.Code + reflectionInitializer_15670548806217660204(schema); // struct leveldb.Snapshot + ::apache::thrift::reflection::DataType dt; + dt.name = "struct leveldb.ResultSnapshot"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 13230961887206242376U; + f.name = "status"; + dt.fields[1] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 15670548806217660204U; + f.name = "snapshot"; + dt.fields[2] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t ResultSnapshot::_reflection_id; +void ResultSnapshot::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_16627180600575569004(schema); +} +uint32_t ResultSnapshot::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast3; + xfer += iprot->readI32(ecast3); + this->status = (Code)ecast3; + this->__isset.status = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->snapshot.read(iprot); + this->__isset.snapshot = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ResultSnapshot::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ResultSnapshot"); + xfer += oprot->writeFieldBegin("status", apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32((int32_t)this->status); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("snapshot", apache::thrift::protocol::T_STRUCT, 2); + xfer += this->snapshot.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(ResultSnapshot &a, ResultSnapshot &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.status, b.status); + swap(a.snapshot, b.snapshot); + swap(a.__isset, b.__isset); +} + +// Reflection initializer for struct leveldb.ResultIterator +namespace { +void reflectionInitializer_595886977232564460(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 595886977232564460U; + if (schema.dataTypes.count(id)) return; + reflectionInitializer_11184146435197093740(schema); // struct leveldb.Iterator + reflectionInitializer_13230961887206242376(schema); // enum leveldb.Code + ::apache::thrift::reflection::DataType dt; + dt.name = "struct leveldb.ResultIterator"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 13230961887206242376U; + f.name = "status"; + dt.fields[1] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 11184146435197093740U; + f.name = "iterator"; + dt.fields[2] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t ResultIterator::_reflection_id; +void ResultIterator::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_595886977232564460(schema); +} +uint32_t ResultIterator::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast4; + xfer += iprot->readI32(ecast4); + this->status = (Code)ecast4; + this->__isset.status = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_STRUCT) { + xfer += this->iterator.read(iprot); + this->__isset.iterator = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ResultIterator::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ResultIterator"); + xfer += oprot->writeFieldBegin("status", apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32((int32_t)this->status); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("iterator", apache::thrift::protocol::T_STRUCT, 2); + xfer += this->iterator.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(ResultIterator &a, ResultIterator &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.status, b.status); + swap(a.iterator, b.iterator); + swap(a.__isset, b.__isset); +} + +// Reflection initializer for struct leveldb.LeveldbException +namespace { +void reflectionInitializer_2551220192341843436(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 2551220192341843436U; + if (schema.dataTypes.count(id)) return; + reflectionInitializer_13230961887206242376(schema); // enum leveldb.Code + ::apache::thrift::reflection::DataType dt; + dt.name = "struct leveldb.LeveldbException"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 1U; + f.name = "message"; + dt.fields[1] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 13230961887206242376U; + f.name = "errorCode"; + dt.fields[2] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t LeveldbException::_reflection_id; +void LeveldbException::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_2551220192341843436(schema); +} +uint32_t LeveldbException::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->message); + this->__isset.message = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t ecast5; + xfer += iprot->readI32(ecast5); + this->errorCode = (Code)ecast5; + this->__isset.errorCode = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t LeveldbException::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("LeveldbException"); + xfer += oprot->writeFieldBegin("message", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeBinary(this->message); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("errorCode", apache::thrift::protocol::T_I32, 2); + xfer += oprot->writeI32((int32_t)this->errorCode); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(LeveldbException &a, LeveldbException &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.message, b.message); + swap(a.errorCode, b.errorCode); + swap(a.__isset, b.__isset); +} + +// Reflection initializer for struct leveldb.IOError +namespace { +void reflectionInitializer_8460881927871070060(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 8460881927871070060U; + if (schema.dataTypes.count(id)) return; + ::apache::thrift::reflection::DataType dt; + dt.name = "struct leveldb.IOError"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 1U; + f.name = "message"; + dt.fields[1] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t IOError::_reflection_id; +void IOError::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_8460881927871070060(schema); +} +uint32_t IOError::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->message); + this->__isset.message = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t IOError::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("IOError"); + xfer += oprot->writeFieldBegin("message", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->message); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(IOError &a, IOError &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.message, b.message); + swap(a.__isset, b.__isset); +} + +// Reflection initializer for struct leveldb.TaoAssocGetResult +namespace { +void reflectionInitializer_6301164048086986412(::apache::thrift::reflection::Schema& schema) { + const uint64_t id = 6301164048086986412U; + if (schema.dataTypes.count(id)) return; + ::apache::thrift::reflection::DataType dt; + dt.name = "struct leveldb.TaoAssocGetResult"; + dt.__isset.fields = true; + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 6U; + f.name = "id2"; + dt.fields[1] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 6U; + f.name = "id1Type"; + dt.fields[2] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 6U; + f.name = "id2Type"; + dt.fields[3] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 6U; + f.name = "time"; + dt.fields[4] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 6U; + f.name = "dataVersion"; + dt.fields[5] = f; + } + { + ::apache::thrift::reflection::StructField f; + f.isRequired = true; + f.type = 1U; + f.name = "data"; + dt.fields[6] = f; + } + schema.dataTypes[id] = dt; + schema.names[dt.name] = id; +} +} // namespace + +const uint64_t TaoAssocGetResult::_reflection_id; +void TaoAssocGetResult::_reflection_register(::apache::thrift::reflection::Schema& schema) { + reflectionInitializer_6301164048086986412(schema); +} +uint32_t TaoAssocGetResult::read(apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->id2); + this->__isset.id2 = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->id1Type); + this->__isset.id1Type = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->id2Type); + this->__isset.id2Type = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->time); + this->__isset.time = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 5: + if (ftype == apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->dataVersion); + this->__isset.dataVersion = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 6: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readBinary(this->data); + this->__isset.data = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t TaoAssocGetResult::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("TaoAssocGetResult"); + xfer += oprot->writeFieldBegin("id2", apache::thrift::protocol::T_I64, 1); + xfer += oprot->writeI64(this->id2); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id1Type", apache::thrift::protocol::T_I64, 2); + xfer += oprot->writeI64(this->id1Type); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("id2Type", apache::thrift::protocol::T_I64, 3); + xfer += oprot->writeI64(this->id2Type); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("time", apache::thrift::protocol::T_I64, 4); + xfer += oprot->writeI64(this->time); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("dataVersion", apache::thrift::protocol::T_I64, 5); + xfer += oprot->writeI64(this->dataVersion); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("data", apache::thrift::protocol::T_STRING, 6); + xfer += oprot->writeBinary(this->data); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(TaoAssocGetResult &a, TaoAssocGetResult &b) { + using ::std::swap; + (void)a; + (void)b; + swap(a.id2, b.id2); + swap(a.id1Type, b.id1Type); + swap(a.id2Type, b.id2Type); + swap(a.time, b.time); + swap(a.dataVersion, b.dataVersion); + swap(a.data, b.data); + swap(a.__isset, b.__isset); +} + +} // namespace diff --git a/thrift/gen-cpp/leveldb_types.h b/thrift/gen-cpp/leveldb_types.h new file mode 100644 index 00000000..117ed4f7 --- /dev/null +++ b/thrift/gen-cpp/leveldb_types.h @@ -0,0 +1,1126 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef leveldb_TYPES_H +#define leveldb_TYPES_H + +#include +#include +#include +#include + +namespace apache { namespace thrift { namespace reflection { +class Schema; +}}} + + +namespace Tleveldb { + +enum CompressionType { + kNoCompression = 0, + kSnappyCompression = 1 +}; + +extern const std::map _CompressionType_VALUES_TO_NAMES; + +extern const std::map _CompressionType_NAMES_TO_VALUES; + +} // namespace +namespace apache { namespace thrift { +template<> +inline constexpr ::Tleveldb::CompressionType TEnumTraits< ::Tleveldb::CompressionType>::min() { +return ::Tleveldb::CompressionType::kNoCompression; +} +template<> +inline constexpr ::Tleveldb::CompressionType TEnumTraits< ::Tleveldb::CompressionType>::max() { +return ::Tleveldb::CompressionType::kSnappyCompression; +} +}} // apache:thrift + +namespace Tleveldb { +enum Code { + kOk = 0, + kNotFound = 1, + kCorruption = 2, + kNotSupported = 3, + kInvalidArgument = 4, + kIOError = 5, + kEnd = 6 +}; + +extern const std::map _Code_VALUES_TO_NAMES; + +extern const std::map _Code_NAMES_TO_VALUES; + +} // namespace +namespace apache { namespace thrift { +template<> +inline constexpr ::Tleveldb::Code TEnumTraits< ::Tleveldb::Code>::min() { +return ::Tleveldb::Code::kOk; +} +template<> +inline constexpr ::Tleveldb::Code TEnumTraits< ::Tleveldb::Code>::max() { +return ::Tleveldb::Code::kEnd; +} +}} // apache:thrift + +namespace Tleveldb { +enum IteratorType { + seekToFirst = 0, + seekToLast = 1, + seekToKey = 2 +}; + +extern const std::map _IteratorType_VALUES_TO_NAMES; + +extern const std::map _IteratorType_NAMES_TO_VALUES; + +} // namespace +namespace apache { namespace thrift { +template<> +inline constexpr ::Tleveldb::IteratorType TEnumTraits< ::Tleveldb::IteratorType>::min() { +return ::Tleveldb::IteratorType::seekToFirst; +} +template<> +inline constexpr ::Tleveldb::IteratorType TEnumTraits< ::Tleveldb::IteratorType>::max() { +return ::Tleveldb::IteratorType::seekToKey; +} +}} // apache:thrift + +namespace Tleveldb { +enum AssocVisibility { + VISIBLE = 0, + DELETED = 1, + UNUSED1 = 2, + HIDDEN = 3, + UNUSED2 = 4, + HARD_DELETE = 4 +}; + +extern const std::map _AssocVisibility_VALUES_TO_NAMES; + +extern const std::map _AssocVisibility_NAMES_TO_VALUES; + +} // namespace +namespace apache { namespace thrift { +template<> +inline constexpr ::Tleveldb::AssocVisibility TEnumTraits< ::Tleveldb::AssocVisibility>::min() { +return ::Tleveldb::AssocVisibility::VISIBLE; +} +template<> +inline constexpr ::Tleveldb::AssocVisibility TEnumTraits< ::Tleveldb::AssocVisibility>::max() { +return ::Tleveldb::AssocVisibility::HARD_DELETE; +} +}} // apache:thrift + +namespace Tleveldb { +typedef std::string Text; + +typedef std::string Bytes; + +class Slice { + public: + + static const uint64_t _reflection_id = 2199896239461470156U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + Slice() : data(""), size(0) { + } + + Slice(const Slice&) = default; + Slice& operator=(const Slice&) = default; + Slice(Slice&&) = default; + Slice& operator=(Slice&&) = default; + + void __clear() { + data = ""; + size = 0; + __isset.__clear(); + } + + virtual ~Slice() throw() {} + + Text data; + int32_t size; + + struct __isset { + __isset() { __clear(); } + void __clear() { + data = false; + size = false; + } + bool data; + bool size; + } __isset; + + bool operator == (const Slice & rhs) const + { + if (!(this->data == rhs.data)) + return false; + if (!(this->size == rhs.size)) + return false; + return true; + } + bool operator != (const Slice &rhs) const { + return !(*this == rhs); + } + + bool operator < (const Slice & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class Slice; +void swap(Slice &a, Slice &b); + +class Range { + public: + + static const uint64_t _reflection_id = 6170219570187881516U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + Range() { + } + + Range(const Range&) = default; + Range& operator=(const Range&) = default; + Range(Range&&) = default; + Range& operator=(Range&&) = default; + + void __clear() { + start.__clear(); + limit.__clear(); + __isset.__clear(); + } + + virtual ~Range() throw() {} + + Slice start; + Slice limit; + + struct __isset { + __isset() { __clear(); } + void __clear() { + start = false; + limit = false; + } + bool start; + bool limit; + } __isset; + + bool operator == (const Range & rhs) const + { + if (!(this->start == rhs.start)) + return false; + if (!(this->limit == rhs.limit)) + return false; + return true; + } + bool operator != (const Range &rhs) const { + return !(*this == rhs); + } + + bool operator < (const Range & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class Range; +void swap(Range &a, Range &b); + +class DBOptions { + public: + + static const uint64_t _reflection_id = 6731746507948871532U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DBOptions() : create_if_missing(0), error_if_exists(0), write_buffer_size(0), max_open_files(0), block_size(0), block_restart_interval(0), compression(static_cast(0)), num_levels(0), level0_file_num_compaction_trigger(0), level0_slowdown_writes_trigger(0), level0_stop_writes_trigger(0), target_file_size_base(0), target_file_size_multiplier(0), max_bytes_for_level_base(0), max_bytes_for_level_multiplier(0), max_grandparent_overlap_factor(0), disableDataSync(0) { + } + + DBOptions(const DBOptions&) = default; + DBOptions& operator=(const DBOptions&) = default; + DBOptions(DBOptions&&) = default; + DBOptions& operator=(DBOptions&&) = default; + + void __clear() { + create_if_missing = 0; + error_if_exists = 0; + write_buffer_size = 0; + max_open_files = 0; + block_size = 0; + block_restart_interval = 0; + compression = static_cast(0); + num_levels = 0; + level0_file_num_compaction_trigger = 0; + level0_slowdown_writes_trigger = 0; + level0_stop_writes_trigger = 0; + target_file_size_base = 0; + target_file_size_multiplier = 0; + max_bytes_for_level_base = 0; + max_bytes_for_level_multiplier = 0; + max_grandparent_overlap_factor = 0; + disableDataSync = 0; + __isset.__clear(); + } + + virtual ~DBOptions() throw() {} + + bool create_if_missing; + bool error_if_exists; + int32_t write_buffer_size; + int32_t max_open_files; + int32_t block_size; + int32_t block_restart_interval; + CompressionType compression; + int32_t num_levels; + int32_t level0_file_num_compaction_trigger; + int32_t level0_slowdown_writes_trigger; + int32_t level0_stop_writes_trigger; + int32_t target_file_size_base; + int32_t target_file_size_multiplier; + int32_t max_bytes_for_level_base; + int32_t max_bytes_for_level_multiplier; + int32_t max_grandparent_overlap_factor; + bool disableDataSync; + + struct __isset { + __isset() { __clear(); } + void __clear() { + create_if_missing = false; + error_if_exists = false; + write_buffer_size = false; + max_open_files = false; + block_size = false; + block_restart_interval = false; + compression = false; + num_levels = false; + level0_file_num_compaction_trigger = false; + level0_slowdown_writes_trigger = false; + level0_stop_writes_trigger = false; + target_file_size_base = false; + target_file_size_multiplier = false; + max_bytes_for_level_base = false; + max_bytes_for_level_multiplier = false; + max_grandparent_overlap_factor = false; + disableDataSync = false; + } + bool create_if_missing; + bool error_if_exists; + bool write_buffer_size; + bool max_open_files; + bool block_size; + bool block_restart_interval; + bool compression; + bool num_levels; + bool level0_file_num_compaction_trigger; + bool level0_slowdown_writes_trigger; + bool level0_stop_writes_trigger; + bool target_file_size_base; + bool target_file_size_multiplier; + bool max_bytes_for_level_base; + bool max_bytes_for_level_multiplier; + bool max_grandparent_overlap_factor; + bool disableDataSync; + } __isset; + + bool operator == (const DBOptions & rhs) const + { + if (!(this->create_if_missing == rhs.create_if_missing)) + return false; + if (!(this->error_if_exists == rhs.error_if_exists)) + return false; + if (!(this->write_buffer_size == rhs.write_buffer_size)) + return false; + if (!(this->max_open_files == rhs.max_open_files)) + return false; + if (!(this->block_size == rhs.block_size)) + return false; + if (!(this->block_restart_interval == rhs.block_restart_interval)) + return false; + if (!(this->compression == rhs.compression)) + return false; + if (!(this->num_levels == rhs.num_levels)) + return false; + if (!(this->level0_file_num_compaction_trigger == rhs.level0_file_num_compaction_trigger)) + return false; + if (!(this->level0_slowdown_writes_trigger == rhs.level0_slowdown_writes_trigger)) + return false; + if (!(this->level0_stop_writes_trigger == rhs.level0_stop_writes_trigger)) + return false; + if (!(this->target_file_size_base == rhs.target_file_size_base)) + return false; + if (!(this->target_file_size_multiplier == rhs.target_file_size_multiplier)) + return false; + if (!(this->max_bytes_for_level_base == rhs.max_bytes_for_level_base)) + return false; + if (!(this->max_bytes_for_level_multiplier == rhs.max_bytes_for_level_multiplier)) + return false; + if (!(this->max_grandparent_overlap_factor == rhs.max_grandparent_overlap_factor)) + return false; + if (!(this->disableDataSync == rhs.disableDataSync)) + return false; + return true; + } + bool operator != (const DBOptions &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DBOptions & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DBOptions; +void swap(DBOptions &a, DBOptions &b); + +class WriteOptions { + public: + + static const uint64_t _reflection_id = 8830325115029814540U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + WriteOptions() : sync(0), disableWAL(0) { + } + + WriteOptions(const WriteOptions&) = default; + WriteOptions& operator=(const WriteOptions&) = default; + WriteOptions(WriteOptions&&) = default; + WriteOptions& operator=(WriteOptions&&) = default; + + void __clear() { + sync = 0; + disableWAL = 0; + __isset.__clear(); + } + + virtual ~WriteOptions() throw() {} + + bool sync; + bool disableWAL; + + struct __isset { + __isset() { __clear(); } + void __clear() { + sync = false; + disableWAL = false; + } + bool sync; + bool disableWAL; + } __isset; + + bool operator == (const WriteOptions & rhs) const + { + if (!(this->sync == rhs.sync)) + return false; + if (!(this->disableWAL == rhs.disableWAL)) + return false; + return true; + } + bool operator != (const WriteOptions &rhs) const { + return !(*this == rhs); + } + + bool operator < (const WriteOptions & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class WriteOptions; +void swap(WriteOptions &a, WriteOptions &b); + +class Snapshot { + public: + + static const uint64_t _reflection_id = 15670548806217660204U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + Snapshot() : snapshotid(0) { + } + + Snapshot(const Snapshot&) = default; + Snapshot& operator=(const Snapshot&) = default; + Snapshot(Snapshot&&) = default; + Snapshot& operator=(Snapshot&&) = default; + + void __clear() { + snapshotid = 0; + __isset.__clear(); + } + + virtual ~Snapshot() throw() {} + + int64_t snapshotid; + + struct __isset { + __isset() { __clear(); } + void __clear() { + snapshotid = false; + } + bool snapshotid; + } __isset; + + bool operator == (const Snapshot & rhs) const + { + if (!(this->snapshotid == rhs.snapshotid)) + return false; + return true; + } + bool operator != (const Snapshot &rhs) const { + return !(*this == rhs); + } + + bool operator < (const Snapshot & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class Snapshot; +void swap(Snapshot &a, Snapshot &b); + +class ReadOptions { + public: + + static const uint64_t _reflection_id = 1092669993626789804U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + ReadOptions() : verify_checksums(0), fill_cache(0) { + } + + ReadOptions(const ReadOptions&) = default; + ReadOptions& operator=(const ReadOptions&) = default; + ReadOptions(ReadOptions&&) = default; + ReadOptions& operator=(ReadOptions&&) = default; + + void __clear() { + verify_checksums = 0; + fill_cache = 0; + snapshot.__clear(); + __isset.__clear(); + } + + virtual ~ReadOptions() throw() {} + + bool verify_checksums; + bool fill_cache; + Snapshot snapshot; + + struct __isset { + __isset() { __clear(); } + void __clear() { + verify_checksums = false; + fill_cache = false; + snapshot = false; + } + bool verify_checksums; + bool fill_cache; + bool snapshot; + } __isset; + + bool operator == (const ReadOptions & rhs) const + { + if (!(this->verify_checksums == rhs.verify_checksums)) + return false; + if (!(this->fill_cache == rhs.fill_cache)) + return false; + if (!(this->snapshot == rhs.snapshot)) + return false; + return true; + } + bool operator != (const ReadOptions &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ReadOptions & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class ReadOptions; +void swap(ReadOptions &a, ReadOptions &b); + +class DBHandle { + public: + + static const uint64_t _reflection_id = 8973827971994157004U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + DBHandle() : dbname("") { + } + + DBHandle(const DBHandle&) = default; + DBHandle& operator=(const DBHandle&) = default; + DBHandle(DBHandle&&) = default; + DBHandle& operator=(DBHandle&&) = default; + + void __clear() { + dbname = ""; + __isset.__clear(); + } + + virtual ~DBHandle() throw() {} + + Text dbname; + + struct __isset { + __isset() { __clear(); } + void __clear() { + dbname = false; + } + bool dbname; + } __isset; + + bool operator == (const DBHandle & rhs) const + { + if (!(this->dbname == rhs.dbname)) + return false; + return true; + } + bool operator != (const DBHandle &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DBHandle & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DBHandle; +void swap(DBHandle &a, DBHandle &b); + +class Iterator { + public: + + static const uint64_t _reflection_id = 11184146435197093740U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + Iterator() : iteratorid(0) { + } + + Iterator(const Iterator&) = default; + Iterator& operator=(const Iterator&) = default; + Iterator(Iterator&&) = default; + Iterator& operator=(Iterator&&) = default; + + void __clear() { + iteratorid = 0; + __isset.__clear(); + } + + virtual ~Iterator() throw() {} + + int64_t iteratorid; + + struct __isset { + __isset() { __clear(); } + void __clear() { + iteratorid = false; + } + bool iteratorid; + } __isset; + + bool operator == (const Iterator & rhs) const + { + if (!(this->iteratorid == rhs.iteratorid)) + return false; + return true; + } + bool operator != (const Iterator &rhs) const { + return !(*this == rhs); + } + + bool operator < (const Iterator & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class Iterator; +void swap(Iterator &a, Iterator &b); + +class kv { + public: + + static const uint64_t _reflection_id = 16082992224095104076U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + kv() { + } + + kv(const kv&) = default; + kv& operator=(const kv&) = default; + kv(kv&&) = default; + kv& operator=(kv&&) = default; + + void __clear() { + key.__clear(); + value.__clear(); + __isset.__clear(); + } + + virtual ~kv() throw() {} + + Slice key; + Slice value; + + struct __isset { + __isset() { __clear(); } + void __clear() { + key = false; + value = false; + } + bool key; + bool value; + } __isset; + + bool operator == (const kv & rhs) const + { + if (!(this->key == rhs.key)) + return false; + if (!(this->value == rhs.value)) + return false; + return true; + } + bool operator != (const kv &rhs) const { + return !(*this == rhs); + } + + bool operator < (const kv & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class kv; +void swap(kv &a, kv &b); + +class ResultItem { + public: + + static const uint64_t _reflection_id = 13211316281207238796U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + ResultItem() : status(static_cast(0)) { + } + + ResultItem(const ResultItem&) = default; + ResultItem& operator=(const ResultItem&) = default; + ResultItem(ResultItem&&) = default; + ResultItem& operator=(ResultItem&&) = default; + + void __clear() { + status = static_cast(0); + value.__clear(); + __isset.__clear(); + } + + virtual ~ResultItem() throw() {} + + Code status; + Slice value; + + struct __isset { + __isset() { __clear(); } + void __clear() { + status = false; + value = false; + } + bool status; + bool value; + } __isset; + + bool operator == (const ResultItem & rhs) const + { + if (!(this->status == rhs.status)) + return false; + if (!(this->value == rhs.value)) + return false; + return true; + } + bool operator != (const ResultItem &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ResultItem & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class ResultItem; +void swap(ResultItem &a, ResultItem &b); + +class ResultPair { + public: + + static const uint64_t _reflection_id = 14875242256166808460U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + ResultPair() : status(static_cast(0)) { + } + + ResultPair(const ResultPair&) = default; + ResultPair& operator=(const ResultPair&) = default; + ResultPair(ResultPair&&) = default; + ResultPair& operator=(ResultPair&&) = default; + + void __clear() { + status = static_cast(0); + keyvalue.__clear(); + __isset.__clear(); + } + + virtual ~ResultPair() throw() {} + + Code status; + kv keyvalue; + + struct __isset { + __isset() { __clear(); } + void __clear() { + status = false; + keyvalue = false; + } + bool status; + bool keyvalue; + } __isset; + + bool operator == (const ResultPair & rhs) const + { + if (!(this->status == rhs.status)) + return false; + if (!(this->keyvalue == rhs.keyvalue)) + return false; + return true; + } + bool operator != (const ResultPair &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ResultPair & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class ResultPair; +void swap(ResultPair &a, ResultPair &b); + +class ResultSnapshot { + public: + + static const uint64_t _reflection_id = 16627180600575569004U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + ResultSnapshot() : status(static_cast(0)) { + } + + ResultSnapshot(const ResultSnapshot&) = default; + ResultSnapshot& operator=(const ResultSnapshot&) = default; + ResultSnapshot(ResultSnapshot&&) = default; + ResultSnapshot& operator=(ResultSnapshot&&) = default; + + void __clear() { + status = static_cast(0); + snapshot.__clear(); + __isset.__clear(); + } + + virtual ~ResultSnapshot() throw() {} + + Code status; + Snapshot snapshot; + + struct __isset { + __isset() { __clear(); } + void __clear() { + status = false; + snapshot = false; + } + bool status; + bool snapshot; + } __isset; + + bool operator == (const ResultSnapshot & rhs) const + { + if (!(this->status == rhs.status)) + return false; + if (!(this->snapshot == rhs.snapshot)) + return false; + return true; + } + bool operator != (const ResultSnapshot &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ResultSnapshot & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class ResultSnapshot; +void swap(ResultSnapshot &a, ResultSnapshot &b); + +class ResultIterator { + public: + + static const uint64_t _reflection_id = 595886977232564460U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + ResultIterator() : status(static_cast(0)) { + } + + ResultIterator(const ResultIterator&) = default; + ResultIterator& operator=(const ResultIterator&) = default; + ResultIterator(ResultIterator&&) = default; + ResultIterator& operator=(ResultIterator&&) = default; + + void __clear() { + status = static_cast(0); + iterator.__clear(); + __isset.__clear(); + } + + virtual ~ResultIterator() throw() {} + + Code status; + Iterator iterator; + + struct __isset { + __isset() { __clear(); } + void __clear() { + status = false; + iterator = false; + } + bool status; + bool iterator; + } __isset; + + bool operator == (const ResultIterator & rhs) const + { + if (!(this->status == rhs.status)) + return false; + if (!(this->iterator == rhs.iterator)) + return false; + return true; + } + bool operator != (const ResultIterator &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ResultIterator & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class ResultIterator; +void swap(ResultIterator &a, ResultIterator &b); + +class LeveldbException : public apache::thrift::TException { + public: + + static const uint64_t _reflection_id = 2551220192341843436U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + LeveldbException() : message(""), errorCode(static_cast(0)) { + } + + LeveldbException(const LeveldbException&) = default; + LeveldbException& operator=(const LeveldbException&) = default; + LeveldbException(LeveldbException&&) = default; + LeveldbException& operator=(LeveldbException&&) = default; + + void __clear() { + message = ""; + errorCode = static_cast(0); + __isset.__clear(); + } + + virtual ~LeveldbException() throw() {} + + Text message; + Code errorCode; + + struct __isset { + __isset() { __clear(); } + void __clear() { + message = false; + errorCode = false; + } + bool message; + bool errorCode; + } __isset; + + bool operator == (const LeveldbException & rhs) const + { + if (!(this->message == rhs.message)) + return false; + if (!(this->errorCode == rhs.errorCode)) + return false; + return true; + } + bool operator != (const LeveldbException &rhs) const { + return !(*this == rhs); + } + + bool operator < (const LeveldbException & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + + virtual const char* what() const throw() { + return "LeveldbException"; + } + +}; + +class LeveldbException; +void swap(LeveldbException &a, LeveldbException &b); + +class IOError : public apache::thrift::TException { + public: + + static const uint64_t _reflection_id = 8460881927871070060U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + IOError() : message("") { + } + + IOError(const IOError&) = default; + IOError& operator=(const IOError&) = default; + IOError(IOError&&) = default; + IOError& operator=(IOError&&) = default; + + void __clear() { + message = ""; + __isset.__clear(); + } + + virtual ~IOError() throw() {} + + std::string message; + + struct __isset { + __isset() { __clear(); } + void __clear() { + message = false; + } + bool message; + } __isset; + + bool operator == (const IOError & rhs) const + { + if (!(this->message == rhs.message)) + return false; + return true; + } + bool operator != (const IOError &rhs) const { + return !(*this == rhs); + } + + bool operator < (const IOError & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + + virtual const char* what() const throw() { + return "IOError"; + } + +}; + +class IOError; +void swap(IOError &a, IOError &b); + +class TaoAssocGetResult { + public: + + static const uint64_t _reflection_id = 6301164048086986412U; + static void _reflection_register(::apache::thrift::reflection::Schema&); + TaoAssocGetResult() : id2(0), id1Type(0), id2Type(0), time(0), dataVersion(0), data("") { + } + + TaoAssocGetResult(const TaoAssocGetResult&) = default; + TaoAssocGetResult& operator=(const TaoAssocGetResult&) = default; + TaoAssocGetResult(TaoAssocGetResult&&) = default; + TaoAssocGetResult& operator=(TaoAssocGetResult&&) = default; + + void __clear() { + id2 = 0; + id1Type = 0; + id2Type = 0; + time = 0; + dataVersion = 0; + data = ""; + __isset.__clear(); + } + + virtual ~TaoAssocGetResult() throw() {} + + int64_t id2; + int64_t id1Type; + int64_t id2Type; + int64_t time; + int64_t dataVersion; + Text data; + + struct __isset { + __isset() { __clear(); } + void __clear() { + id2 = false; + id1Type = false; + id2Type = false; + time = false; + dataVersion = false; + data = false; + } + bool id2; + bool id1Type; + bool id2Type; + bool time; + bool dataVersion; + bool data; + } __isset; + + bool operator == (const TaoAssocGetResult & rhs) const + { + if (!(this->id2 == rhs.id2)) + return false; + if (!(this->id1Type == rhs.id1Type)) + return false; + if (!(this->id2Type == rhs.id2Type)) + return false; + if (!(this->time == rhs.time)) + return false; + if (!(this->dataVersion == rhs.dataVersion)) + return false; + if (!(this->data == rhs.data)) + return false; + return true; + } + bool operator != (const TaoAssocGetResult &rhs) const { + return !(*this == rhs); + } + + bool operator < (const TaoAssocGetResult & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class TaoAssocGetResult; +void swap(TaoAssocGetResult &a, TaoAssocGetResult &b); + +} // namespace + +#endif diff --git a/thrift/gen-cpp/reflection_types.h b/thrift/gen-cpp/reflection_types.h new file mode 100644 index 00000000..b2ce3492 --- /dev/null +++ b/thrift/gen-cpp/reflection_types.h @@ -0,0 +1,247 @@ +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated SignedSource<> + */ +#ifndef reflection_TYPES_H +#define reflection_TYPES_H + +#include +#include +#include +#include + + +#include +#include + +namespace apache { namespace thrift { namespace reflection { + +enum Type { + TYPE_VOID = 0, + TYPE_STRING = 1, + TYPE_BOOL = 2, + TYPE_BYTE = 3, + TYPE_I16 = 4, + TYPE_I32 = 5, + TYPE_I64 = 6, + TYPE_DOUBLE = 7, + TYPE_ENUM = 8, + TYPE_LIST = 9, + TYPE_SET = 10, + TYPE_MAP = 11, + TYPE_STRUCT = 12, + TYPE_SERVICE = 13, + TYPE_PROGRAM = 14 +}; + +extern const std::map _Type_VALUES_TO_NAMES; + +extern const std::map _Type_NAMES_TO_VALUES; + +class StructField { + public: + + StructField() : isRequired(0), type(0), name("") { + } + + StructField(const StructField&) = default; + StructField& operator=(const StructField&) = default; + StructField(StructField&&) = default; + StructField& operator=(StructField&&) = default; + + void __clear() { + isRequired = 0; + type = 0; + name = ""; + annotations.clear(); + __isset.__clear(); + } + + virtual ~StructField() throw() {} + + bool isRequired; + int64_t type; + std::string name; + boost::container::flat_map annotations; + + struct __isset { + __isset() { __clear(); } + void __clear() { + isRequired = false; + type = false; + name = false; + annotations = false; + } + bool isRequired; + bool type; + bool name; + bool annotations; + } __isset; + + bool operator == (const StructField & rhs) const + { + if (!(this->isRequired == rhs.isRequired)) + return false; + if (!(this->type == rhs.type)) + return false; + if (!(this->name == rhs.name)) + return false; + if (__isset.annotations != rhs.__isset.annotations) + return false; + else if (__isset.annotations && !(annotations == rhs.annotations)) + return false; + return true; + } + bool operator != (const StructField &rhs) const { + return !(*this == rhs); + } + + bool operator < (const StructField & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class StructField; +void swap(StructField &a, StructField &b); + +class DataType { + public: + + DataType() : name(""), mapKeyType(0), valueType(0) { + } + + DataType(const DataType&) = default; + DataType& operator=(const DataType&) = default; + DataType(DataType&&) = default; + DataType& operator=(DataType&&) = default; + + void __clear() { + name = ""; + fields.clear(); + mapKeyType = 0; + valueType = 0; + enumValues.clear(); + __isset.__clear(); + } + + virtual ~DataType() throw() {} + + std::string name; + boost::container::flat_map fields; + int64_t mapKeyType; + int64_t valueType; + boost::container::flat_map enumValues; + + struct __isset { + __isset() { __clear(); } + void __clear() { + name = false; + fields = false; + mapKeyType = false; + valueType = false; + enumValues = false; + } + bool name; + bool fields; + bool mapKeyType; + bool valueType; + bool enumValues; + } __isset; + + bool operator == (const DataType & rhs) const + { + if (!(this->name == rhs.name)) + return false; + if (__isset.fields != rhs.__isset.fields) + return false; + else if (__isset.fields && !(fields == rhs.fields)) + return false; + if (__isset.mapKeyType != rhs.__isset.mapKeyType) + return false; + else if (__isset.mapKeyType && !(mapKeyType == rhs.mapKeyType)) + return false; + if (__isset.valueType != rhs.__isset.valueType) + return false; + else if (__isset.valueType && !(valueType == rhs.valueType)) + return false; + if (__isset.enumValues != rhs.__isset.enumValues) + return false; + else if (__isset.enumValues && !(enumValues == rhs.enumValues)) + return false; + return true; + } + bool operator != (const DataType &rhs) const { + return !(*this == rhs); + } + + bool operator < (const DataType & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class DataType; +void swap(DataType &a, DataType &b); + +class Schema { + public: + + Schema() { + } + + Schema(const Schema&) = default; + Schema& operator=(const Schema&) = default; + Schema(Schema&&) = default; + Schema& operator=(Schema&&) = default; + + void __clear() { + dataTypes.clear(); + names.clear(); + __isset.__clear(); + } + + virtual ~Schema() throw() {} + + std::unordered_map dataTypes; + std::unordered_map names; + + struct __isset { + __isset() { __clear(); } + void __clear() { + dataTypes = false; + names = false; + } + bool dataTypes; + bool names; + } __isset; + + bool operator == (const Schema & rhs) const + { + if (!(this->dataTypes == rhs.dataTypes)) + return false; + if (!(this->names == rhs.names)) + return false; + return true; + } + bool operator != (const Schema &rhs) const { + return !(*this == rhs); + } + + bool operator < (const Schema & ) const; + + uint32_t read(apache::thrift::protocol::TProtocol* iprot); + uint32_t write(apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class Schema; +void swap(Schema &a, Schema &b); + +}}} // namespace + +#endif diff --git a/thrift/if/leveldb.thrift b/thrift/if/leveldb.thrift new file mode 100644 index 00000000..1768bb89 --- /dev/null +++ b/thrift/if/leveldb.thrift @@ -0,0 +1,384 @@ +#!/usr/local/bin/thrift --gen cpp + +namespace java Tleveldb +namespace cpp Tleveldb +namespace rb Tleveldb +namespace py Tleveldb +namespace perl Tleveldb + +// Types +typedef binary Text +typedef binary Bytes + +// A basic object needed for storing keys and values +struct Slice { + 1:Text data; + 2:i32 size +} + +// Different compression types supported +enum CompressionType { + kNoCompression = 0x0, + kSnappyCompression = 0x1 +} + +// Error codes +enum Code { + kOk = 0, + kNotFound = 1, + kCorruption = 2, + kNotSupported = 3, + kInvalidArgument = 4, + kIOError = 5, + kEnd = 6 +} + +// A range object +struct Range { + 1:Slice start; // Included in the range + 2:Slice limit // Not included in the range +} + +// Options to creating a database +struct DBOptions { + 1:bool create_if_missing; + 2:bool error_if_exists; + 3:i32 write_buffer_size; + 4:i32 max_open_files; + 5:i32 block_size; + 6:i32 block_restart_interval; + 7:CompressionType compression, + 8:i32 num_levels, + 9:i32 level0_file_num_compaction_trigger, + 10:i32 level0_slowdown_writes_trigger, + 11:i32 level0_stop_writes_trigger, + 12:i32 target_file_size_base, + 13:i32 target_file_size_multiplier, + 14:i32 max_bytes_for_level_base, + 15:i32 max_bytes_for_level_multiplier, + 16:i32 max_grandparent_overlap_factor, + 17:bool disableDataSync +} + +// Options for writing +struct WriteOptions { + 1:bool sync, + 2:bool disableWAL +} + +struct Snapshot { + 1:i64 snapshotid // server generated +} + +// Options for reading. If you do not have a +// snapshot, set snapshot.snapshotid = 0 +struct ReadOptions { + 1:bool verify_checksums; + 2:bool fill_cache, + 3:Snapshot snapshot +} + +// Represents a database object +struct DBHandle { + 1:Text dbname //name of the database +} + +struct Iterator { + 1:i64 iteratorid // server generated +} + +// flags for the iterator +enum IteratorType { + seekToFirst = 0, + seekToLast = 1, + seekToKey = 2 +} + +struct kv { + 1:Slice key; + 2:Slice value +} + +// Return a single value from the Get call +struct ResultItem { + 1:Code status; + 2:Slice value +} + +// Return a key,value from a Scan call +struct ResultPair { + 1:Code status; + 2:kv keyvalue +} + +// Snapshot result +struct ResultSnapshot { + 1:Code status; + 2:Snapshot snapshot +} + +// Iterator result +struct ResultIterator { + 1:Code status; + 2:Iterator iterator +} + +exception LeveldbException { + 1:Text message, + 2:Code errorCode +} + +// The Database service +service DB { + + // opens the database. The database name cannot have "/" + // in its name. + DBHandle Open(1:Text dbname, 2:DBOptions dboptions) + throws (1:LeveldbException se), + + // closes the database + Code Close(1:DBHandle dbhandle, 2:Text dbname), + + // puts a key in the database + Code Put(1:DBHandle dbhandle, 2:kv keyvalue, 3:WriteOptions options), + + // deletes a key from the database + Code Delete(1:DBHandle dbhandle, 2:Slice key, 3:WriteOptions options), + + // writes batch of keys into the database + Code Write(1:DBHandle dbhandle, 2:list batch, 3:WriteOptions options), + + // fetch a key from the DB. + // ResultItem.status == kNotFound means key is non existant + // ResultItem.status == kOk means key is found + ResultItem Get(1:DBHandle dbhandle, 2:Slice inputkey, + 3:ReadOptions options), + + // start iteration over a set of keys. If iteratorType.seekToFirst + // is set, then position the iterator at the first key in the source. + // If iteratorType.seekToLast is set, then position at the last key in the + // source. If iteratorType.seekToKey is set, then position at the first + // key in the source that is at or past target. + // If any two of iteratorType.seekToFirst & iteratorType.seekToLast + // and iteratorType.seekToKey are set, then error. + // If either iteratorType.seekToFirst or iteratorType.seekToLast is set, + // then target is not used. + ResultIterator NewIterator(1:DBHandle dbhandle, 2:ReadOptions options, + 3:IteratorType iteratorType, + 4:Slice target), + + // Release resources associated with an iterator allocated previously + // via a call to NewIterator. The call to this method may be skipped + // if the iterator had already traversed all the keys in the specified + // range. If the application wants to terminate a scan before processing + // all the resulting keys, then it is essential to invoke this method. + Code DeleteIterator(1:DBHandle dbhandle, 2:Iterator iterator), + + // Return the previous/next from this iteration + ResultPair GetNext(1:DBHandle dbhandle, 2:Iterator iterator), + ResultPair GetPrev(1:DBHandle dbhandle, 2:Iterator iterator), + + // Create snapshot. + ResultSnapshot GetSnapshot(1:DBHandle dbhandle), + + // Release snapshots + Code ReleaseSnapshot(1:DBHandle dbhandle, 2:Snapshot snapshot), + + // compact a range of keys + // begin.size == 0 to start at a range earlier than the first existing key + // end.size == 0 to end at a range later than the last existing key + Code CompactRange(1:DBHandle dbhandle, 2:Slice start, 3:Slice endhere), +} + +// ****************** FACEBOOK specific stuff ******************** + +// +// An IOError exception from an assoc operation +// +exception IOError { + 1:string message +} + +// +// Visibility state for assoc +// +enum AssocVisibility +{ + VISIBLE = 0, // live object, include in lookups and count + DELETED = 1, // exclude from lookup queries and count, ok to + // delete permanently from persistent store + UNUSED1 = 2, // not used + HIDDEN = 3, // exclude from lookup queries and count + UNUSED2 = 4, // not used + HARD_DELETE = 4 // deleted by calling expunge, will be swept + // as soon as possible +} + +/** + * Holds the assoc get result of a id2 + */ +struct TaoAssocGetResult { + /** id2 of assoc */ + 1:i64 id2, + + /** id1 type of assoc */ + 2:i64 id1Type, + + /** id2 type of assoc */ + 3:i64 id2Type, + + /** time stamp of the assoc */ + 4:i64 time, + + /** version of the data blob */ + 5:i64 dataVersion, + + /** serialized data of the asoc */ + 6:Text data, +} + +// +// Service +// +service AssocService { + + /** + * TAO Assoc Put operation. + * Note that currently the argument visibility has no effect. + * + * @if update_count is true, then return the updated count for this assoc + * @if update_count is false, then return 0 + * @return negative number if failure + */ + i64 taoAssocPut( + /** name of table */ + 1:Text tableName, + + /** type assoc */ + 2:i64 assocType, + + /** id1 of assoc */ + 3:i64 id1, + + /** id2 of assoc */ + 4:i64 id2, + + /** id1Type of assoc */ + 5:i64 id1Type, + + /** id2Type of assoc */ + 6:i64 id2Type, + + /** timestamp of assoc */ + 7:i64 timestamp, + + /** visibility */ + 8:AssocVisibility visibility, + + /** whether to keep the count or not */ + 9:bool update_count, + + /** version of the data blob */ + 10:i64 dataVersion, + + /** serialized data of assoc */ + 11:Text data, + + /** wormhole comment */ + 12:Text wormhole_comment + ) throws (1:IOError io) + + /** + * TAO Assoc Delete operation. + * + * @return the updated count for this assoc + */ + i64 taoAssocDelete( + /** name of table */ + 1:Text tableName, + + /** type assoc */ + 2:i64 assocType, + + /** id1 of assoc */ + 3:i64 id1, + + /** id2 of assoc */ + 4:i64 id2, + + /** visibility flag for this delete */ + 5:AssocVisibility visibility, + + /** whether to keep the count or not */ + 6:bool update_count, + + /** wormhole comment */ + 7:Text wormhole_comment + ) throws (1:IOError io) + + /** + * TAO Assoc RangeGet operation. + * Obtain assocs in bewteen start_time and end_time in reverse time order. + * The range check is inclusive: start_time >= time && time >= end_time. + * And yes, start_time >= end_time because this range scan is a backward + * scan in time, starting with most recent time and scanning backwards + * for the most recent n assocs. + */ + list taoAssocRangeGet( + /** name of table */ + 1:Text tableName, + + /** type of assoc */ + 2:i64 assocType, + + /** id1 of assoc */ + 3:i64 id1, + + /** maximum timestamp of assocs to retrieve */ + 4:i64 start_time, + + /** minimum timestamp of assocs to retrieve */ + 5:i64 end_time, + + /** number of assocs to skip from start */ + 6:i64 offset, + + /** max number of assocs (columns) returned */ + 7:i64 limit + ) throws (1:IOError io) + + /** + * TAO Assoc Get operation. + */ + list taoAssocGet( + /** name of table */ + 1:Text tableName, + + /** type of assoc */ + 2:i64 assocType, + + /** id1 of assoc */ + 3:i64 id1, + + /** list of id2 need to be fetch */ + 4:list id2s + ) throws (1:IOError io) + + /** + * TAO Assoc Count Get operation. + * Returns the number of assocs for given id1 and assoc type + */ + i64 taoAssocCount( + /** name of table */ + 1:Text tableName, + + /** type of assoc */ + 2:i64 assocType, + + /** id1 of assoc */ + 3:i64 id1, + + ) throws (1:IOError io) +} + + diff --git a/thrift/lib/cpp/ClientUtil.h b/thrift/lib/cpp/ClientUtil.h new file mode 100644 index 00000000..5772ce37 --- /dev/null +++ b/thrift/lib/cpp/ClientUtil.h @@ -0,0 +1,229 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_CLIENTUTIL_H_ +#define THRIFT_CLIENTUTIL_H_ 1 + +#include "thrift/lib/cpp/transport/TBufferTransports.h" +#include "thrift/lib/cpp/transport/TSocket.h" +#include "thrift/lib/cpp/protocol/TBinaryProtocol.h" + +namespace apache { namespace thrift { namespace util { + +/* + * Versions that accept a host and port + */ + +template +ClientT* createClient(const std::string& host, uint16_t port) { + boost::shared_ptr socket( + new transport::TSocket(host, port)); + // We could specialize this to not create a wrapper transport when + // TransportT is TTransport or TSocket. However, everyone should always + // use a TFramedTransport or TBufferedTransport wrapper for performance + // reasons. + boost::shared_ptr transport(new TransportT(socket)); + boost::shared_ptr protocol( new ProtocolT(transport)); + transport->open(); + + return new ClientT(protocol); +} + +template +boost::shared_ptr createClientPtr(const std::string& host, + uint16_t port) { + return boost::shared_ptr( + createClient(host, port)); +} + +template +ClientT* createClient(const std::string& host, + uint16_t port, + bool useFramed = true) { + if (useFramed) { + return createClient( + host, port); + } else { + return createClient( + host, port); + } +} + +template +ClientT* createClient(const std::string& host, + uint16_t port, + bool useFramed = true) { + return createClient >( + host, port, useFramed); +} + +template +boost::shared_ptr createClientPtr(const std::string& host, + uint16_t port, + bool useFramed = true) { + return boost::shared_ptr( + createClient(host, port, useFramed)); +} + +template +boost::shared_ptr createClientPtr(const std::string& host, + uint16_t port, + bool useFramed = true) { + return boost::shared_ptr( + createClient(host, port, useFramed)); +} + +/* + * Versions that accept TSocketAddress + */ + +template +ClientT* createClient(const transport::TSocketAddress* address) { + boost::shared_ptr socket( + new transport::TSocket(address)); + // We could specialize this to not create a wrapper transport when + // TransportT is TTransport or TSocket. However, everyone should always + // use a TFramedTransport or TBufferedTransport wrapper for performance + // reasons. + boost::shared_ptr transport(new TransportT(socket)); + boost::shared_ptr protocol( new ProtocolT(transport)); + transport->open(); + + return new ClientT(protocol); +} + +template +boost::shared_ptr createClientPtr( + const transport::TSocketAddress* address) { + return boost::shared_ptr( + createClient(address)); +} + +template +ClientT* createClient(const transport::TSocketAddress* address, + bool useFramed = true) { + if (useFramed) { + return createClient( + address); + } else { + return createClient( + address); + } +} + +template +ClientT* createClient(const transport::TSocketAddress* address, + bool useFramed = true) { + return createClient >( + address, useFramed); +} + +template +boost::shared_ptr createClientPtr( + const transport::TSocketAddress* address, + bool useFramed = true) { + return boost::shared_ptr( + createClient(address, useFramed)); +} + +template +boost::shared_ptr createClientPtr( + const transport::TSocketAddress* address, + bool useFramed = true) { + return boost::shared_ptr( + createClient(address, useFramed)); +} + +/* + * Versions that accept TSocketAddress and socket options + */ + +template +ClientT* createClient(const transport::TSocketAddress* address, + const transport::TSocket::Options& options) { + boost::shared_ptr socket( + new transport::TSocket(address)); + socket->setSocketOptions(options); + + // We could specialize this to not create a wrapper transport when + // TransportT is TTransport or TSocket. However, everyone should always + // use a TFramedTransport or TBufferedTransport wrapper for performance + // reasons. + boost::shared_ptr transport(new TransportT(socket)); + boost::shared_ptr protocol( new ProtocolT(transport)); + transport->open(); + + return new ClientT(protocol); +} + +template +boost::shared_ptr createClientPtr( + const transport::TSocketAddress* address, + const transport::TSocket::Options& options) { + + return boost::shared_ptr( + createClient(address), options); +} + +template +ClientT* createClient(const transport::TSocketAddress* address, + const transport::TSocket::Options& options, + bool useFramed = true) { + if (useFramed) { + return createClient( + address, options); + } else { + return createClient( + address, options); + } +} + +template +ClientT* createClient(const transport::TSocketAddress* address, + const transport::TSocket::Options& options, + bool useFramed = true + ) { + return createClient >( + address, options, useFramed); +} + +template +boost::shared_ptr createClientPtr( + const transport::TSocketAddress* address, + const transport::TSocket::Options& options, + bool useFramed = true) { + return boost::shared_ptr( + createClient(address, options, useFramed)); +} + +template +boost::shared_ptr createClientPtr( + const transport::TSocketAddress* address, + const transport::TSocket::Options& options, + bool useFramed = true) { + return boost::shared_ptr( + createClient(address, options, useFramed)); +} + + +}}} // apache::thrift::util + +#endif // THRIFT_CLIENTUTIL_H_ diff --git a/thrift/lib/cpp/EventHandlerBase.h b/thrift/lib/cpp/EventHandlerBase.h new file mode 100644 index 00000000..241940b8 --- /dev/null +++ b/thrift/lib/cpp/EventHandlerBase.h @@ -0,0 +1,322 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_EVENTHANDLERBASE_H_ +#define THRIFT_EVENTHANDLERBASE_H_ 1 + +#include +#include +#include +#include "thrift/lib/cpp/server/TConnectionContext.h" +#include + +namespace apache { namespace thrift { + +using server::TConnectionContext; + +/** + * Virtual interface class that can handle events from the processor. To + * use this you should subclass it and implement the methods that you care + * about. Your subclass can also store local data that you may care about, + * such as additional "arguments" to these methods (stored in the object + * instance's state). + */ +class TProcessorEventHandler { + public: + + virtual ~TProcessorEventHandler() {} + + /** + * Called before calling other callback methods. + * Expected to return some sort of context object. + * The return value is passed to all other callbacks + * for that function invocation. + */ + virtual void* getContext(const char* fn_name, + TConnectionContext* connectionContext) { + return NULL; + } + + /** + * Expected to free resources associated with a context. + */ + virtual void freeContext(void* ctx, const char* fn_name) { } + + /** + * Called before reading arguments. + */ + virtual void preRead(void* ctx, const char* fn_name) {} + + /** + * Called between reading arguments and calling the handler. + */ + virtual void postRead(void* ctx, const char* fn_name, uint32_t bytes) {} + + /** + * Called between calling the handler and writing the response. + */ + virtual void preWrite(void* ctx, const char* fn_name) {} + + /** + * Called after writing the response. + */ + virtual void postWrite(void* ctx, const char* fn_name, uint32_t bytes) {} + + /** + * Called when an async function call completes successfully. + */ + virtual void asyncComplete(void* ctx, const char* fn_name) {} + + /** + * Called if the handler throws an undeclared exception. + */ + virtual void handlerError(void* ctx, const char* fn_name) {} + + protected: + TProcessorEventHandler() {} +}; + +/** + * A helper class used by the generated code to free each context. + */ +class TProcessorContextFreer { + public: + TProcessorContextFreer(boost::shared_ptr handler, + void* context, const char* method) : + handler_(handler), context_(context), method_(method) {} + ~TProcessorContextFreer() { + if (handler_ != NULL) { + handler_->freeContext(context_, method_); + } + } + + void unregister() { handler_.reset(); } + + private: + boost::shared_ptr handler_; + void* context_; + const char* method_; +}; + +class ContextStack { + friend class EventHandlerBase; + + public: + ContextStack( + const std::vector>& handlers, + const char* method, + TConnectionContext* connectionContext) + : handlers_(handlers) + , method_(method) { + for (auto handler: handlers) { + ctxs.push_back(handler->getContext(method, connectionContext)); + } + } + + ~ContextStack() { + for (size_t i = 0; i < handlers_.size(); i++) { + handlers_[i]->freeContext(ctxs[i], method_); + } + } + + private: + std::vector ctxs; + std::vector> handlers_; + const char* method_; +}; + +class EventHandlerBase { + public: + EventHandlerBase() + : setEventHandlerPos_(-1) {} + + EventHandlerBase(const EventHandlerBase& original) + : handlers_(original.handlers_), + eventHandler_(original.eventHandler_), + setEventHandlerPos_(original.setEventHandlerPos_), + s_() {} + + void addEventHandler( + const boost::shared_ptr& handler) { + handlers_.push_back(handler); + } + + void clearEventHandlers() { + handlers_.clear(); + setEventHandlerPos_ = -1; + if (eventHandler_) { + setEventHandler(eventHandler_); + } + } + + boost::shared_ptr getEventHandler() { + return eventHandler_; + } + + void setEventHandler(boost::shared_ptr eventHandler) { + eventHandler_ = eventHandler; + if (setEventHandlerPos_ > 0) { + handlers_.erase(handlers_.begin() + setEventHandlerPos_); + } + setEventHandlerPos_ = handlers_.size(); + handlers_.push_back(eventHandler); + } + + /** + * These functions are only used in the client handler + * implementation. The server process functions maintain + * ContextStack on the stack and binds ctx in to the async calls. + * + * Clients are not thread safe, so using a member variable is okay. + * Client send_ and recv_ functions contain parameters based off of + * the function call, and adding a parameter there would change the + * function signature enough that other thrift users might break. + * + * The generated code should be the ONLY user of s_. All other functions + * should just use the ContextStack parameter. + */ + void generateClientContextStack(const char* fn_name, + TConnectionContext* connectionContext) { + auto s = getContextStack(fn_name, connectionContext); + s_ = std::move(s); + } + + void clearClientContextStack() { + s_.reset(); + } + + ContextStack* getClientContextStack() { + return s_.get(); + } + + protected: + std::unique_ptr getContextStack( + const char* fn_name, + TConnectionContext* connectionContext) { + std::unique_ptr ctx( + new ContextStack(handlers_, fn_name, connectionContext)); + return ctx; + } + + void preWrite(ContextStack* s, const char* fn_name) { + if (s) { + for (size_t i = 0; i < handlers_.size(); i++) { + handlers_[i]->preWrite(s->ctxs[i], fn_name); + } + } + } + + void postWrite(ContextStack* s, const char* fn_name, + uint32_t bytes) { + if (s) { + for (size_t i = 0; i < handlers_.size(); i++) { + handlers_[i]->postWrite(s->ctxs[i], fn_name, bytes); + } + } + } + + void preRead(ContextStack* s, const char* fn_name) { + if (s) { + for (size_t i = 0; i < handlers_.size(); i++) { + handlers_[i]->preRead(s->ctxs[i], fn_name); + } + } + } + + void postRead(ContextStack* s, const char* fn_name, + uint32_t bytes) { + if (s) { + for (size_t i = 0; i < handlers_.size(); i++) { + handlers_[i]->postRead(s->ctxs[i], fn_name, bytes); + } + } + } + + void handlerError(ContextStack* s, const char* fn_name) { + if (s) { + for (size_t i = 0; i < handlers_.size(); i++) { + handlers_[i]->handlerError(s->ctxs[i], fn_name); + } + } + } + + void asyncComplete(ContextStack* s, const char* fn_name) { + if (s) { + for (size_t i = 0; i < handlers_.size(); i++) { + handlers_[i]->asyncComplete(s->ctxs[i], fn_name); + } + } + } + + public: + std::vector> handlers_; + boost::shared_ptr eventHandler_; + + private: + int setEventHandlerPos_; + std::unique_ptr s_; + +}; + +class TProcessorEventHandlerFactory { + public: + virtual boost::shared_ptr getEventHandler() = 0; +}; + +/** + * Base class for all thrift processors. Used to automatically attach event + * handlers to processors at creation time. + */ +class TProcessorBase : public EventHandlerBase { + public: + TProcessorBase(); + + static void addProcessorEventHandlerFactory( + boost::shared_ptr factory); + + static void removeProcessorEventHandlerFactory( + boost::shared_ptr factory); + + private: + static std::vector> + registeredHandlerFactories_; +}; + +/** + * Base class for all thrift clients. Used to automatically attach event + * handlers to clients at creation time. + */ +class TClientBase : public EventHandlerBase { + public: + TClientBase(); + + static void addClientEventHandlerFactory( + boost::shared_ptr factory); + + static void removeClientEventHandlerFactory( + boost::shared_ptr factory); + + private: + static std::vector> + registeredHandlerFactories_; +}; + +}} // apache::thrift + +#endif // #ifndef THRIFT_EVENTHANDLERBASE_H_ diff --git a/thrift/lib/cpp/README b/thrift/lib/cpp/README new file mode 100644 index 00000000..576d0170 --- /dev/null +++ b/thrift/lib/cpp/README @@ -0,0 +1,67 @@ +Thrift C++ Software Library + +License +======= + +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. + +Using Thrift with C++ +===================== + +The Thrift C++ libraries are built using the GNU tools. Follow the instructions +in the top-level README, or run bootstrap.sh in this folder to generate the +Makefiles. + +In case you do not want to open another README file, do this: + ./bootstrap.sh + ./configure (--with-boost=/usr/local) + make + sudo make install + +Thrift is divided into two libraries. + +libthrift + The core Thrift library contains all the core Thrift code. It requires + boost shared pointers, pthreads, and librt. + +libthriftnb + This library contains the Thrift nonblocking server, which uses libevent. + To link this library you will also need to link libevent. + +Linking Against Thrift +====================== + +After you build and install Thrift the libraries are installed to +/usr/local/lib by default. Make sure this is in your LDPATH. + +On Linux, the best way to do this is to ensure that /usr/local/lib is in +your /etc/ld.so.conf and then run /sbin/ldconfig. + +Depending upon whether you are linking dynamically or statically and how +your build environment it set up, you may need to include additional +libraries when linking against thrift, such as librt and/or libpthread. If +you are using libthriftnb you will also need libevent. + +Dependencies +============ + +boost shared pointers +http://www.boost.org/libs/smart_ptr/smart_ptr.htm + +libevent (for libthriftnb only) +http://monkey.org/~provos/libevent/ diff --git a/thrift/lib/cpp/Reflection.h b/thrift/lib/cpp/Reflection.h new file mode 100644 index 00000000..bbe04095 --- /dev/null +++ b/thrift/lib/cpp/Reflection.h @@ -0,0 +1,40 @@ +/** + * Copyright 2012 Facebook + * @author Tudor Bosman (tudorb@fb.com) + */ + +#ifndef THRIFT_LIB_CPP_REFLECTION_H_ +#define THRIFT_LIB_CPP_REFLECTION_H_ + +#include +#include + +#include "reflection_types.h" + +namespace apache { +namespace thrift { +namespace reflection { + +namespace detail { +const size_t kTypeBits = 5; +const uint64_t kTypeMask = (1ULL << kTypeBits) - 1; +} // namespace detail + +inline int64_t makeTypeId(Type type, uint64_t hash) { + return static_cast((hash & ~detail::kTypeMask) | type); +} + +inline Type getType(int64_t typeId) { + return static_cast(typeId & detail::kTypeMask); +} + +inline bool isBaseType(Type type) { + return type <= TYPE_DOUBLE; +} + +} // namespace reflection +} // namespace thrift +} // namespace apache + +#endif /* THRIFT_LIB_CPP_REFLECTION_H_ */ + diff --git a/thrift/lib/cpp/TApplicationException.h b/thrift/lib/cpp/TApplicationException.h new file mode 100644 index 00000000..8350471e --- /dev/null +++ b/thrift/lib/cpp/TApplicationException.h @@ -0,0 +1,108 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TAPPLICATIONEXCEPTION_H_ +#define _THRIFT_TAPPLICATIONEXCEPTION_H_ 1 + +#include "thrift/lib/cpp/Thrift.h" + + +namespace apache { namespace thrift { + +namespace protocol { + class TProtocol; +} + +/** + * This class is thrown when some high-level communication errors with + * the remote peer occur, and also when a server throws an unexpected + * exception from a handler method. Because of the latter case, this + * class can be serialized. + */ +class TApplicationException : public TException { + public: + + /** + * Error codes for the various types of exceptions. + */ + enum TApplicationExceptionType + { UNKNOWN = 0 + , UNKNOWN_METHOD = 1 + , INVALID_MESSAGE_TYPE = 2 + , WRONG_METHOD_NAME = 3 + , BAD_SEQUENCE_ID = 4 + , MISSING_RESULT = 5 + , INVALID_TRANSFORM = 6 + , INVALID_PROTOCOL = 7 + , UNSUPPORTED_CLIENT_TYPE = 8 + }; + + + TApplicationException() : + type_(UNKNOWN) {} + + TApplicationException(TApplicationExceptionType type) : + type_(type) {} + + TApplicationException(const std::string& message) : + message_(message), + type_(UNKNOWN) {} + + TApplicationException(TApplicationExceptionType type, + const std::string& message) : + message_(message), + type_(type) {} + + virtual ~TApplicationException() throw() {} + + /** + * Returns an error code that provides information about the type of error + * that has occurred. + * + * @return Error code + */ + TApplicationExceptionType getType() { + return type_; + } + + virtual const char* what() const throw() { + if (message_.empty()) { + switch (type_) { + case UNKNOWN : return "TApplicationException: Unknown application exception"; + case UNKNOWN_METHOD : return "TApplicationException: Unknown method"; + case INVALID_MESSAGE_TYPE : return "TApplicationException: Invalid message type"; + case WRONG_METHOD_NAME : return "TApplicationException: Wrong method name"; + case BAD_SEQUENCE_ID : return "TApplicationException: Bad sequence identifier"; + case MISSING_RESULT : return "TApplicationException: Missing result"; + case INVALID_TRANSFORM : + return "TApplicationException: Invalid transform"; + case INVALID_PROTOCOL : + return "TApplicationException: Invalid protocol"; + case UNSUPPORTED_CLIENT_TYPE: + return "TApplicationException: Unsupported client type"; + default : return "TApplicationException: (Invalid exception type)"; + }; + } else { + return message_.c_str(); + } + } + + uint32_t read(protocol::TProtocol* iprot); + uint32_t write(protocol::TProtocol* oprot) const; + + protected: + std::string message_; + + /** + * Error code + */ + TApplicationExceptionType type_; + +}; + +}} // apache::thrift + +#endif // #ifndef _THRIFT_TAPPLICATIONEXCEPTION_H_ diff --git a/thrift/lib/cpp/TDispatchProcessor.h b/thrift/lib/cpp/TDispatchProcessor.h new file mode 100644 index 00000000..22c54b25 --- /dev/null +++ b/thrift/lib/cpp/TDispatchProcessor.h @@ -0,0 +1,145 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef _THRIFT_TDISPATCHPROCESSOR_H_ +#define _THRIFT_TDISPATCHPROCESSOR_H_ 1 + +#include "thrift/lib/cpp/TProcessor.h" + +namespace apache { namespace thrift { + +using server::TConnectionContext; + +/** + * TDispatchProcessor is a helper class to parse the message header then call + * another function to dispatch based on the function name. + * + * Subclasses must implement dispatchCall() to dispatch on the function name. + */ +template +class TDispatchProcessorT : public TProcessor { + public: + virtual bool process(boost::shared_ptr in, + boost::shared_ptr out, + TConnectionContext* connectionContext) { + protocol::TProtocol* inRaw = in.get(); + protocol::TProtocol* outRaw = out.get(); + + // Try to dynamic cast to the template protocol type + Protocol_* specificIn = dynamic_cast(inRaw); + Protocol_* specificOut = dynamic_cast(outRaw); + if (specificIn && specificOut) { + return processFast(specificIn, specificOut, connectionContext); + } + + // Log the fact that we have to use the slow path + T_GENERIC_PROTOCOL(this, inRaw, specificIn); + T_GENERIC_PROTOCOL(this, outRaw, specificOut); + + std::string fname; + protocol::TMessageType mtype; + int32_t seqid; + inRaw->readMessageBegin(fname, mtype, seqid); + + // If this doesn't look like a valid call, log an error and return false so + // that the server will close the connection. + // + // (The old generated processor code used to try to skip a T_STRUCT and + // continue. However, that seems unsafe.) + if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY) { + GlobalOutput.printf("received invalid message type %d from client", + mtype); + return false; + } + + return this->dispatchCall(inRaw, outRaw, fname, seqid, connectionContext); + } + + protected: + bool processFast(Protocol_* in, Protocol_* out, + TConnectionContext* connectionContext) { + std::string fname; + protocol::TMessageType mtype; + int32_t seqid; + in->readMessageBegin(fname, mtype, seqid); + + if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY) { + GlobalOutput.printf("received invalid message type %d from client", + mtype); + return false; + } + + return this->dispatchCallTemplated(in, out, fname, + seqid, connectionContext); + } + + /** + * dispatchCall() methods must be implemented by subclasses + */ + virtual bool dispatchCall(apache::thrift::protocol::TProtocol* in, + apache::thrift::protocol::TProtocol* out, + const std::string& fname, int32_t seqid, + TConnectionContext* connectionContext) = 0; + + virtual bool dispatchCallTemplated(Protocol_* in, Protocol_* out, + const std::string& fname, int32_t seqid, + TConnectionContext* connectionContext) = 0; +}; + +/** + * Non-templatized version of TDispatchProcessor, that doesn't bother trying to + * perform a dynamic_cast. + */ +class TDispatchProcessor : public TProcessor { + public: + virtual bool process(boost::shared_ptr in, + boost::shared_ptr out, + TConnectionContext* connectionContext) { + std::string fname; + protocol::TMessageType mtype; + int32_t seqid; + in->readMessageBegin(fname, mtype, seqid); + + if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY) { + GlobalOutput.printf("received invalid message type %d from client", + mtype); + return false; + } + + return dispatchCall(in.get(), out.get(), fname, seqid, connectionContext); + } + + protected: + virtual bool dispatchCall(apache::thrift::protocol::TProtocol* in, + apache::thrift::protocol::TProtocol* out, + const std::string& fname, int32_t seqid, + TConnectionContext* connectionContext) = 0; +}; + +// Specialize TDispatchProcessorT for TProtocol and TDummyProtocol just to use +// the generic TDispatchProcessor. +template <> +class TDispatchProcessorT : + public TDispatchProcessor {}; +template <> +class TDispatchProcessorT : + public TDispatchProcessor {}; + +}} // apache::thrift + +#endif // _THRIFT_TDISPATCHPROCESSOR_H_ diff --git a/thrift/lib/cpp/TLogging.h b/thrift/lib/cpp/TLogging.h new file mode 100644 index 00000000..3f591cbb --- /dev/null +++ b/thrift/lib/cpp/TLogging.h @@ -0,0 +1,193 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_TLOGGING_H +#define THRIFT_TLOGGING_H 1 + +#include "thrift/lib/cpp/thrift_config.h" +#include "thrift/lib/cpp/concurrency/Util.h" + +#include + +/** + * Contains utility macros for debugging and logging. + * + */ + +#ifdef THRIFT_HAVE_CLOCK_GETTIME +#include +#endif +#include + +#ifdef THRIFT_HAVE_STDINT_H +#include +#endif + +/** + * T_GLOBAL_DEBUGGING_LEVEL = 0: all debugging turned off, debug macros undefined + * T_GLOBAL_DEBUGGING_LEVEL = 1: all debugging turned on + */ +#ifndef T_GLOBAL_DEBUGGING_LEVEL +#define T_GLOBAL_DEBUGGING_LEVEL 0 +#endif + +/** + * T_GLOBAL_LOGGING_LEVEL = 0: all logging turned off, logging macros undefined + * T_GLOBAL_LOGGING_LEVEL = 1: all logging turned on + */ +#define T_GLOBAL_LOGGING_LEVEL 1 + +/** + * Standard wrapper around fprintf what will prefix the file name and line + * number to the line. Uses T_GLOBAL_DEBUGGING_LEVEL to control whether it is + * turned on or off. + * + * @param format_string + */ +#define T_DEBUG(format_string,...) \ + T_DEBUG_L(0, format_string, ##__VA_ARGS__) + +#define COMPUTE_TIME \ + int64_t nowMs = apache::thrift::concurrency::Util::currentTime(); \ + time_t nowSec = (time_t) (nowMs / 1000); \ + nowMs -= nowSec * 1000; \ + int ms = (int)nowMs; \ + char dbgtime[26]; \ + ctime_r(&nowSec, dbgtime); \ + dbgtime[24] = '\0'; + +/** + * analogous to T_DEBUG but also prints the time + * + * @param string format_string input: printf style format string + */ +#define T_DEBUG_T(format_string,...) \ + do { \ + if (T_GLOBAL_DEBUGGING_LEVEL > 0) { \ + COMPUTE_TIME \ + fprintf(stderr, "[%s,%d] [%s, %d ms] " format_string " \n", \ + __FILE__, __LINE__, dbgtime, ms, \ + ##__VA_ARGS__); \ + } \ + } while(0) + + +/** + * analogous to T_DEBUG but uses input level to determine whether or not the string + * should be logged. + * + * @param int level: specified debug level + * @param string format_string input: format string + */ +#define T_DEBUG_L(level, format_string, ...) \ + do { \ + if (T_GLOBAL_DEBUGGING_LEVEL > (level)) { \ + COMPUTE_TIME \ + fprintf(stderr, "[%s,%d] [%s, %d ms] " format_string " \n", \ + __FILE__, __LINE__, dbgtime, ms, ##__VA_ARGS__); \ + } \ + } while (0) + + +/** + * Explicit error logging. Prints time, file name and line number + * + * @param string format_string input: printf style format string + */ +#define T_ERROR(format_string,...) \ + { \ + COMPUTE_TIME \ + fprintf(stderr,"[%s,%d] [%s, %d ms] ERROR: " format_string " \n", \ + __FILE__, __LINE__,dbgtime, ms, \ + ##__VA_ARGS__); \ + } + + +/** + * Analogous to T_ERROR, additionally aborting the process. + * WARNING: macro calls abort(), ending program execution + * + * @param string format_string input: printf style format string + */ +#define T_ERROR_ABORT(format_string,...) \ + { \ + COMPUTE_TIME \ + fprintf(stderr,"[%s,%d] [%s, %d ms] ERROR: Going to abort " \ + format_string " \n", \ + __FILE__, __LINE__,dbgtime, ms, \ + ##__VA_ARGS__); \ + exit(1); \ + } + + +/** + * Log input message + * + * @param string format_string input: printf style format string + */ +#if T_GLOBAL_LOGGING_LEVEL > 0 + #define T_LOG_OPER(format_string,...) \ + { \ + if (T_GLOBAL_LOGGING_LEVEL > 0) { \ + COMPUTE_TIME \ + fprintf(stderr,"[%s, %d ms] " format_string " \n", \ + dbgtime, ms, ##__VA_ARGS__); \ + } \ + } +#else + #define T_LOG_OPER(format_string,...) +#endif + + +/** + * T_GLOBAL_DEBUG_VIRTUAL = 0 or unset: normal operation, + * virtual call debug messages disabled + * T_GLOBAL_DEBUG_VIRTUAL = 1: log a debug messages whenever an + * avoidable virtual call is made + * T_GLOBAL_DEBUG_VIRTUAL = 2: record detailed info that can be + * printed by calling + * apache::thrift::profile_print_info() + */ +#if T_GLOBAL_DEBUG_VIRTUAL > 1 + #define T_VIRTUAL_CALL() \ + ::apache::thrift::profile_virtual_call(typeid(*this)) + #define T_GENERIC_PROTOCOL(template_class, generic_prot, specific_prot) \ + do { \ + if (!(specific_prot)) { \ + ::apache::thrift::profile_generic_protocol( \ + typeid(*template_class), typeid(*generic_prot)); \ + } \ + } while (0) +#elif T_GLOBAL_DEBUG_VIRTUAL == 1 + #define T_VIRTUAL_CALL() \ + fprintf(stderr,"[%s,%d] virtual call\n", __FILE__, __LINE__) + #define T_GENERIC_PROTOCOL(template_class, generic_prot, specific_prot) \ + do { \ + if (!(specific_prot)) { \ + fprintf(stderr, \ + "[%s,%d] failed to cast to specific protocol type\n", \ + __FILE__, __LINE__); \ + } \ + } while (0) +#else + #define T_VIRTUAL_CALL() + #define T_GENERIC_PROTOCOL(template_class, generic_prot, specific_prot) +#endif + +#endif // #ifndef THRIFT_TLOGGING_H diff --git a/thrift/lib/cpp/TProcessor.h b/thrift/lib/cpp/TProcessor.h new file mode 100644 index 00000000..f54cbea6 --- /dev/null +++ b/thrift/lib/cpp/TProcessor.h @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_TPROCESSOR_H_ +#define THRIFT_TPROCESSOR_H_ 1 + +#include +#include +#include "thrift/lib/cpp/EventHandlerBase.h" +#include "thrift/lib/cpp/server/TConnectionContext.h" +#include "thrift/lib/cpp/protocol/TProtocol.h" +#include + +namespace apache { namespace thrift { + +/** + * A processor is a generic object that acts upon two streams of data, one + * an input and the other an output. The definition of this object is loose, + * though the typical case is for some sort of server that either generates + * responses to an input stream or forwards data from one pipe onto another. + * + */ +class TProcessor : public TProcessorBase { + public: + virtual ~TProcessor() {} + + virtual bool process(boost::shared_ptr in, + boost::shared_ptr out, + TConnectionContext* connectionContext) = 0; + + bool process(boost::shared_ptr io, + TConnectionContext* connectionContext) { + return process(io, io, connectionContext); + } + + protected: + TProcessor() {} +}; + +class TProcessorFactory { + public: + virtual ~TProcessorFactory() {} + + /** + * Get the TProcessor to use for a particular connection. + * + * This method is always invoked in the same thread that the connection was + * accepted on. This generally means that this call does not need to be + * thread safe, as it will always be invoked from a single thread. + */ + virtual boost::shared_ptr getProcessor( + server::TConnectionContext* ctx) = 0; +}; + +class TSingletonProcessorFactory : public TProcessorFactory { + public: + explicit TSingletonProcessorFactory( + const boost::shared_ptr& processor) : + processor_(processor) {} + + boost::shared_ptr getProcessor(server::TConnectionContext*) { + return processor_; + } + + boost::shared_ptr getProcessor() { + return processor_; + } + + private: + boost::shared_ptr processor_; +}; + +/** + * This is a helper class to allow boost::shared_ptr to be used with handler + * pointers returned by the generated handler factories. + * + * The handler factory classes generated by the thrift compiler return raw + * pointers, and factory->releaseHandler() must be called when the handler is + * no longer needed. + * + * A ReleaseHandler object can be instantiated and passed as the second + * parameter to a shared_ptr, so that factory->releaseHandler() will be called + * when the object is no longer needed, instead of deleting the pointer. + */ +template +class ReleaseHandler { + public: + explicit ReleaseHandler( + const boost::shared_ptr& handlerFactory) : + handlerFactory_(handlerFactory) {} + + void operator()(typename HandlerFactory_::Handler* handler) { + if (handler) { + handlerFactory_->releaseHandler(handler); + } + } + + private: + boost::shared_ptr handlerFactory_; +}; + +}} // apache::thrift + +#endif // #ifndef THRIFT_TPROCESSOR_H_ diff --git a/thrift/lib/cpp/TReflectionLocal.h b/thrift/lib/cpp/TReflectionLocal.h new file mode 100644 index 00000000..d621f5c9 --- /dev/null +++ b/thrift/lib/cpp/TReflectionLocal.h @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TREFLECTIONLOCAL_H_ +#define _THRIFT_TREFLECTIONLOCAL_H_ 1 + +#include +#include +#include "thrift/lib/cpp/protocol/TProtocol.h" + +/** + * Local Reflection is a blanket term referring to the the structure + * and generation of this particular representation of Thrift types. + * (It is called local because it cannot be serialized by Thrift). + * + */ + +namespace apache { namespace thrift { namespace reflection { namespace local { + +using apache::thrift::protocol::TType; + +// We include this many bytes of the structure's fingerprint when serializing +// a top-level structure. Long enough to make collisions unlikely, short +// enough to not significantly affect the amount of memory used. +const int FP_PREFIX_LEN = 4; + +struct FieldMeta { + int16_t tag; + bool is_optional; +}; + +struct TypeSpec { + TType ttype; + uint8_t fp_prefix[FP_PREFIX_LEN]; + + // Use an anonymous union here so we can fit two TypeSpecs in one cache line. + union { + struct { + // Use parallel arrays here for denser packing (of the arrays). + FieldMeta* metas; + TypeSpec** specs; + } tstruct; + struct { + TypeSpec *subtype1; + TypeSpec *subtype2; + } tcontainer; + }; + + // Static initialization of unions isn't really possible, + // so take the plunge and use constructors. + // Hopefully they'll be evaluated at compile time. + + TypeSpec(TType ttype) : ttype(ttype) { + std::memset(fp_prefix, 0, FP_PREFIX_LEN); + } + + TypeSpec(TType ttype, + const uint8_t* fingerprint, + FieldMeta* metas, + TypeSpec** specs) : + ttype(ttype) + { + std::memcpy(fp_prefix, fingerprint, FP_PREFIX_LEN); + tstruct.metas = metas; + tstruct.specs = specs; + } + + TypeSpec(TType ttype, TypeSpec* subtype1, TypeSpec* subtype2) : + ttype(ttype) + { + std::memset(fp_prefix, 0, FP_PREFIX_LEN); + tcontainer.subtype1 = subtype1; + tcontainer.subtype2 = subtype2; + } + +}; + +}}}} // apache::thrift::reflection::local + +#endif // #ifndef _THRIFT_TREFLECTIONLOCAL_H_ diff --git a/thrift/lib/cpp/Thrift.h b/thrift/lib/cpp/Thrift.h new file mode 100644 index 00000000..b3adaacf --- /dev/null +++ b/thrift/lib/cpp/Thrift.h @@ -0,0 +1,283 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_THRIFT_H_ +#define THRIFT_THRIFT_H_ + +#include "thrift/lib/cpp/thrift_config.h" +#include +#include + +#include +#include +#ifdef THRIFT_HAVE_INTTYPES_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include "thrift/lib/cpp/TLogging.h" + +namespace apache { namespace thrift { + +struct ltstr { + bool operator()(const char* s1, const char* s2) const { + return strcmp(s1, s2) < 0; + } +}; + +/** + * Helper template class for enum<->string conversion. + */ +template +struct TEnumTraits { + /** + * Finds the name of a given enum value, returning it or NULL on failure. + * Specialized implementations will be emitted as part of enum codegen. + * + * Example specialization: + * template<> + * const char* TEnumTraits::findName(MyEnum value) { + * return findName(_MyEnum_VALUES_TO_NAMES, value); + * } + * Note the use of helper function 'findName(...)', below. + */ + static const char* findName(T value); + /** + * Attempts to find a value for a given name. + * Specialized implementations will be emitted as part of enum codegen. + * + * Example implementation: + * template<> + * bool TEnumTraits::findValue(const char* name, + * MyEnum* outValue) { + * return findValue(_MyEnum_NAMES_TO_VALUES, name, outValue); + * } + * Note the use of helper function 'findValue(...)', below. + */ + static bool findValue(const char* name, T* outValue); + + /** + * Return the minimum value. + */ + static constexpr T min(); + + /** + * Return the maximum value. + */ + static constexpr T max(); + private: + /** + * Helper method used by codegen implementation of findName, Supports + * use with strict and non-strict enums by way of template parameter + * 'ValueType'. + */ + template + static const char* findName(const std::map& map, + T value) { + auto found = map.find(value); + if (found == map.end()) { + return NULL; + } else { + return found->second; + } + } + + /** + * Helper method used by codegen implementation of findValue, Supports + * use with strict and non-strict enums by way of template parameter + * 'ValueType'. + */ + template + static bool findValue(const std::map& map, + const char* name, T* out) { + auto found = map.find(name); + if (found == map.end()) { + return false; + } else { + *out = static_cast(found->second); + return true; + } + } +}; + +template +class TEnumIterator : public std::map::iterator { + public: + TEnumIterator(int n, + T* enums, + const char** names) : + ii_(0), n_(n), enums_(enums), names_(names) { + } + + int operator ++() { + return ++ii_; + } + + bool operator !=(const TEnumIterator& end) { + assert(end.n_ == -1); + return (ii_ != n_); + } + + std::pair operator*() const { + return std::make_pair(enums_[ii_], names_[ii_]); + } + + private: + int ii_; + const int n_; + T* enums_; + const char** names_; +}; + +template +class TEnumInverseIterator : public std::map::iterator { + public: + TEnumInverseIterator(int n, + T* enums, + const char** names) : + ii_(0), n_(n), enums_(enums), names_(names) { + } + + int operator ++() { + return ++ii_; + } + + bool operator !=(const TEnumInverseIterator& end) { + assert(end.n_ == -1); + return (ii_ != n_); + } + + std::pair operator*() const { + return std::make_pair(names_[ii_], enums_[ii_]); + } + + private: + int ii_; + const int n_; + T* enums_; + const char** names_; +}; + +class TOutput { + public: + TOutput() : f_(&errorTimeWrapper) {} + + inline void setOutputFunction(void (*function)(const char *)){ + f_ = function; + } + + inline void operator()(const char *message){ + f_(message); + } + + // It is important to have a const char* overload here instead of + // just the string version, otherwise errno could be corrupted + // if there is some problem allocating memory when constructing + // the string. + void perror(const char *message, int errno_copy); + inline void perror(const std::string &message, int errno_copy) { + perror(message.c_str(), errno_copy); + } + + void printf(const char *message, ...); + + inline static void errorTimeWrapper(const char* msg) { + time_t now; + char dbgtime[26]; + time(&now); + ctime_r(&now, dbgtime); + dbgtime[24] = 0; + fprintf(stderr, "Thrift: %s %s\n", dbgtime, msg); + } + + /** Just like strerror_r but returns a C++ string object. */ + static std::string strerror_s(int errno_copy); + + private: + void (*f_)(const char *); +}; + +extern TOutput GlobalOutput; + +/** + * Base class for all Thrift exceptions. + * Should never be instantiated, only caught. + */ +class TException : public std::exception { +public: + TException() {} + TException(TException&&) {} + TException(const TException&) {} + TException& operator=(const TException&) { return *this; } + TException& operator=(TException&&) { return *this; } +}; + +/** + * Base class for exceptions from the Thrift library, and occasionally + * from the generated code. This class should not be thrown by user code. + * Instances of this class are not meant to be serialized. + */ +class TLibraryException : public TException { + public: + TLibraryException() {} + + explicit TLibraryException(const std::string& message) : + message_(message) {} + + TLibraryException(const char* message, int errnoValue); + + virtual ~TLibraryException() throw() {} + + virtual const char* what() const throw() { + if (message_.empty()) { + return "Default TLibraryException."; + } else { + return message_.c_str(); + } + } + + protected: + std::string message_; + +}; + +#if T_GLOBAL_DEBUG_VIRTUAL > 1 +void profile_virtual_call(const std::type_info& info); +void profile_generic_protocol(const std::type_info& template_type, + const std::type_info& prot_type); +void profile_print_info(FILE *f); +void profile_print_info(); +void profile_write_pprof(FILE* gen_calls_f, FILE* virtual_calls_f); +#endif + +template +inline void reallyClear(ThriftContainer& container) { + ThriftContainer emptyContainer; + swap(container, emptyContainer); +} + +}} // apache::thrift + +#endif // #ifndef THRIFT_THRIFT_H_ diff --git a/thrift/lib/cpp/async/SimpleCallback.h b/thrift/lib/cpp/async/SimpleCallback.h new file mode 100644 index 00000000..00551e24 --- /dev/null +++ b/thrift/lib/cpp/async/SimpleCallback.h @@ -0,0 +1,98 @@ +#ifndef _THRIFT_ASYNC_SIMPLECALLBACK_H_ +#define _THRIFT_ASYNC_SIMPLECALLBACK_H_ 1 + +#include "thrift/lib/cpp/Thrift.h" +namespace apache { namespace thrift { + +/** + * A template class for forming simple method callbacks with either an empty + * argument list or one argument of known type. + * + * For more efficiency where tr1::function is overkill. + */ + +template ///< type of return value +class SimpleCallback { + typedef R (C::*cfptr_t)(A); ///< pointer-to-member-function type + cfptr_t fptr_; ///< the embedded function pointer + C* obj_; ///< object whose function we're wrapping + public: + /** + * Constructor for empty callback object. + */ + SimpleCallback() : + fptr_(NULL), obj_(NULL) {} + /** + * Construct callback wrapper for member function. + * + * @param fptr pointer-to-member-function + * @param "this" for object associated with callback + */ + SimpleCallback(cfptr_t fptr, const C* obj) : + fptr_(fptr), obj_(const_cast(obj)) + {} + + /** + * Make a call to the member function we've wrapped. + * + * @param i argument for the wrapped member function + * @return value from that function + */ + R operator()(A i) const { + (obj_->*fptr_)(i); + } + + operator bool() const { + return obj_ != NULL && fptr_ != NULL; + } + + ~SimpleCallback() {} +}; + +/** + * Specialization of SimpleCallback for empty argument list. + */ +template ///< type of return value +class SimpleCallback { + typedef R (C::*cfptr_t)(); ///< pointer-to-member-function type + cfptr_t fptr_; ///< the embedded function pointer + C* obj_; ///< object whose function we're wrapping + public: + /** + * Constructor for empty callback object. + */ + SimpleCallback() : + fptr_(NULL), obj_(NULL) {} + + /** + * Construct callback wrapper for member function. + * + * @param fptr pointer-to-member-function + * @param obj "this" for object associated with callback + */ + SimpleCallback(cfptr_t fptr, const C* obj) : + fptr_(fptr), obj_(const_cast(obj)) + {} + + /** + * Make a call to the member function we've wrapped. + * + * @return value from that function + */ + R operator()() const { + (obj_->*fptr_)(); + } + + operator bool() const { + return obj_ != NULL && fptr_ != NULL; + } + + ~SimpleCallback() {} +}; + +}} // apache::thrift + +#endif /* !_THRIFT_ASYNC_SIMPLECALLBACK_H_ */ diff --git a/thrift/lib/cpp/async/TAsyncChannel.h b/thrift/lib/cpp/async/TAsyncChannel.h new file mode 100644 index 00000000..6ac10c6f --- /dev/null +++ b/thrift/lib/cpp/async/TAsyncChannel.h @@ -0,0 +1,119 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef THRIFT_ASYNC_TASYNCCHANNEL_H_ +#define THRIFT_ASYNC_TASYNCCHANNEL_H_ 1 + +#include +#include "thrift/lib/cpp/Thrift.h" +#include "thrift/lib/cpp/transport/TTransportUtils.h" + +namespace apache { namespace thrift { namespace async { + +class TAsyncTransport; + +/** + * TAsyncChannel defines an asynchronous API for message-based I/O. + */ +class TAsyncChannel { + public: + typedef std::tr1::function VoidCallback; + + virtual ~TAsyncChannel() {} + + // is the channel readable (possibly closed by the remote site)? + virtual bool readable() const = 0; + // is the channel in a good state? + virtual bool good() const = 0; + virtual bool error() const = 0; + virtual bool timedOut() const = 0; + + /** + * Send a message over the channel. + * + * @return call "cob" on success, "errorCob" on fail. Caller must be ready + * for either cob to be called before return. Only one cob will be + * called and it will be called exactly once per invocation. + */ + virtual void sendMessage( + const VoidCallback& cob, + const VoidCallback& errorCob, + apache::thrift::transport::TMemoryBuffer* message) = 0; + + /** + * Receive a message from the channel. + * + * @return call "cob" on success, "errorCob" on fail. Caller must be ready + * for either cob to be called before return. Only one cob will be + * called and it will be called exactly once per invocation. + */ + virtual void recvMessage( + const VoidCallback& cob, + const VoidCallback& errorCob, + apache::thrift::transport::TMemoryBuffer* message) = 0; + + /** + * Send a message over the channel and receive a response. + * + * @return call "cob" on success, "errorCob" on fail. Caller must be ready + * for either cob to be called before return. Only one cob will be + * called and it will be called exactly once per invocation. + */ + virtual void sendAndRecvMessage( + const VoidCallback& cob, + const VoidCallback& errorCob, + apache::thrift::transport::TMemoryBuffer* sendBuf, + apache::thrift::transport::TMemoryBuffer* recvBuf) = 0; + + /** + * Send a message over the channel, single cob version. (See above.) + * + * @return call "cob" on success or fail; channel status must be queried + * by the cob. + */ + void sendMessage(const VoidCallback& cob, + apache::thrift::transport::TMemoryBuffer* message) { + return sendMessage(cob, cob, message); + } + + /** + * Receive a message from the channel, single cob version. (See above.) + * + * @return call "cob" on success or fail; channel status must be queried + * by the cob. + */ + void recvMessage(const VoidCallback& cob, + apache::thrift::transport::TMemoryBuffer* message) { + return recvMessage(cob, cob, message); + } + + /** + * Send a message over the channel and receive response, single cob version. + * (See above.) + * + * @return call "cob" on success or fail; channel status must be queried + * by the cob. + */ + void sendAndRecvMessage(const VoidCallback& cob, + apache::thrift::transport::TMemoryBuffer* sendBuf, + apache::thrift::transport::TMemoryBuffer* recvBuf) { + return sendAndRecvMessage(cob, cob, sendBuf, recvBuf); + } + + /** + * Cancel pending callbacks. Use this when the channel is closing because the + * server had been shut down. + */ + virtual void cancelCallbacks() = 0; + + // TODO(dreiss): Make this nonvirtual when TFramedSocketAsyncChannel gets + // renamed to TFramedAsyncChannel. + virtual boost::shared_ptr getTransport() = 0; +}; + +}}} // apache::thrift::async + +#endif // #ifndef THRIFT_ASYNC_TASYNCCHANNEL_H_ diff --git a/thrift/lib/cpp/async/TAsyncDispatchProcessor.h b/thrift/lib/cpp/async/TAsyncDispatchProcessor.h new file mode 100644 index 00000000..c6cdf510 --- /dev/null +++ b/thrift/lib/cpp/async/TAsyncDispatchProcessor.h @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TASYNCDISPATCHPROCESSOR_H_ +#define THRIFT_ASYNC_TASYNCDISPATCHPROCESSOR_H_ 1 + +#include "thrift/lib/cpp/async/TAsyncProcessor.h" + +namespace apache { namespace thrift { namespace async { + +/** + * TAsyncDispatchProcessor is a helper class to parse the message header then + * call another function to dispatch based on the function name. + * + * Subclasses must implement dispatchCall() to dispatch on the function name. + */ +template +class TAsyncDispatchProcessorT : public TAsyncProcessor { + public: + virtual void process(std::tr1::function _return, + boost::shared_ptr in, + boost::shared_ptr out, + TConnectionContext* context) { + protocol::TProtocol* inRaw = in.get(); + protocol::TProtocol* outRaw = out.get(); + + // Try to dynamic cast to the template protocol type + Protocol_* specificIn = dynamic_cast(inRaw); + Protocol_* specificOut = dynamic_cast(outRaw); + if (specificIn && specificOut) { + return processFast(_return, specificIn, specificOut, context); + } + + // Log the fact that we have to use the slow path + T_GENERIC_PROTOCOL(this, inRaw, specificIn); + T_GENERIC_PROTOCOL(this, outRaw, specificOut); + + std::string fname; + protocol::TMessageType mtype; + int32_t seqid; + try { + inRaw->readMessageBegin(fname, mtype, seqid); + } catch (const TException &ex) { + GlobalOutput.printf("received invalid message from client: %s", + ex.what()); + _return(false); + return; + } + + // If this doesn't look like a valid call, log an error and return false so + // that the server will close the connection. + // + // (The old generated processor code used to try to skip a T_STRUCT and + // continue. However, that seems unsafe.) + if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY) { + GlobalOutput.printf("received invalid message type %d from client", + mtype); + _return(false); + return; + } + + return this->dispatchCall(_return, inRaw, outRaw, fname, seqid, context); + } + + void processFast(std::tr1::function _return, + Protocol_* in, Protocol_* out, + TConnectionContext* context) { + std::string fname; + protocol::TMessageType mtype; + int32_t seqid; + try { + in->readMessageBegin(fname, mtype, seqid); + } catch (const TException &ex) { + GlobalOutput.printf("received invalid message from client: %s", + ex.what()); + _return(false); + return; + } + + if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY) { + GlobalOutput.printf("received invalid message type %d from client", + mtype); + _return(false); + return; + } + + return this->dispatchCallTemplated(_return, in, out, fname, seqid, context); + } + + virtual void dispatchCall(std::tr1::function _return, + apache::thrift::protocol::TProtocol* in, + apache::thrift::protocol::TProtocol* out, + const std::string& fname, int32_t seqid, + TConnectionContext* context) = 0; + + virtual void dispatchCallTemplated(std::tr1::function _return, + Protocol_* in, Protocol_* out, + const std::string& fname, int32_t seqid, + TConnectionContext* context) = 0; +}; + +/** + * Non-templatized version of TAsyncDispatchProcessor, + * that doesn't bother trying to perform a dynamic_cast. + */ +class TAsyncDispatchProcessor : public TAsyncProcessor { + public: + virtual void process(std::tr1::function _return, + boost::shared_ptr in, + boost::shared_ptr out, + TConnectionContext* context) { + protocol::TProtocol* inRaw = in.get(); + protocol::TProtocol* outRaw = out.get(); + + std::string fname; + protocol::TMessageType mtype; + int32_t seqid; + try { + inRaw->readMessageBegin(fname, mtype, seqid); + } catch (const TException &ex) { + GlobalOutput.printf("received invalid message from client: %s", + ex.what()); + _return(false); + return; + } + + // If this doesn't look like a valid call, log an error and return false so + // that the server will close the connection. + // + // (The old generated processor code used to try to skip a T_STRUCT and + // continue. However, that seems unsafe.) + if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY) { + GlobalOutput.printf("received invalid message type %d from client", + mtype); + _return(false); + return; + } + + return dispatchCall(_return, inRaw, outRaw, fname, seqid, context); + } + + virtual void dispatchCall(std::tr1::function _return, + apache::thrift::protocol::TProtocol* in, + apache::thrift::protocol::TProtocol* out, + const std::string& fname, int32_t seqid, + TConnectionContext* context) = 0; +}; + +// Specialize TAsyncDispatchProcessorT for TProtocol and TDummyProtocol just to +// use the generic TDispatchProcessor. +template <> +class TAsyncDispatchProcessorT : + public TAsyncDispatchProcessor {}; +template <> +class TAsyncDispatchProcessorT : + public TAsyncDispatchProcessor {}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TASYNCDISPATCHPROCESSOR_H_ diff --git a/thrift/lib/cpp/async/TAsyncEventChannel.h b/thrift/lib/cpp/async/TAsyncEventChannel.h new file mode 100644 index 00000000..b573b3f3 --- /dev/null +++ b/thrift/lib/cpp/async/TAsyncEventChannel.h @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TASYNCEVENTCHANNEL_H_ +#define THRIFT_ASYNC_TASYNCEVENTCHANNEL_H_ 1 + +#include "thrift/lib/cpp/async/TAsyncChannel.h" +#include "thrift/lib/cpp/async/TDelayedDestruction.h" + +namespace apache { namespace thrift { namespace async { + +class TEventBase; + +/** + * TAsyncEventChannel defines an API for TAsyncChannel objects that are driven + * by TEventBase. + */ +class TAsyncEventChannel : public TAsyncChannel, + public TDelayedDestruction { + public: + + /** + * Determine if this channel is idle (i.e., has no outstanding reads or + * writes). + */ + virtual bool isIdle() const = 0; + + /** + * Attach the channel to a TEventBase. + * + * This may only be called if the channel is not currently attached to a + * TEventBase (by an earlier call to detachEventBase()). + * + * This method must be invoked in the TEventBase's thread. + */ + virtual void attachEventBase(TEventBase* eventBase) = 0; + + /** + * Detach the channel from its TEventBase. + * + * This may only be called when the channel is idle and has no reads or + * writes pending. Once detached, the channel may not be used again until it + * is re-attached to a TEventBase by calling attachEventBase(). + * + * This method must be called from the current TEventBase's thread. + */ + virtual void detachEventBase() = 0; + + /** + * Get the receive timeout. + * + * @return Returns the current receive timeout, in milliseconds. A return + * value of 0 indicates that no timeout is set. + */ + virtual uint32_t getRecvTimeout() const = 0; + + /** + * Set the timeout for receiving messages. + * + * When set to a non-zero value, the entire message must be received within + * the specified number of milliseconds, or the receive will fail and the + * channel will be closed. + */ + virtual void setRecvTimeout(uint32_t milliseconds) = 0; + + protected: + /** + * Protected destructor. + * + * Users of TAsyncEventChannel must never delete it directly. Instead, invoke + * destroy() instead. (See the documentation in TDelayedDestruction.h for + * more details.) + */ + + virtual ~TAsyncEventChannel() { } +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TASYNCEVENTCHANNEL_H_ diff --git a/thrift/lib/cpp/async/TAsyncProcessor.h b/thrift/lib/cpp/async/TAsyncProcessor.h new file mode 100644 index 00000000..591e9877 --- /dev/null +++ b/thrift/lib/cpp/async/TAsyncProcessor.h @@ -0,0 +1,90 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef THRIFT_TASYNCPROCESSOR_H +#define THRIFT_TASYNCPROCESSOR_H 1 + +#include +#include +#include "thrift/lib/cpp/TProcessor.h" +#include "thrift/lib/cpp/server/TConnectionContext.h" +#include "thrift/lib/cpp/protocol/TProtocol.h" + +using apache::thrift::server::TConnectionContext; + +namespace apache { namespace thrift { namespace async { + +/** + * Async version of a TProcessor. It is not expected to complete by the time + * the call to process returns. Instead, it calls a cob to signal completion. + * + * @author David Reiss + */ + +class TEventServer; // forward declaration + +class TAsyncProcessor : public TProcessorBase { + public: + virtual ~TAsyncProcessor() {} + + virtual void process(std::tr1::function _return, + boost::shared_ptr in, + boost::shared_ptr out, + TConnectionContext* context = NULL) = 0; + + void process(std::tr1::function _return, + boost::shared_ptr io) { + return process(_return, io, io); + } + + const TEventServer* getAsyncServer() { + return asyncServer_; + } + protected: + TAsyncProcessor() {} + + const TEventServer* asyncServer_; + private: + friend class TEventServer; + void setAsyncServer(const TEventServer* server) { + asyncServer_ = server; + } +}; + +class TAsyncProcessorFactory { + public: + virtual ~TAsyncProcessorFactory() {} + + /** + * Get the TAsyncProcessor to use for a particular connection. + */ + virtual boost::shared_ptr getProcessor( + server::TConnectionContext* ctx) = 0; +}; + +class TAsyncSingletonProcessorFactory : public TAsyncProcessorFactory { + public: + explicit TAsyncSingletonProcessorFactory( + const boost::shared_ptr& processor) : + processor_(processor) {} + + boost::shared_ptr getProcessor(server::TConnectionContext*) { + return processor_; + } + + private: + boost::shared_ptr processor_; +}; + + +}}} // apache::thrift::async + +// XXX I'm lazy for now +namespace apache { namespace thrift { +using apache::thrift::async::TAsyncProcessor; +}} + +#endif // #ifndef THRIFT_TASYNCPROCESSOR_H diff --git a/thrift/lib/cpp/async/TAsyncSSLServerSocket.h b/thrift/lib/cpp/async/TAsyncSSLServerSocket.h new file mode 100644 index 00000000..d4e2c9aa --- /dev/null +++ b/thrift/lib/cpp/async/TAsyncSSLServerSocket.h @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TASYNCSSLSERVERSOCKET_H_ +#define THRIFT_ASYNC_TASYNCSSLSERVERSOCKET_H_ 1 + +#include "thrift/lib/cpp/async/TAsyncServerSocket.h" +#include "thrift/lib/cpp/transport/TSSLSocket.h" + +namespace apache { namespace thrift { + +namespace transport { +class TSocketAddress; +} + +namespace async { + +class TAsyncSSLSocket; + +class TAsyncSSLServerSocket : public TDelayedDestruction, + private TAsyncServerSocket::AcceptCallback { + public: + class SSLAcceptCallback { + public: + virtual ~SSLAcceptCallback() {} + + /** + * connectionAccepted() is called whenever a new client connection is + * received. + * + * The SSLAcceptCallback will remain installed after connectionAccepted() + * returns. + * + * @param sock The newly accepted client socket. The + * SSLAcceptCallback + * assumes ownership of this socket, and is responsible + * for closing it when done. + */ + virtual void connectionAccepted( + const boost::shared_ptr &sock) + THRIFT_NOEXCEPT = 0; + + /** + * acceptError() is called if an error occurs while accepting. + * + * The SSLAcceptCallback will remain installed even after an accept error. + * If the callback wants to uninstall itself and stop trying to accept new + * connections, it must explicit call setAcceptCallback(NULL). + * + * @param ex An exception representing the error. + */ + virtual void acceptError(const std::exception& ex) THRIFT_NOEXCEPT = 0; + }; + + /** + * Create a new TAsyncSSLServerSocket with the specified TEventBase. + * + * @param eventBase The TEventBase to use for driving the asynchronous I/O. + * If this parameter is NULL, attachEventBase() must be + * called before this socket can begin accepting + * connections. All TAsyncSSLSocket objects accepted by + * this server socket will be attached to this TEventBase + * when they are created. + */ + explicit TAsyncSSLServerSocket( + const boost::shared_ptr& ctx, + TEventBase* eventBase = NULL); + + /** + * Destroy the socket. + * + * destroy() must be called to destroy the socket. The normal destructor is + * private, and should not be invoked directly. This prevents callers from + * deleting a TAsyncSSLServerSocket while it is invoking a callback. + */ + virtual void destroy(); + + void bind(const transport::TSocketAddress& address) { + serverSocket_->bind(address); + } + void bind(uint16_t port) { + serverSocket_->bind(port); + } + void getAddress(transport::TSocketAddress* addressReturn) { + serverSocket_->getAddress(addressReturn); + } + void listen(int backlog) { + serverSocket_->listen(backlog); + } + + /** + * Helper function to create a shared_ptr. + * + * This passes in the correct destructor object, since TAsyncSSLServerSocket's + * destructor is protected and cannot be invoked directly. + */ + static boost::shared_ptr newSocket( + const boost::shared_ptr& ctx, + TEventBase* evb) { + return boost::shared_ptr( + new TAsyncSSLServerSocket(ctx, evb), + Destructor()); + } + + /** + * Set the accept callback. + * + * This method may only be invoked from the TEventBase's loop thread. + * + * @param callback The callback to invoke when a new socket + * connection is accepted and a new TAsyncSSLSocket is + * created. + * + * Throws TTransportException on error. + */ + void setSSLAcceptCallback(SSLAcceptCallback* callback); + + SSLAcceptCallback *getSSLAcceptCallback() const { + return sslCallback_; + } + + void attachEventBase(TEventBase* eventBase); + void detachEventBase(); + + /** + * Returns the TEventBase that the handler is currently attached to. + */ + TEventBase* getEventBase() const { + return eventBase_; + } + + protected: + /** + * Protected destructor. + * + * Invoke destroy() instead to destroy the TAsyncSSLServerSocket. + */ + virtual ~TAsyncSSLServerSocket(); + + private: + virtual void connectionAccepted(int fd, + const transport::TSocketAddress& clientAddr) + THRIFT_NOEXCEPT; + virtual void acceptError(const std::exception& ex) THRIFT_NOEXCEPT; + + TEventBase* eventBase_; + TAsyncServerSocket* serverSocket_; + // SSL context + boost::shared_ptr ctx_; + // The accept callback + SSLAcceptCallback* sslCallback_; +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TASYNCSSLSERVERSOCKET_H_ diff --git a/thrift/lib/cpp/async/TAsyncSSLSocket.h b/thrift/lib/cpp/async/TAsyncSSLSocket.h new file mode 100644 index 00000000..93dcf3f2 --- /dev/null +++ b/thrift/lib/cpp/async/TAsyncSSLSocket.h @@ -0,0 +1,411 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TASYNCSSLSOCKET_H_ +#define THRIFT_ASYNC_TASYNCSSLSOCKET_H_ 1 + +#include "thrift/lib/cpp/async/TAsyncSocket.h" +#include "thrift/lib/cpp/async/TAsyncTimeout.h" +#include "thrift/lib/cpp/transport/TSSLSocket.h" +#include "thrift/lib/cpp/transport/TTransportException.h" + +namespace apache { namespace thrift { + +namespace async { + +class TSSLException: public apache::thrift::transport::TTransportException { + public: + TSSLException(int sslError, int errno_copy); + + int getSSLError() const { return error_; } + + protected: + int error_; +}; + +/** + * A class for performing asynchronous I/O on an SSL connection. + * + * TAsyncSSLSocket allows users to asynchronously wait for data on an + * SSL connection, and to asynchronously send data. + * + * The APIs for reading and writing are intentionally asymmetric. + * Waiting for data to read is a persistent API: a callback is + * installed, and is notified whenever new data is available. It + * continues to be notified of new events until it is uninstalled. + * + * TAsyncSSLSocket does not provide read timeout functionality, + * because it typically cannot determine when the timeout should be + * active. Generally, a timeout should only be enabled when + * processing is blocked waiting on data from the remote endpoint. + * For server connections, the timeout should not be active if the + * server is currently processing one or more outstanding requests for + * this connection. For client connections, the timeout should not be + * active if there are no requests pending on the connection. + * Additionally, if a client has multiple pending requests, it will + * ususally want a separate timeout for each request, rather than a + * single read timeout. + * + * The write API is fairly intuitive: a user can request to send a + * block of data, and a callback will be informed once the entire + * block has been transferred to the kernel, or on error. + * TAsyncSSLSocket does provide a send timeout, since most callers + * want to give up if the remote end stops responding and no further + * progress can be made sending the data. + */ +class TAsyncSSLSocket : public TAsyncSocket { + public: + +#if THRIFT_HAVE_UNIQUE_PTR + typedef std::unique_ptr UniquePtr; +#endif + + class HandshakeCallback { + public: + virtual ~HandshakeCallback() {} + + /** + * handshakeSuccess() is called when a new SSL connection is + * established, i.e., after SSL_accept/connect() returns successfully. + * + * The HandshakeCallback will be uninstalled before handshakeSuccess() + * is called. + * + * @param sock SSL socket on which the handshake was initiated + */ + virtual void handshakeSuccess(TAsyncSSLSocket *sock) THRIFT_NOEXCEPT = 0; + + /** + * handshakeError() is called if an error occurs while + * establishing the SSL connection. + * + * The HandshakeCallback will be uninstalled before handshakeError() + * is called. + * + * @param sock SSL socket on which the handshake was initiated + * @param ex An exception representing the error. + */ + virtual void handshakeError( + TAsyncSSLSocket *sock, + const apache::thrift::transport::TTransportException& ex) + THRIFT_NOEXCEPT = 0; + }; + + class HandshakeTimeout : public TAsyncTimeout { + public: + HandshakeTimeout(TAsyncSSLSocket* sslSocket, TEventBase* eventBase) + : TAsyncTimeout(eventBase) + , sslSocket_(sslSocket) {} + + virtual void timeoutExpired() THRIFT_NOEXCEPT { + sslSocket_->timeoutExpired(); + } + + private: + TAsyncSSLSocket* sslSocket_; + }; + + /** + * These are passed to the application via errno, so values have to be + * outside the valid errno range + */ + enum SSLError { + SSL_CLIENT_RENEGOTIATION_ATTEMPT = 0x8001 + }; + + /** + * Create a client TAsyncSSLSocket + */ + TAsyncSSLSocket(const boost::shared_ptr &ctx, + TEventBase* evb) : + TAsyncSocket(evb), + corked_(false), + server_(false), + handshakeComplete_(false), + renegotiateAttempted_(false), + sslState_(STATE_UNINIT), + ctx_(ctx), + handshakeCallback_(NULL), + ssl_(NULL), + sslSession_(NULL), + handshakeTimeout_(this, evb) { + } + + /** + * Create a TAsyncSSLSocket from an already connected socket file descriptor. + * + * Note that while TAsyncSSLSocket enables TCP_NODELAY for sockets it creates + * when connecting, it does not change the socket options when given an + * existing file descriptor. If callers want TCP_NODELAY enabled when using + * this version of the constructor, they need to explicitly call + * setNoDelay(true) after the constructor returns. + * + * @param ctx SSL context for this connection. + * @param evb EventBase that will manage this socket. + * @param fd File descriptor to take over (should be a connected socket). + */ + TAsyncSSLSocket(const boost::shared_ptr& ctx, + TEventBase* evb, int fd, bool server = true); + + /** + * Helper function to create a shared_ptr. + */ + static boost::shared_ptr newSocket( + const boost::shared_ptr& ctx, + TEventBase* evb, int fd, bool server=true) { + return boost::shared_ptr( + new TAsyncSSLSocket(ctx, evb, fd, server), + Destructor()); + } + + /** + * Helper function to create a shared_ptr. + */ + static boost::shared_ptr newSocket( + const boost::shared_ptr& ctx, + TEventBase* evb) { + return boost::shared_ptr( + new TAsyncSSLSocket(ctx, evb), + Destructor()); + } + + /** + * TODO: implement support for SSL renegotiation. + * + * This involves proper handling of the SSL_ERROR_WANT_READ/WRITE + * code as a result of SSL_write/read(), instead of returning an + * error. In that case, the READ/WRITE event should be registered, + * and a flag (e.g., writeBlockedOnRead) should be set to indiciate + * the condition. In the next invocation of read/write callback, if + * the flag is on, performWrite()/performRead() should be called in + * addition to the normal call to performRead()/performWrite(), and + * the flag should be reset. + */ + + // Inherit TAsyncTransport methods from TAsyncSocket except the + // following. + // See the documentation in TAsyncTransport.h + // TODO: implement graceful shutdown in close() + // TODO: implement detachSSL() that returns the SSL connection + virtual void closeNow(); + virtual void shutdownWrite(); + virtual void shutdownWriteNow(); + virtual bool good() const; + virtual bool connecting() const; + + /** + * Accept an SSL connection on the socket. + * + * The callback will be invoked and uninstalled when an SSL + * connection has been established on the underlying socket. + * + * @param callback callback object to invoke on success/failure + * @param timeout timeout for this function in milliseconds, or 0 for no + * timeout + */ + void sslAccept(HandshakeCallback* callback, uint32_t timeout = 0); + + /** + * Invoke SSL accept following an asynchronous session cache lookup + */ + void restartSSLAccept(); + + /** + * Connect to the given address, invoking callback when complete or on error + * + * Note timeout applies to TCP + SSL connection time + */ + void connect(ConnectCallback* callback, + const transport::TSocketAddress& address, + int timeout = 0, + const OptionList &options = emptyOptionList) THRIFT_NOEXCEPT; + + using TAsyncSocket::connect; + + /** + * Initiate an SSL connection on the socket + * THe callback will be invoked and uninstalled when an SSL connection + * has been establshed on the underlying socket. + * + * @param callback callback object to invoke on success/failure + * @param timeout timeout for this function in milliseconds, or 0 for no + * timeout + */ + void sslConnect(HandshakeCallback *callback, uint64_t timeout = 0); + + enum SSLStateEnum { + STATE_UNINIT, + STATE_ACCEPTING, + STATE_CACHE_LOOKUP, + STATE_CONNECTING, + STATE_ESTABLISHED, + STATE_REMOTE_CLOSED, /// remote end closed; we can still write + STATE_CLOSING, ///< close() called, but waiting on writes to complete + /// close() called with pending writes, before connect() has completed + STATE_CONNECTING_CLOSING, + STATE_CLOSED, + STATE_ERROR + }; + + SSLStateEnum getSSLState() const { return sslState_;} + + /** + * Get a handle to the negotiated SSL session. This increments the session + * refcount and must be deallocated by the caller. + */ + SSL_SESSION *getSSLSession(); + + /** + * Set the SSL session to be used during sslConnect. TAsyncSSLSocket will + * hold a reference to the session until it is destroyed or released by the + * underlying SSL structure. + * + * @param takeOwnership if true, TAsyncSSLSocket will assume the caller's + * reference count to session. + */ + void setSSLSession(SSL_SESSION *session, bool takeOwnership = false); + +#ifdef OPENSSL_NPN_NEGOTIATED + /** + * Get the name of the protocol selected by the client during + * Next Protocol Negotiation (NPN) + * + * @param protoName Name of the protocol (not guaranteed to be + * null terminated); will be set to NULL if + * the client did not negotiate a protocol. + * Note: the TAsyncSSLSocket retains ownership + * of this string. + * @param protoNameLen Length of the name. + */ + void getSelectedNextProtocol(const unsigned char** protoName, + unsigned* protoLen); +#endif // OPENSSL_NPN_NEGOTIATED + + /** + * Determine if the session specified during setSSLSession was reused + * or if the server rejected it and issued a new session. + */ + bool getSSLSessionReused() const; + + /** + * Get the negociated cipher name for this SSL connection. + * Returns the cipher used or the constant value "NONE" when no SSL session + * has been established. + */ + const char *getNegotiatedCipherName() const; + + /** + * Get the SSL version for this connection. + * Possible return values are SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, + * with hexa representations 0x200, 0x300, 0x301, + * or 0 if no SSL session has been established. + */ + int getSSLVersion() const; + + /* Get the number of bytes read from the wire (including protocol + * overhead). Returns 0 once the connection has been closed. + */ + unsigned long getBytesRead() const { + if (ssl_ != NULL) { + return BIO_number_read(SSL_get_rbio(ssl_)); + } + return 0; + } + + /* Get the number of bytes written to the wire (including protocol + * overhead). Returns 0 once the connection has been closed. + */ + unsigned long getBytesWritten() const { + if (ssl_ != NULL) { + return BIO_number_written(SSL_get_wbio(ssl_)); + } + return 0; + } + + virtual void attachEventBase(TEventBase* eventBase) { + TAsyncSocket::attachEventBase(eventBase); + handshakeTimeout_.attachEventBase(eventBase); + } + + virtual void detachEventBase() { + TAsyncSocket::detachEventBase(); + handshakeTimeout_.detachEventBase(); + } + + void timeoutExpired() THRIFT_NOEXCEPT; + + protected: + + /** + * Protected destructor. + * + * Users of TAsyncSSLSocket must never delete it directly. Instead, invoke + * destroy() instead. (See the documentation in TDelayedDestruction.h for + * more details.) + */ + ~TAsyncSSLSocket(); + + // Inherit event notification methods from TAsyncSocket except + // the following. + + void handleRead() THRIFT_NOEXCEPT; + void handleWrite() THRIFT_NOEXCEPT; + void handleAccept() THRIFT_NOEXCEPT; + void handleConnect() THRIFT_NOEXCEPT; + + void invalidState(HandshakeCallback* callback); + bool willBlock(int ret, int *errorOut) THRIFT_NOEXCEPT; + + virtual void checkForImmediateRead() THRIFT_NOEXCEPT; + // TAsyncSocket calls this at the wrong time for SSL + void handleInitialReadWrite() THRIFT_NOEXCEPT {} + + ssize_t performRead(void* buf, size_t buflen); + ssize_t performWrite(const iovec* vec, uint32_t count, bool haveMore, + uint32_t* countWritten, uint32_t* partialWritten); + + // Inherit error handling methods from TAsyncSocket, plus the following. + void failHandshake(const char* fn, const transport::TTransportException& ex); + + void invokeHandshakeCallback(); + + static void sslInfoCallback(const SSL *ssl, int type, int val); + + // Whether we've applied the TCP_CORK option to the socket + bool corked_; + // SSL related members. + bool server_; + // Used to prevent client-initiated renegotiation. Note that TAsyncSSLSocket + // doesn't fully support renegotiation, so we could just fail all attempts + // to enforce this. Once it is supported, we should make it an option + // to disable client-initiated renegotiation. + bool handshakeComplete_; + bool renegotiateAttempted_; + SSLStateEnum sslState_; + boost::shared_ptr ctx_; + // Callback for SSL_accept() or SSL_connect() + HandshakeCallback* handshakeCallback_; + SSL* ssl_; + SSL_SESSION *sslSession_; + HandshakeTimeout handshakeTimeout_; +}; + +}}} // apache::thrift::async + +#endif // #ifndef THRIFT_ASYNC_TASYNCSSLSOCKET_H_ diff --git a/thrift/lib/cpp/async/TAsyncServerSocket.h b/thrift/lib/cpp/async/TAsyncServerSocket.h new file mode 100644 index 00000000..15b10a20 --- /dev/null +++ b/thrift/lib/cpp/async/TAsyncServerSocket.h @@ -0,0 +1,513 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TASYNCSERVERSOCKET_H_ +#define THRIFT_ASYNC_TASYNCSERVERSOCKET_H_ 1 + +#include "thrift/lib/cpp/thrift_config.h" +#include "thrift/lib/cpp/async/TDelayedDestruction.h" +#include "thrift/lib/cpp/async/TEventHandler.h" +#include +#include +#include +#include +#include +#include +#include + +namespace apache { namespace thrift { + +namespace transport { +class TSocketAddress; +} + +namespace async { + +class TNotificationPipe; + +/** + * A listening socket that asynchronously informs a callback whenever a new + * connection has been accepted. + * + * Unlike most async interfaces that always invoke their callback in the same + * TEventBase thread, TAsyncServerSocket is unusual in that it can distribute + * the callbacks across multiple TEventBase threads. + * + * This supports a common use case for network servers to distribute incoming + * connections across a number of TEventBase threads. (Servers typically run + * with one TEventBase thread per CPU.) + * + * Despite being able to invoke callbacks in multiple TEventBase threads, + * TAsyncServerSocket still has one "primary" TEventBase. Operations that + * modify the TAsyncServerSocket state may only be performed from the primary + * TEventBase thread. + */ +class TAsyncServerSocket : public TDelayedDestruction, + private TEventHandler { + public: +#if THRIFT_HAVE_UNIQUE_PTR + typedef std::unique_ptr UniquePtr; +#endif + + class AcceptCallback { + public: + virtual ~AcceptCallback() {} + + /** + * connectionAccepted() is called whenever a new client connection is + * received. + * + * The AcceptCallback will remain installed after connectionAccepted() + * returns. + * + * @param fd The newly accepted client socket. The AcceptCallback + * assumes ownership of this socket, and is responsible + * for closing it when done. The newly accepted file + * descriptor will have already been put into + * non-blocking mode. + * @param clientAddr A reference to a TSocketAddress struct containing the + * client's address. This struct is only guaranteed to + * remain valid until connectionAccepted() returns. + */ + virtual void connectionAccepted(int fd, + const transport::TSocketAddress& clientAddr) + THRIFT_NOEXCEPT = 0; + + /** + * acceptError() is called if an error occurs while accepting. + * + * The AcceptCallback will remain installed even after an accept error, + * as the errors are typically somewhat transient, such as being out of + * file descriptors. The server socket must be explicitly stopped if you + * wish to stop accepting after an error. + * + * @param ex An exception representing the error. + */ + virtual void acceptError(const std::exception& ex) THRIFT_NOEXCEPT = 0; + + /** + * acceptStarted() will be called in the callback's TEventBase thread + * after this callback has been added to the TAsyncServerSocket. + * + * acceptStarted() will be called before any calls to connectionAccepted() + * or acceptError() are made on this callback. + * + * acceptStarted() makes it easier for callbacks to perform initialization + * inside the callback thread. (The call to addAcceptCallback() must + * always be made from the TAsyncServerSocket's primary TEventBase thread. + * acceptStarted() provides a hook that will always be invoked in the + * callback's thread.) + * + * Note that the call to acceptStarted() is made once the callback is + * added, regardless of whether or not the TAsyncServerSocket is actually + * accepting at the moment. acceptStarted() will be called even if the + * TAsyncServerSocket is paused when the callback is added (including if + * the initial call to startAccepting() on the TAsyncServerSocket has not + * been made yet). + */ + virtual void acceptStarted() THRIFT_NOEXCEPT {} + + /** + * acceptStopped() will be called when this AcceptCallback is removed from + * the TAsyncServerSocket, or when the TAsyncServerSocket is destroyed, + * whichever occurs first. + * + * No more calls to connectionAccepted() or acceptError() will be made + * after acceptStopped() is invoked. + */ + virtual void acceptStopped() THRIFT_NOEXCEPT {} + }; + + static const uint32_t kDefaultMaxAcceptAtOnce = 30; + static const uint32_t kDefaultCallbackAcceptAtOnce = 5; + static const uint32_t kDefaultMaxMessagesInPipe = 0xffffffff; + /** + * Create a new TAsyncServerSocket with the specified TEventBase. + * + * @param eventBase The TEventBase to use for driving the asynchronous I/O. + * If this parameter is NULL, attachEventBase() must be + * called before this socket can begin accepting + * connections. + */ + explicit TAsyncServerSocket(TEventBase* eventBase = NULL); + + /** + * Helper function to create a shared_ptr. + * + * This passes in the correct destructor object, since TAsyncServerSocket's + * destructor is protected and cannot be invoked directly. + */ + static boost::shared_ptr newSocket(TEventBase* evb) { + return boost::shared_ptr(new TAsyncServerSocket(evb), + Destructor()); + } + + /** + * Destroy the socket. + * + * TAsyncServerSocket::destroy() must be called to destroy the socket. + * The normal destructor is private, and should not be invoked directly. + * This prevents callers from deleting a TAsyncServerSocket while it is + * invoking a callback. + * + * destroy() must be invoked from the socket's primary TEventBase thread. + * + * If there are AcceptCallbacks still installed when destroy() is called, + * acceptStopped() will be called on these callbacks to notify them that + * accepting has stopped. Accept callbacks being driven by other TEventBase + * threads may continue to receive new accept callbacks for a brief period of + * time after destroy() returns. They will not receive any more callback + * invocations once acceptStopped() is invoked. + */ + virtual void destroy(); + + /** + * Attach this TAsyncServerSocket to its primary TEventBase. + * + * This may only be called if the TAsyncServerSocket is not already attached + * to a TEventBase. The TAsyncServerSocket must be attached to a TEventBase + * before it can begin accepting connections. + */ + void attachEventBase(TEventBase *eventBase); + + /** + * Detach the TAsyncServerSocket from its primary TEventBase. + * + * detachEventBase() may only be called if the TAsyncServerSocket is not + * currently accepting connections. + */ + void detachEventBase(); + + /** + * Get the TEventBase used by this socket. + */ + TEventBase* getEventBase() const { + return eventBase_; + } + + /** + * Create a TAsyncServerSocket from an existing socket file descriptor. + * + * useExistingSocket() will cause the TAsyncServerSocket to take ownership of + * the specified file descriptor, and use it to listen for new connections. + * The TAsyncServerSocket will close the file descriptor when it is + * destroyed. + * + * useExistingSocket() must be called before bind() or listen(). + * + * The supplied file descriptor will automatically be put into non-blocking + * mode. The caller may have already directly called bind() and possibly + * listen on the file descriptor. If so the caller should skip calling the + * corresponding TAsyncServerSocket::bind() and listen() methods. + * + * On error a TTransportException will be thrown and the caller will retain + * ownership of the file descriptor. + */ + void useExistingSocket(int fd); + + /** + * Return the underlying file descriptor + */ + int getSocket() const { + return socket_; + } + + /** + * Bind to the specified address. + * + * This must be called from the primary TEventBase thread. + * + * Throws TTransportException on error. + */ + void bind(const transport::TSocketAddress& address); + + /** + * Bind to the specified port. + * + * This must be called from the primary TEventBase thread. + * + * Throws TTransportException on error. + */ + void bind(uint16_t port); + + /** + * Get the local address to which the socket is bound. + * + * Throws TTransportException on error. + */ + void getAddress(transport::TSocketAddress* addressReturn); + + /** + * Begin listening for connections. + * + * This calls ::listen() with the specified backlog. + * + * Once listen() is invoked the socket will actually be open so that remote + * clients may establish connections. (Clients that attempt to connect + * before listen() is called will receive a connection refused error.) + * + * At least one callback must be set and startAccepting() must be called to + * actually begin notifying the accept callbacks of newly accepted + * connections. The backlog parameter controls how many connections the + * kernel will accept and buffer internally while the accept callbacks are + * paused (or if accepting is enabled but the callbacks cannot keep up). + * + * bind() must be called before calling listen(). + * listen() must be called from the primary TEventBase thread. + * + * Throws TTransportException on error. + */ + void listen(int backlog); + + /** + * Add an AcceptCallback. + * + * When a new socket is accepted, one of the AcceptCallbacks will be invoked + * with the new socket. The AcceptCallbacks are invoked in a round-robin + * fashion. This allows the accepted sockets to distributed among a pool of + * threads, each running its own TEventBase object. This is a common model, + * since most asynchronous-style servers typically run one TEventBase thread + * per CPU. + * + * The TEventBase object associated with each AcceptCallback must be running + * its loop. If the TEventBase loop is not running, sockets will still be + * scheduled for the callback, but the callback cannot actually get invoked + * until the loop runs. + * + * This method must be invoked from the TAsyncServerSocket's primary + * TEventBase thread. + * + * Note that startAccepting() must be called on the TAsyncServerSocket to + * cause it to actually start accepting sockets once callbacks have been + * installed. + * + * @param callback The callback to invoke. + * @param eventBase The TEventBase to use to invoke the callback. This + * parameter may be NULL, in which case the callback will be invoked in + * the TAsyncServerSocket's primary TEventBase. + * @param maxAtOnce The maximum number of connections to accept in this + * callback on a single iteration of the event base loop. + * This only takes effect when eventBase is non-NULL. When + * using a NULL eventBase for the callback, the + * setMaxAcceptAtOnce() method controls how many + * connections the main event base will accept at once. + */ + void addAcceptCallback(AcceptCallback *callback, TEventBase *eventBase, + uint32_t maxAtOnce = kDefaultCallbackAcceptAtOnce); + + /** + * Remove an AcceptCallback. + * + * This allows a single AcceptCallback to be removed from the round-robin + * pool. + * + * This method must be invoked from the TAsyncServerSocket's primary + * TEventBase thread. Use TEventBase::runInEventBaseThread() to schedule the + * operation in the correct TEventBase if your code is not in the server + * socket's primary TEventBase. + * + * Given that the accept callback is being driven by a different TEventBase, + * the AcceptCallback may continue to be invoked for a short period of time + * after removeAcceptCallback() returns in this thread. Once the other + * TEventBase thread receives the notification to stop, it will call + * acceptStopped() on the callback to inform it that it is fully stopped and + * will not receive any new sockets. + * + * If the last accept callback is removed while the socket is accepting, + * the socket will implicitly pause accepting. If a callback is later added, + * it will resume accepting immediately, without requiring startAccepting() + * to be invoked. + * + * @param callback The callback to uninstall. + * @param eventBase The TEventBase associated with this callback. This must + * be the same TEventBase that was used when the callback was installed + * with addAcceptCallback(). + */ + void removeAcceptCallback(AcceptCallback *callback, TEventBase *eventBase); + + /** + * Begin accepting connctions on this socket. + * + * bind() and listen() must be called before calling startAccepting(). + * + * When a TAsyncServerSocket is initially created, it will not begin + * accepting connections until at least one callback has been added and + * startAccepting() has been called. startAccepting() can also be used to + * resume accepting connections after a call to pauseAccepting(). + * + * If startAccepting() is called when there are no accept callbacks + * installed, the socket will not actually begin accepting until an accept + * callback is added. + * + * This method may only be called from the primary TEventBase thread. + */ + void startAccepting(); + + /** + * Pause accepting connections. + * + * startAccepting() may be called to resume accepting. + * + * This method may only be called from the primary TEventBase thread. + * If there are AcceptCallbacks being driven by other TEventBase threads they + * may continue to receive callbacks for a short period of time after + * pauseAccepting() returns. + * + * Unlike removeAcceptCallback() or destroy(), acceptStopped() will not be + * called on the AcceptCallback objects simply due to a temporary pause. If + * the server socket is later destroyed while paused, acceptStopped() will be + * called all of the installed AcceptCallbacks. + */ + void pauseAccepting(); + + /** + * Get the maximum number of connections that will be accepted each time + * around the event loop. + */ + uint32_t getMaxAcceptAtOnce() const { + return maxAcceptAtOnce_; + } + + /** + * Set the maximum number of connections that will be accepted each time + * around the event loop. + * + * This provides a very coarse-grained way of controlling how fast the + * TAsyncServerSocket will accept connections. If you find that when your + * server is overloaded TAsyncServerSocket accepts connections more quickly + * than your code can process them, you can try lowering this number so that + * fewer connections will be accepted each event loop iteration. + * + * For more explicit control over the accept rate, you can also use + * pauseAccepting() to temporarily pause accepting when your server is + * overloaded, and then use startAccepting() later to resume accepting. + */ + void setMaxAcceptAtOnce(uint32_t numConns) { + maxAcceptAtOnce_ = numConns; + } + + /** + * Get the maximum number of unprocessed messages which a NotificationPipe + * can hold. + */ + uint32_t getMaxNumMessagesInPipe() const { + return maxNumMsgsInPipe_; + } + + /** + * Set the maximum number of unprocessed messages in NotificationPipe. + * No new message will be sent to that NotificationPipe if there are more + * than such number of unprocessed messages in that pipe. + */ + void setMaxNumMessagesInPipe(uint32_t num) { + maxNumMsgsInPipe_ = num; + } + + /** + * Get the speed of adjusting connection accept rate. + */ + double getAcceptRateAdjustSpeed() const { + return acceptRateAdjustSpeed_; + } + + /** + * Set the speed of adjusting connection accept rate. + */ + void setAcceptRateAdjustSpeed(double speed) { + acceptRateAdjustSpeed_ = speed; + } + + /** + * Get the number of connections dropped by the TAsyncServerSocket + */ + uint64_t getNumDroppedConnections() const { + return numDroppedConnections_; + } + + protected: + /** + * Protected destructor. + * + * Invoke destroy() instead to destroy the TAsyncServerSocket. + */ + virtual ~TAsyncServerSocket(); + + private: + /** + * A struct to keep track of the callbacks associated with this server + * socket. + */ + struct CallbackInfo { + CallbackInfo(AcceptCallback *callback, TEventBase *eventBase) + : callback(callback), + eventBase(eventBase), + pipe(NULL) {} + + AcceptCallback *callback; + TEventBase *eventBase; + // Note that the TNotificationPipe is actually owned by the RemoteAcceptor. + // The RemoteAcceptor will destroy the TNotificationPipe (and itself) + // once the pipe is closed by the TAsyncServerSocket. + TNotificationPipe *pipe; + }; + class RemoteAcceptor; + enum MessageType { + MSG_NEW_CONN = 0, + MSG_ERROR = 1 + }; + class BackoffTimeout; + + // Inherited from TEventHandler + virtual void handlerReady(uint16_t events) THRIFT_NOEXCEPT; + + int createSocket(int family); + void setupSocket(int fd); + void dispatchSocket(int socket, const transport::TSocketAddress& address); + void dispatchError(const char *msg, int errnoValue); + void enterBackoff(); + void backoffTimeoutExpired(); + + CallbackInfo* nextCallback() { + CallbackInfo* info = &callbacks_[callbackIndex_]; + + ++callbackIndex_; + if (callbackIndex_ >= callbacks_.size()) { + callbackIndex_ = 0; + } + + return info; + } + + TEventBase *eventBase_; + sa_family_t addressFamily_; + int socket_; + bool accepting_; + uint32_t maxAcceptAtOnce_; + uint32_t maxNumMsgsInPipe_; + double acceptRateAdjustSpeed_; //0 to disable auto adjust + double acceptRate_; + int64_t lastAccepTimestamp_; // milliseconds + uint64_t numDroppedConnections_; + uint32_t callbackIndex_; + BackoffTimeout *backoffTimeout_; + std::vector callbacks_; +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TASYNCSERVERSOCKET_H_ diff --git a/thrift/lib/cpp/async/TAsyncSignalHandler.h b/thrift/lib/cpp/async/TAsyncSignalHandler.h new file mode 100644 index 00000000..7a80be21 --- /dev/null +++ b/thrift/lib/cpp/async/TAsyncSignalHandler.h @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TASYNCSIGNALHANDLER_H_ +#define THRIFT_ASYNC_TASYNCSIGNALHANDLER_H_ 1 + +#include "thrift/lib/cpp/thrift_config.h" +#include +#include + +namespace apache { namespace thrift { namespace async { + +class TEventBase; + +/** + * A handler to receive notification about POSIX signals. + * + * TAsyncSignalHandler allows code to process signals from within a TEventBase + * loop. Standard signal handlers interrupt execution of the main thread, and + * are run while the main thread is paused. As a result, great care must be + * taken to avoid race conditions if the signal handler has to access or modify + * any data used by the main thread. + * + * TAsyncSignalHandler solves this problem by running the TAsyncSignalHandler + * callback in normal thread of execution, as a TEventBase callback. + * + * TAsyncSignalHandler may only be used in a single thread. It will only + * process signals received by the thread where the TAsyncSignalHandler is + * registered. It is the user's responsibility to ensure that signals are + * delivered to the desired thread in multi-threaded programs. + */ +class TAsyncSignalHandler { + public: + /** + * Create a new TAsyncSignalHandler. + */ + TAsyncSignalHandler(TEventBase* eventBase); + virtual ~TAsyncSignalHandler(); + + /** + * Register to receive callbacks about the specified signal. + * + * Once the handler has been registered for a particular signal, + * signalReceived() will be called each time this thread receives this + * signal. + * + * Throws a TException if an error occurs, or if this handler is already + * registered for this signal. + */ + void registerSignalHandler(int signum); + + /** + * Unregister for callbacks about the specified signal. + * + * Throws a TException if an error occurs, or if this signal was not + * registered. + */ + void unregisterSignalHandler(int signum); + + /** + * signalReceived() will called to indicate that the specified signal has + * been received. + * + * signalReceived() will always be invoked from the TEventBase loop (i.e., + * after the main POSIX signal handler has returned control to the TEventBase + * thread). + */ + virtual void signalReceived(int signum) THRIFT_NOEXCEPT = 0; + + private: + typedef std::map SignalEventMap; + + // Forbidden copy constructor and assignment operator + TAsyncSignalHandler(TAsyncSignalHandler const &); + TAsyncSignalHandler& operator=(TAsyncSignalHandler const &); + + static void libeventCallback(int signum, short events, void* arg); + + TEventBase* eventBase_; + SignalEventMap signalEvents_; +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TASYNCSIGNALHANDLER_H_ diff --git a/thrift/lib/cpp/async/TAsyncSocket.h b/thrift/lib/cpp/async/TAsyncSocket.h new file mode 100644 index 00000000..eb25fcd3 --- /dev/null +++ b/thrift/lib/cpp/async/TAsyncSocket.h @@ -0,0 +1,619 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TASYNCSOCKET_H_ +#define THRIFT_ASYNC_TASYNCSOCKET_H_ 1 + +#include +#include +#include "thrift/lib/cpp/async/TAsyncTimeout.h" +#include "thrift/lib/cpp/async/TAsyncTransport.h" +#include "thrift/lib/cpp/async/TDelayedDestruction.h" +#include "thrift/lib/cpp/async/TEventHandler.h" + +#include +#include + +namespace apache { namespace thrift { namespace async { + +/** + * A class for performing asynchronous I/O on a socket. + * + * TAsyncSocket allows users to asynchronously wait for data on a socket, and + * to asynchronously send data. + * + * The APIs for reading and writing are intentionally asymmetric. Waiting for + * data to read is a persistent API: a callback is installed, and is notified + * whenever new data is available. It continues to be notified of new events + * until it is uninstalled. + * + * TAsyncSocket does not provide read timeout functionality, because it + * typically cannot determine when the timeout should be active. Generally, a + * timeout should only be enabled when processing is blocked waiting on data + * from the remote endpoint. For server sockets, the timeout should not be + * active if the server is currently processing one or more outstanding + * requests for this socket. For client sockets, the timeout should not be + * active if there are no requests pending on the socket. Additionally, if a + * client has multiple pending requests, it will ususally want a separate + * timeout for each request, rather than a single read timeout. + * + * The write API is fairly intuitive: a user can request to send a block of + * data, and a callback will be informed once the entire block has been + * transferred to the kernel, or on error. TAsyncSocket does provide a send + * timeout, since most callers want to give up if the remote end stops + * responding and no further progress can be made sending the data. + */ +class TAsyncSocket : public TAsyncTransport, + public TDelayedDestruction { + public: +#if THRIFT_HAVE_UNIQUE_PTR + typedef std::unique_ptr UniquePtr; +#endif + + class ConnectCallback { + public: + virtual ~ConnectCallback() {} + + /** + * connectSuccess() will be invoked when the connection has been + * successfully established. + */ + virtual void connectSuccess() THRIFT_NOEXCEPT = 0; + + /** + * connectError() will be invoked if the connection attempt fails. + * + * @param ex An exception describing the error that occurred. + */ + virtual void connectError(const transport::TTransportException& ex) + THRIFT_NOEXCEPT = 0; + }; + + /** + * Create a new unconnected TAsyncSocket. + * + * connect() must later be called on this socket to establish a connection. + */ + explicit TAsyncSocket(TEventBase* evb); + + /** + * Create a new TAsyncSocket and begin the connection process. + * + * @param evb EventBase that will manage this socket. + * @param address The address to connect to. + * @param connectTimeout Optional timeout in milliseconds for the connection + * attempt. + */ + TAsyncSocket(TEventBase* evb, + const transport::TSocketAddress& address, + uint32_t connectTimeout = 0); + + /** + * Create a new TAsyncSocket and begin the connection process. + * + * @param evb EventBase that will manage this socket. + * @param ip IP address to connect to (dotted-quad). + * @param port Destination port in host byte order. + * @param connectTimeout Optional timeout in milliseconds for the connection + * attempt. + */ + TAsyncSocket(TEventBase* evb, + const std::string& ip, + uint16_t port, + uint32_t connectTimeout = 0); + + /** + * Create a TAsyncSocket from an already connected socket file descriptor. + * + * Note that while TAsyncSocket enables TCP_NODELAY for sockets it creates + * when connecting, it does not change the socket options when given an + * existing file descriptor. If callers want TCP_NODELAY enabled when using + * this version of the constructor, they need to explicitly call + * setNoDelay(true) after the constructor returns. + * + * @param evb EventBase that will manage this socket. + * @param fd File descriptor to take over (should be a connected socket). + */ + TAsyncSocket(TEventBase* evb, int fd); + + /** + * Helper function to create a shared_ptr. + * + * This passes in the correct destructor object, since TAsyncSocket's + * destructor is protected and cannot be invoked directly. + */ + static boost::shared_ptr newSocket(TEventBase* evb) { + return boost::shared_ptr(new TAsyncSocket(evb), + Destructor()); + } + + /** + * Helper function to create a shared_ptr. + */ + static boost::shared_ptr newSocket( + TEventBase* evb, + const transport::TSocketAddress& address, + uint32_t connectTimeout = 0) { + return boost::shared_ptr( + new TAsyncSocket(evb, address, connectTimeout), + Destructor()); + } + + /** + * Helper function to create a shared_ptr. + */ + static boost::shared_ptr newSocket( + TEventBase* evb, + const std::string& ip, + uint16_t port, + uint32_t connectTimeout = 0) { + return boost::shared_ptr( + new TAsyncSocket(evb, ip, port, connectTimeout), + Destructor()); + } + + /** + * Helper function to create a shared_ptr. + */ + static boost::shared_ptr newSocket(TEventBase* evb, int fd) { + return boost::shared_ptr(new TAsyncSocket(evb, fd), + Destructor()); + } + + /** + * Destroy the socket. + * + * TAsyncSocket::destroy() must be called to destroy the socket. + * The normal destructor is private, and should not be invoked directly. + * This prevents callers from deleting a TAsyncSocket while it is invoking a + * callback. + */ + virtual void destroy(); + + /** + * Get the TEventBase used by this socket. + */ + virtual TEventBase* getEventBase() const { + return eventBase_; + } + + /** + * Get the file descriptor used by the TAsyncSocket. + */ + int getFd() const { + return fd_; + } + + /** + * Extract the file descriptor from the TAsyncSocket. + * + * This will immediately cause any installed callbacks to be invoked with an + * error. The TAsyncSocket may no longer be used after the file descriptor + * has been extracted. + * + * Returns the file descriptor. The caller assumes ownership of the + * descriptor, and it will not be closed when the TAsyncSocket is destroyed. + */ + int detachFd(); + + /** + * Class that consists of the input parameters for setsockopt(). + * + * The memory referenced by optval should be valid throughout the + * life cycle of the SocketOption object. + */ + class SocketOption { + public: + SocketOption(): level_(0), optname_(0), optval_(NULL), size_(0) {} + + template + SocketOption(int level, int optname, const T* optval): + level_(level), optname_(optname), optval_(optval), size_(sizeof(T)) {} + + int apply(int fd) const { + return setsockopt(fd, level_, optname_, optval_, size_); + } + + protected: + int level_; + int optname_; + const void *optval_; + size_t size_; + }; + + typedef std::list OptionList; + + static OptionList emptyOptionList; + + /** + * Initiate a connection. + * + * @param callback The callback to inform when the connection attempt + * completes. + * @param address The address to connect to. + * @param timeout A timeout value, in milliseconds. If the connection + * does not succeed within this period, + * callback->connectError() will be invoked. + */ + virtual void connect(ConnectCallback* callback, + const transport::TSocketAddress& address, + int timeout = 0, + const OptionList &options = emptyOptionList) THRIFT_NOEXCEPT; + void connect(ConnectCallback* callback, const std::string& ip, uint16_t port, + int timeout = 00, + const OptionList &options = emptyOptionList) THRIFT_NOEXCEPT; + + /** + * Set the send timeout. + * + * If write requests do not make any progress for more than the specified + * number of milliseconds, fail all pending writes and close the socket. + * + * If write requests are currently pending when setSendTimeout() is called, + * the timeout interval is immediately restarted using the new value. + * + * (See the comments for TAsyncSocket for an explanation of why TAsyncSocket + * provides setSendTimeout() but not setRecvTimeout().) + * + * @param milliseconds The timeout duration, in milliseconds. If 0, no + * timeout will be used. + */ + void setSendTimeout(uint32_t milliseconds); + + /** + * Get the send timeout. + * + * @return Returns the current send timeout, in milliseconds. A return value + * of 0 indicates that no timeout is set. + */ + uint32_t getSendTimeout() const { + return sendTimeout_; + } + + /** + * Set the maximum number of reads to execute from the underlying + * socket each time the TEventBase detects that new ingress data is + * available. The default is unlimited, but callers can use this method + * to limit the amount of data read from the socket per event loop + * iteration. + * + * @param maxReads Maximum number of reads per data-available event; + * a value of zero means unlimited. + */ + void setMaxReadsPerEvent(uint16_t maxReads) { + maxReadsPerEvent_ = maxReads; + } + + /** + * Get the maximum number of reads this object will execute from + * the underlying socket each time the TEventBase detects that new + * ingress data is available. + * + * @returns Maximum number of reads per data-available event; a value + * of zero means unlimited. + */ + uint16_t getMaxReadsPerEvent() const { + return maxReadsPerEvent_; + } + + // Methods inherited from TAsyncTransport + // See the documentation in TAsyncTransport.h + virtual void setReadCallback(ReadCallback* callback); + virtual ReadCallback* getReadCallback() const; + + virtual void write(WriteCallback* callback, const void* buf, size_t bytes); + virtual void writev(WriteCallback* callback, const iovec* vec, size_t count); + virtual void writeChain(WriteCallback* callback, + std::unique_ptr&& buf, + bool cork = false); + + virtual void close(); + virtual void closeNow(); + virtual void closeWithReset(); + virtual void shutdownWrite(); + virtual void shutdownWriteNow(); + + virtual bool readable() const; + virtual bool good() const; + virtual bool error() const; + virtual void attachEventBase(TEventBase* eventBase); + virtual void detachEventBase(); + + virtual void getLocalAddress(transport::TSocketAddress* address) const; + virtual void getPeerAddress(transport::TSocketAddress* address) const; + + virtual bool connecting() const { + return (state_ == STATE_CONNECTING); + } + + // Methods controlling socket options + + /** + * Force writes to be transmitted immediately. + * + * This controls the TCP_NODELAY socket option. When enabled, TCP segments + * are sent as soon as possible, even if it is not a full frame of data. + * When disabled, the data may be buffered briefly to try and wait for a full + * frame of data. + * + * By default, TCP_NODELAY is enabled for TAsyncSocket objects. + * + * This method will fail if the socket is not currently open. + * + * @return Returns 0 if the TCP_NODELAY flag was successfully updated, + * or a non-zero errno value on error. + */ + int setNoDelay(bool noDelay); + + /* + * Set the Flavor of Congestion Control to be used for this Socket + * Please check '/lib/modules//kernel/net/ipv4' for tcp_*.ko + * first to make sure the module is available for plugging in + * Alternatively you can choose from net.ipv4.tcp_allowed_congestion_control + */ + int setCongestionFlavor(const std::string &cname); + + /* + * Forces ACKs to be sent immediately + * + * @return Returns 0 if the TCP_QUICKACK flag was successfully updated, + * or a non-zero errno value on error. + */ + int setQuickAck(bool quickack); + + /** + * Set the send bufsize + */ + int setSendBufSize(size_t bufsize); + + /** + * Set the recv bufsize + */ + int setRecvBufSize(size_t bufsize); + + /** + * Generic API for reading a socket option. + * + * @param level same as the "level" parameter in getsockopt(). + * @param optname same as the "optname" parameter in getsockopt(). + * @param optval pointer to the variable in which the option value should + * be returned. + * @return same as the return value of getsockopt(). + */ + template + int getSockOpt(int level, int optname, T *optval) { + return getsockopt(fd_, level, optname, optval, sizeof(T)); + } + + /** + * Generic API for setting a socket option. + * + * @param level same as the "level" parameter in getsockopt(). + * @param optname same as the "optname" parameter in getsockopt(). + * @param optval the option value to set. + * @return same as the return value of setsockopt(). + */ + template + int setSockOpt(int level, int optname, const T *optval) { + return setsockopt(fd_, level, optname, optval, sizeof(T)); + } + + protected: + enum ReadResultEnum { + READ_EOF = 0, + READ_ERROR = -1, + READ_BLOCKING = -2, + }; + + /** + * Protected destructor. + * + * Users of TAsyncSocket must never delete it directly. Instead, invoke + * destroy() instead. (See the documentation in TDelayedDestruction.h for + * more details.) + */ + ~TAsyncSocket(); + + enum StateEnum { + STATE_UNINIT, + STATE_CONNECTING, + STATE_ESTABLISHED, + STATE_CLOSED, + STATE_ERROR + }; + enum ShutdownFlags { + /// shutdownWrite() called, but we are still waiting on writes to drain + SHUT_WRITE_PENDING = 0x01, + /// writes have been completely shut down + SHUT_WRITE = 0x02, + /** + * Reads have been shutdown. + * + * At the moment we don't distinguish between remote read shutdown + * (received EOF from the remote end) and local read shutdown. We can + * only receive EOF when a read callback is set, and we immediately inform + * it of the EOF. Therefore there doesn't seem to be any reason to have a + * separate state of "received EOF but the local side may still want to + * read". + * + * We also don't currently provide any API for only shutting down the read + * side of a socket. (This is a no-op as far as TCP is concerned, anyway.) + */ + SHUT_READ = 0x04, + }; + + class WriteRequest; + + class WriteTimeout : public TAsyncTimeout { + public: + WriteTimeout(TAsyncSocket* socket, TEventBase* eventBase) + : TAsyncTimeout(eventBase) + , socket_(socket) {} + + virtual void timeoutExpired() THRIFT_NOEXCEPT { + socket_->timeoutExpired(); + } + + private: + TAsyncSocket* socket_; + }; + + class IoHandler : public TEventHandler { + public: + IoHandler(TAsyncSocket* socket, TEventBase* eventBase) + : TEventHandler(eventBase, -1) + , socket_(socket) {} + IoHandler(TAsyncSocket* socket, TEventBase* eventBase, int fd) + : TEventHandler(eventBase, fd) + , socket_(socket) {} + + virtual void handlerReady(uint16_t events) THRIFT_NOEXCEPT { + socket_->ioReady(events); + } + + private: + TAsyncSocket* socket_; + }; + + void init(); + + // event notification methods + void ioReady(uint16_t events) THRIFT_NOEXCEPT; + virtual void checkForImmediateRead() THRIFT_NOEXCEPT; + virtual void handleInitialReadWrite() THRIFT_NOEXCEPT; + virtual void handleRead() THRIFT_NOEXCEPT; + virtual void handleWrite() THRIFT_NOEXCEPT; + virtual void handleConnect() THRIFT_NOEXCEPT; + void timeoutExpired() THRIFT_NOEXCEPT; + + /** + * Attempt to read from the socket. + * + * @param buf The buffer to read data into. + * @param buflen The length of the buffer. + * + * @return Returns the number of bytes read, or READ_EOF on EOF, or + * READ_ERROR on error, or READ_BLOCKING if the operation will + * block. + */ + virtual ssize_t performRead(void* buf, size_t buflen); + + /** + * Populate an iovec array from an IOBuf and attempt to write it. + * + * @param callback Write completion/error callback. + * @param vec Target iovec array; caller retains ownership. + * @param count Number of IOBufs to write, beginning at start of buf. + * @param buf Chain of iovecs. + * @param cork Whether to delay the output until a subsequent + * non-corked write. + */ + void writeChainImpl(WriteCallback* callback, iovec* vec, + size_t count, std::unique_ptr&& buf, bool cork); + + /** + * Write as much data as possible to the socket without blocking, + * and queue up any leftover data to send when the socket can + * handle writes again. + * + * @param callback The callback to invoke when the write is completed. + * @param vec Array of buffers to write; this method will make a + * copy of the vector (but not the buffers themselves) + * if the write has to be completed asynchronously. + * @param count Number of elements in vec. + * @param buf The IOBuf that manages the buffers referenced by + * vec, or a pointer to NULL if the buffers are not + * associated with an IOBuf. Note that ownership of + * the IOBuf is transferred here; upon completion of + * the write, the TAsyncSocket deletes the IOBuf. + * @param cork Whether to delay the write until the next non-corked + * write operation. (Note: may not be supported in all + * subclasses or on all platforms.) + */ + void writeImpl(WriteCallback* callback, const iovec* vec, size_t count, + std::unique_ptr&& buf, bool cork = false); + + /** + * Attempt to write to the socket. + * + * @param vec The iovec array pointing to the buffers to write. + * @param count The length of the iovec array. + * @param haveMore This flag is inherited from TAsyncSocket but is + * not handled here. + * @param countWritten On return, the value pointed to by this parameter + * will contain the number of iovec entries that were + * fully written. + * @param partialWritten On return, the value pointed to by this parameter + * will contain the number of bytes written in the + * partially written iovec entry. + * + * @return Returns the total number of bytes written, or -1 on error. If no + * data can be written immediately, 0 is returned. + */ + virtual ssize_t performWrite(const iovec* vec, uint32_t count, + bool haveMore, uint32_t* countWritten, + uint32_t* partialWritten); + + bool updateEventRegistration(); + + /** + * Update event registration. + * + * @param enable Flags of events to enable. Set it to 0 if no events + * need to be enabled in this call. + * @param disable Flags of events + * to disable. Set it to 0 if no events need to be disabled in this + * call. + * + * @return true iff the update is successful. + */ + bool updateEventRegistration(uint16_t enable, uint16_t disable); + + // error handling methods + void startFail(); + void finishFail(); + void fail(const char* fn, const transport::TTransportException& ex); + void failConnect(const char* fn, const transport::TTransportException& ex); + void failRead(const char* fn, const transport::TTransportException& ex); + void failWrite(const char* fn, WriteCallback* callback, size_t bytesWritten, + const transport::TTransportException& ex); + void failWrite(const char* fn, const transport::TTransportException& ex); + void failAllWrites(const transport::TTransportException& ex); + void invalidState(ConnectCallback* callback); + void invalidState(ReadCallback* callback); + void invalidState(WriteCallback* callback); + + uint8_t state_; ///< StateEnum describing current state + uint8_t shutdownFlags_; ///< Shutdown state (ShutdownFlags) + uint16_t eventFlags_; ///< TEventBase::HandlerFlags settings + int fd_; ///< The socket file descriptor + uint32_t sendTimeout_; ///< The send timeout, in milliseconds + uint16_t maxReadsPerEvent_; ///< Max reads per event loop iteration + TEventBase* eventBase_; ///< The TEventBase + WriteTimeout writeTimeout_; ///< A timeout for connect and write + IoHandler ioHandler_; ///< A TEventHandler to monitor the fd + + ConnectCallback* connectCallback_; ///< ConnectCallback + ReadCallback* readCallback_; ///< ReadCallback + WriteRequest* writeReqHead_; ///< Chain of WriteRequests + WriteRequest* writeReqTail_; ///< End of WriteRequest chain +}; + +}}} // apache::thrift::async + +#endif // #ifndef THRIFT_ASYNC_TASYNCSOCKET_H_ diff --git a/thrift/lib/cpp/async/TAsyncTimeout.h b/thrift/lib/cpp/async/TAsyncTimeout.h new file mode 100644 index 00000000..410754c0 --- /dev/null +++ b/thrift/lib/cpp/async/TAsyncTimeout.h @@ -0,0 +1,153 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TASYNCTIMEOUT_H_ +#define THRIFT_ASYNC_TASYNCTIMEOUT_H_ 1 + +#include "thrift/lib/cpp/thrift_config.h" +#include "thrift/lib/cpp/async/TEventUtil.h" +#include + +namespace apache { namespace thrift { namespace async { + +class TEventBase; + +/** + * TAsyncTimeout is used to asynchronously wait for a timeout to occur. + */ +class TAsyncTimeout : private boost::noncopyable { + public: + enum InternalEnum { + INTERNAL, + NORMAL + }; + + /** + * Create a new TAsyncTimeout object, driven by the specified TEventBase. + */ + explicit TAsyncTimeout(TEventBase* eventBase); + + /** + * Create a new internal TAsyncTimeout object. + * + * Internal timeouts are like regular timeouts, but will not stop the + * TEventBase loop from exiting if the only remaining events are internal + * timeouts. + * + * This is useful for implementing fallback timeouts to abort the TEventBase + * loop if the other events have not been processed within a specified time + * period: if the event loop takes too long the timeout will fire and can + * stop the event loop. However, if all other events complete, the event + * loop will exit even though the internal timeout is still installed. + */ + TAsyncTimeout(TEventBase* eventBase, InternalEnum internal); + + /** + * Create a new TAsyncTimeout object, not yet assigned to a TEventBase. + * + * attachEventBase() must be called prior to scheduling the timeout. + */ + TAsyncTimeout(); + + /** + * TAsyncTimeout destructor. + * + * The timeout will be automatically cancelled if it is running. + */ + virtual ~TAsyncTimeout(); + + /** + * timeoutExpired() is invoked when the timeout period has expired. + */ + virtual void timeoutExpired() THRIFT_NOEXCEPT = 0; + + /** + * Schedule the timeout to fire in the specified number of milliseconds. + * + * After the specified number of milliseconds has elapsed, timeoutExpired() + * will be invoked by the TEventBase's main loop. + * + * If the timeout is already running, it will be rescheduled with the + * new timeout value. + * + * @param milliseconds The timeout duration, in milliseconds. + * + * @return Returns true if the timeout was successfully scheduled, + * and false if an error occurred. After an error, the timeout is + * always unscheduled, even if scheduleTimeout() was just + * rescheduling an existing timeout. + */ + bool scheduleTimeout(uint32_t milliseconds); + + /** + * Cancel the timeout, if it is running. + */ + void cancelTimeout(); + + /** + * Returns true if the timeout is currently scheduled. + */ + bool isScheduled() { + return TEventUtil::isEventRegistered(&event_); + } + + /** + * Attach the timeout to a TEventBase. + * + * This may only be called if the timeout is not currently attached to a + * TEventBase (either by using the default constructor, or by calling + * detachEventBase()). + * + * This method must be invoked in the TEventBase's thread. + * + * The internal parameter specifies if this timeout should be treated as an + * internal event. TEventBase::loop() will return when there are no more + * non-internal events remaining. + */ + void attachEventBase(TEventBase* eventBase, + InternalEnum internal = NORMAL); + + /** + * Detach the timeout from its TEventBase. + * + * This may only be called when the timeout is not running. + * Once detached, the timeout may not be scheduled again until it is + * re-attached to a TEventBase by calling attachEventBase(). + * + * This method must be called from the current TEventBase's thread. + */ + void detachEventBase(); + + private: + static void libeventCallback(int fd, short events, void* arg); + + struct event event_; + + /* + * In debug builds, store a pointer to the TEventBase. We only use this + * for some assert() statements, to make sure that TAsyncTimeout is always + * used from the correct thread. + */ +#ifndef NDEBUG + TEventBase* eventBase_; +#endif +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TASYNCTIMEOUT_H_ diff --git a/thrift/lib/cpp/async/TAsyncTimeoutSet.h b/thrift/lib/cpp/async/TAsyncTimeoutSet.h new file mode 100644 index 00000000..df5962ba --- /dev/null +++ b/thrift/lib/cpp/async/TAsyncTimeoutSet.h @@ -0,0 +1,198 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TASYNCTIMEOUTSET_H_ +#define THRIFT_ASYNC_TASYNCTIMEOUTSET_H_ 1 + +#include "thrift/lib/cpp/async/TAsyncTimeout.h" +#include "thrift/lib/cpp/async/TDelayedDestruction.h" + +#include +#include +#include + +namespace apache { namespace thrift { namespace async { + +/** + * TAsyncTimeoutSet exists for efficiently managing a group of timeouts events + * that always have the same timeout interval. + * + * TAsyncTimeoutSet takes advantage of the fact that the timeouts are always + * scheduled in sorted order. (Since each timeout has the same interval, when + * a new timeout is scheduled it will always be the last timeout in the set.) + * This avoids the need to perform any additional sorting of the timeouts + * within a single TAsyncTimeoutSet. + * + * TAsyncTimeoutSet is useful whenever you have a large group of objects that + * each need their own timeout, but with the same interval for each object. + * For example, managing idle timeouts for thousands of connection, or + * scheduling health checks for a large group of servers. + */ +class TAsyncTimeoutSet : private TAsyncTimeout, public TDelayedDestruction { + public: + typedef std::unique_ptr UniquePtr; + + /** + * A callback to be notified when a timeout has expired. + * + * TAsyncTimeoutSet::Callback is very similar to TAsyncTimeout. The primary + * distinction is that TAsyncTimeout can choose its timeout interval each + * time it is scheduled. On the other hand, TAsyncTimeoutSet::Callback + * always uses the timeout interval defined by the TAsyncTimeoutSet where it + * is scheduled. + */ + class Callback { + public: + Callback() + : timeoutSet_(NULL), + expiration_(0), + prev_(NULL), + next_(NULL) {} + + virtual ~Callback(); + + /** + * timeoutExpired() is invoked when the timeout has expired. + */ + virtual void timeoutExpired() THRIFT_NOEXCEPT = 0; + + /** + * Cancel the timeout, if it is running. + * + * If the timeout is not scheduled, cancelTimeout() does nothing. + */ + void cancelTimeout() { + if (timeoutSet_ == NULL) { + // We're not scheduled, so there's nothing to do. + return; + } + cancelTimeoutImpl(); + } + + /** + * Return true if this timeout is currently scheduled, and false otherwise. + */ + bool isScheduled() const { + return timeoutSet_ != NULL; + } + + private: + // Get the time remaining until this timeout expires + std::chrono::milliseconds getTimeRemaining( + std::chrono::milliseconds now) const { + if (now >= expiration_) { + return std::chrono::milliseconds(0); + } + return expiration_ - now; + } + + void setScheduled(TAsyncTimeoutSet* timeoutSet, Callback* prev); + void cancelTimeoutImpl(); + + TAsyncTimeoutSet* timeoutSet_; + std::chrono::milliseconds expiration_; + Callback* prev_; + Callback* next_; + + // Give TAsyncTimeoutSet direct access to our members so it can take care + // of scheduling/cancelling. + friend class TAsyncTimeoutSet; + }; + + /** + * Create a new TAsyncTimeoutSet with the specified interval. + */ + TAsyncTimeoutSet(TEventBase* eventBase, + std::chrono::milliseconds intervalMS, + std::chrono::milliseconds atMostEveryN = + std::chrono::milliseconds(0)); + + /** + * Destroy the TAsyncTimeoutSet. + * + * Normally a TAsyncTimeoutSet should only be destroyed when there are no + * more callbacks pending in the set. If there are timeout callbacks pending + * for this set, destroying the TAsyncTimeoutSet will automatically cancel + * them. If you destroy a TAsyncTimeoutSet with callbacks pending, your + * callback code needs to be aware that the callbacks will never be invoked. + */ + virtual void destroy(); + + /** + * Get the interval for this TAsyncTimeoutSet. + * + * Returns the timeout interval in milliseconds. All callbacks scheduled + * with scheduleTimeout() will be invoked after this amount of time has + * passed since the call to scheduleTimeout(). + */ + std::chrono::milliseconds getInterval() const { + return interval_; + } + + /** + * Schedule the specified Callback to be invoked after the TAsyncTimeoutSet's + * specified timeout interval. + * + * If the callback is already scheduled, this cancels the existing timeout + * before scheduling the new timeout. + */ + void scheduleTimeout(Callback* callback); + + /** + * Limit how frequently this TAsyncTimeoutSet will fire. + */ + void fireAtMostEvery(const std::chrono::milliseconds& ms) { + atMostEveryN_ = ms; + } + + /** + * Get a pointer to the next Callback scheduled to be invoked (may be null). + */ + Callback* front() { return head_; } + const Callback* front() const { return head_; } + + protected: + /** + * Protected destructor. + * + * Use destroy() instead. See the comments in TDelayedDestruction for more + * details. + */ + virtual ~TAsyncTimeoutSet(); + + private: + // Forbidden copy constructor and assignment operator + TAsyncTimeoutSet(TAsyncTimeoutSet const &) = delete; + TAsyncTimeoutSet& operator=(TAsyncTimeoutSet const &) = delete; + + // Private methods to be invoked by TAsyncTimeoutSet::Callback + void headChanged(); + + // Methods inherited from TAsyncTimeout + virtual void timeoutExpired() THRIFT_NOEXCEPT; + + std::chrono::milliseconds interval_; + std::chrono::milliseconds atMostEveryN_; + bool inTimeoutExpired_; + Callback* head_; + Callback* tail_; +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TASYNCTIMEOUTSET_H_ diff --git a/thrift/lib/cpp/async/TAsyncTransport.h b/thrift/lib/cpp/async/TAsyncTransport.h new file mode 100644 index 00000000..b37bc403 --- /dev/null +++ b/thrift/lib/cpp/async/TAsyncTransport.h @@ -0,0 +1,445 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TASYNCTRANSPORT_H_ +#define THRIFT_ASYNC_TASYNCTRANSPORT_H_ 1 + +#include "thrift/lib/cpp/thrift_config.h" +#include +#include +#include + +namespace folly { +class IOBuf; +} + +namespace apache { namespace thrift { + +namespace transport { +class TSocketAddress; +class TTransportException; +} + +namespace async { + +class TEventBase; + +/** + * TAsyncTransport defines an asynchronous API for streaming I/O. + * + * This class provides an API to for asynchronously waiting for data + * on a streaming transport, and for asynchronously sending data. + * + * The APIs for reading and writing are intentionally asymmetric. Waiting for + * data to read is a persistent API: a callback is installed, and is notified + * whenever new data is available. It continues to be notified of new events + * until it is uninstalled. + * + * TAsyncTransport does not provide read timeout functionality, because it + * typically cannot determine when the timeout should be active. Generally, a + * timeout should only be enabled when processing is blocked waiting on data + * from the remote endpoint. For server-side applications, the timeout should + * not be active if the server is currently processing one or more outstanding + * requests on this transport. For client-side applications, the timeout + * should not be active if there are no requests pending on the transport. + * Additionally, if a client has multiple pending requests, it will ususally + * want a separate timeout for each request, rather than a single read timeout. + * + * The write API is fairly intuitive: a user can request to send a block of + * data, and a callback will be informed once the entire block has been + * transferred to the kernel, or on error. TAsyncTransport does provide a send + * timeout, since most callers want to give up if the remote end stops + * responding and no further progress can be made sending the data. + */ +class TAsyncTransport { + public: + class ReadCallback { + public: + virtual ~ReadCallback() {} + + /** + * When data becomes available, getReadBuffer() will be invoked to get the + * buffer into which data should be read. + * + * This method allows the ReadCallback to delay buffer allocation until + * data becomes available. This allows applications to manage large + * numbers of idle connections, without having to maintain a separate read + * buffer for each idle connection. + * + * It is possible that in some cases, getReadBuffer() may be called + * multiple times before readDataAvailable() is invoked. In this case, the + * data will be written to the buffer returned from the most recent call to + * readDataAvailable(). If the previous calls to readDataAvailable() + * returned different buffers, the ReadCallback is responsible for ensuring + * that they are not leaked. + * + * If getReadBuffer() throws an exception, returns a NULL buffer, or + * returns a 0 length, the ReadCallback will be uninstalled and its + * readError() method will be invoked. + * + * getReadBuffer() is not allowed to change the transport state before it + * returns. (For example, it should never uninstall the read callback, or + * set a different read callback.) + * + * @param bufReturn getReadBuffer() should update *bufReturn to contain the + * address of the read buffer. This parameter will never + * be NULL. + * @param lenReturn getReadBuffer() should update *lenReturn to contain the + * maximum number of bytes that may be written to the read + * buffer. This parameter will never be NULL. + */ + virtual void getReadBuffer(void** bufReturn, size_t* lenReturn) = 0; + + /** + * readDataAvailable() will be invoked when data has been successfully read + * into the buffer returned by the last call to getReadBuffer(). + * + * The read callback remains installed after readDataAvailable() returns. + * It must be explicitly uninstalled to stop receiving read events. + * getReadBuffer() will be called at least once before each call to + * readDataAvailable(). getReadBuffer() will also be called before any + * call to readEOF(). + * + * @param len The number of bytes placed in the buffer. + */ + virtual void readDataAvailable(size_t len) THRIFT_NOEXCEPT = 0; + + /** + * readEOF() will be invoked when the transport is closed. + * + * The read callback will be automatically uninstalled immediately before + * readEOF() is invoked. + */ + virtual void readEOF() THRIFT_NOEXCEPT = 0; + + /** + * readError() will be invoked if an error occurs reading from the + * transport. + * + * The read callback will be automatically uninstalled immediately before + * readError() is invoked. + * + * @param ex An exception describing the error that occurred. + */ + virtual void readError(const transport::TTransportException& ex) + THRIFT_NOEXCEPT = 0; + }; + + class WriteCallback { + public: + virtual ~WriteCallback() {} + + /** + * writeSuccess() will be invoked when all of the data has been + * successfully written. + * + * Note that this mainly signals that the buffer containing the data to + * write is no longer needed and may be freed or re-used. It does not + * guarantee that the data has been fully transmitted to the remote + * endpoint. For example, on socket-based transports, writeSuccess() only + * indicates that the data has been given to the kernel for eventual + * transmission. + */ + virtual void writeSuccess() THRIFT_NOEXCEPT = 0; + + /** + * writeError() will be invoked if an error occurs writing the data. + * + * @param bytesWritten The number of bytes that were successfull + * @param ex An exception describing the error that occurred. + */ + virtual void writeError(size_t bytesWritten, + const transport::TTransportException& ex) + THRIFT_NOEXCEPT = 0; + }; + + virtual ~TAsyncTransport() {} + + /** + * Set the read callback. + * + * See the documentation for ReadCallback above for a description of how the + * callback will be invoked. Note that the callback remains installed until + * it is explicitly uninstalled, or until an error occurs. + * + * If a ReadCallback is already installed, it is replaced with the new + * callback. + * + * Note that setReadCallback() may invoke the ReadCallback immediately, + * before returning. + * + * @param callback The callback to invoke when data is available. + * This parameter may be NULL to uninstall the current + * read callback. + */ + virtual void setReadCallback(ReadCallback* callback) = 0; + + /** + * Get the currently installed read callback. + * + * @return Returns a pointer to the installed ReadCallback, or NULL if no + * ReadCallback is installed. + */ + virtual ReadCallback* getReadCallback() const = 0; + + /** + * Write data to the transport. + * + * write() will always return immediately. The WriteCallback will later be + * invoked from the main TEventBase loop when the write has completed. + * + * Additional write attempts may be started before the first write completes. + * The subsequent write requests will be queued, and processed in the order + * in which they were called. + * + * @param callback The callback to invoke when the data has been written. + * The callback may not be NULL. + * @param buf The buffer containing the data to write. The caller is + * responsible for ensuring that this buffer remains valid + * until the callback is invoked. This parameter may not + * be NULL. + * @param bytes The number of bytes to write. + */ + virtual void write(WriteCallback* callback, + const void* buf, size_t bytes) = 0; + + /** + * Write non-contiguous data to the transport. + * + * writev() will always return immediately. The WriteCallback will later be + * invoked from the main TEventBase loop when the write has completed. + * + * Additional write attempts may be started before the first write completes. + * The subsequent write requests will be queued, and processed in the order + * in which they were called. + * + * @param callback The callback to invoke when the data has been written. + * The callback may not be NULL. + * @param vec A pointer to an array of iovec objects. The caller is + * responsible for ensuring that the buffers remain valid + * until the callback is invoked. This parameter may not + * be NULL. + * @param count The number of iovec objects in the vec array. + */ + virtual void writev(WriteCallback* callback, + const iovec* vec, size_t count) = 0; + + /** + * Write a chain of IOBufs to the transport. + * + * writeChain() will always return immediately. The WriteCallback will + * later be invoked from the main TEventBase loop when the write has + * completed. + * + * Additional write attempts may be started before the first write completes. + * The subsequent write requests will be queued, and processed in the order + * in which they were called. + * + * @param callback The callback to invoke when the data has been written. + * The callback may not be NULL. + * @param iob The head of an IOBuf chain. The TAsyncTransport + * will take ownership of this chain and delete it + * after writing. + * @param cork Whether to delay the write until the next non-corked + * write operation. (Note: may not be supported in all + * subclasses or on all platforms.) + */ + virtual void writeChain(WriteCallback* callback, + std::unique_ptr&& iob, + bool cork = false) = 0; + + /** + * Close the transport. + * + * This gracefully closes the transport, waiting for all pending write + * requests to complete before actually closing the underlying transport. + * + * If a read callback is set, readEOF() will be called immediately. If there + * are outstanding write requests, the close will be delayed until all + * remaining writes have completed. No new writes may be started after + * close() has been called. + */ + virtual void close() = 0; + + /** + * Close the transport immediately. + * + * This closes the transport immediately, dropping any outstanding data + * waiting to be written. + * + * If a read callback is set, readEOF() will be called immediately. + * If there are outstanding write requests, these requests will be aborted + * and writeError() will be invoked immediately on all outstanding write + * callbacks. + */ + virtual void closeNow() = 0; + + /** + * Reset the transport immediately. + * + * This closes the transport immediately, sending a reset to the remote peer + * if possible to indicate abnormal shutdown. + * + * Note that not all subclasses implement this reset functionality: some + * subclasses may treat reset() the same as closeNow(). Subclasses that use + * TCP transports should terminate the connection with a TCP reset. + */ + virtual void closeWithReset() { + closeNow(); + } + + /** + * Perform a half-shutdown of the write side of the transport. + * + * The caller should not make any more calls to write() or writev() after + * shutdownWrite() is called. Any future write attempts will fail + * immediately. + * + * Not all transport types support half-shutdown. If the underlying + * transport does not support half-shutdown, it will fully shutdown both the + * read and write sides of the transport. (Fully shutting down the socket is + * better than doing nothing at all, since the caller may rely on the + * shutdownWrite() call to notify the other end of the connection that no + * more data can be read.) + * + * If there is pending data still waiting to be written on the transport, + * the actual shutdown will be delayed until the pending data has been + * written. + * + * Note: There is no corresponding shutdownRead() equivalent. Simply + * uninstall the read callback if you wish to stop reading. (On TCP sockets + * at least, shutting down the read side of the socket is a no-op anyway.) + */ + virtual void shutdownWrite() = 0; + + /** + * Perform a half-shutdown of the write side of the transport. + * + * shutdownWriteNow() is identical to shutdownWrite(), except that it + * immediately performs the shutdown, rather than waiting for pending writes + * to complete. Any pending write requests will be immediately failed when + * shutdownWriteNow() is called. + */ + virtual void shutdownWriteNow() = 0; + + /** + * Determine if transport is open and ready to read or write. + * + * Note that this function returns false on EOF; you must also call error() + * to distinguish between an EOF and an error. + * + * @return true iff the transport is open and ready, false otherwise. + */ + virtual bool good() const = 0; + + /** + * Determine if the transport is readable or not. + * + * @return true iff the transport is readable, false otherwise. + */ + virtual bool readable() const = 0; + + /** + * Determine if transport is connected to the endpoint + * + * @return false iff the transport is connected, otherwise true + */ + virtual bool connecting() const = 0; + + /** + * Determine if an error has occurred with this transport. + * + * @return true iff an error has occurred (not EOF). + */ + virtual bool error() const = 0; + + /** + * Attach the transport to a TEventBase. + * + * This may only be called if the transport is not currently attached to a + * TEventBase (by an earlier call to detachEventBase()). + * + * This method must be invoked in the TEventBase's thread. + */ + virtual void attachEventBase(TEventBase* eventBase) = 0; + + /** + * Detach the transport from its TEventBase. + * + * This may only be called when the transport is idle and has no reads or + * writes pending. Once detached, the transport may not be used again until + * it is re-attached to a TEventBase by calling attachEventBase(). + * + * This method must be called from the current TEventBase's thread. + */ + virtual void detachEventBase() = 0; + + /** + * Get the TEventBase used by this transport. + * + * Returns NULL if this transport is not currently attached to a TEventBase. + */ + virtual TEventBase* getEventBase() const = 0; + + /** + * Set the send timeout. + * + * If write requests do not make any progress for more than the specified + * number of milliseconds, fail all pending writes and close the transport. + * + * If write requests are currently pending when setSendTimeout() is called, + * the timeout interval is immediately restarted using the new value. + * + * @param milliseconds The timeout duration, in milliseconds. If 0, no + * timeout will be used. + */ + virtual void setSendTimeout(uint32_t milliseconds) = 0; + + /** + * Get the send timeout. + * + * @return Returns the current send timeout, in milliseconds. A return value + * of 0 indicates that no timeout is set. + */ + virtual uint32_t getSendTimeout() const = 0; + + /** + * Get the address of the local endpoint of this transport. + * + * This function may throw TTransportException on error. + * + * @param address The local address will be stored in the specified + * TSocketAddress. + */ + virtual void getLocalAddress(transport::TSocketAddress* address) const = 0; + + /** + * Get the address of the remote endpoint to which this transport is + * connected. + * + * This function may throw TTransportException on error. + * + * @param address The remote endpoint's address will be stored in the + * specified TSocketAddress. + */ + virtual void getPeerAddress(transport::TSocketAddress* address) const = 0; +}; + +}}} // apache::thrift::async + +#endif // #ifndef THRIFT_ASYNC_TASYNCTRANSPORT_H_ diff --git a/thrift/lib/cpp/async/TBinaryAsyncChannel.h b/thrift/lib/cpp/async/TBinaryAsyncChannel.h new file mode 100644 index 00000000..2b8b2f5e --- /dev/null +++ b/thrift/lib/cpp/async/TBinaryAsyncChannel.h @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TBINARYASYNCCHANNEL_H_ +#define THRIFT_ASYNC_TBINARYASYNCCHANNEL_H_ 1 + +#include "thrift/lib/cpp/async/TUnframedAsyncChannel.h" + +namespace apache { namespace thrift { namespace async { + +namespace detail { + +/** + * A class to determine the end of a raw TBinaryProtocol message. + */ +class TBinaryACProtocolTraits { + public: + TBinaryACProtocolTraits() : strictRead_(true) {} + + // Methods required by TUnframedACReadState + bool getMessageLength(uint8_t* buffer, + uint32_t bufferLength, + uint32_t* messageLength); + + // Methods specific to TBinaryAsyncChannel + + void setStrictRead(bool strictRead) { + strictRead_ = strictRead; + } + bool getStrictRead() const { + return strictRead_; + } + + private: + bool strictRead_; +}; + +} // namespace detail + +/** + * TBinaryAsyncChannel + * + * This is a TAsyncChannel implementation that reads and writes raw (unframed) + * messages encoded using TBinaryProtocol. + */ +class TBinaryAsyncChannel : + public TUnframedAsyncChannel { + private: + typedef TUnframedAsyncChannel Parent; + + public: + TBinaryAsyncChannel(const boost::shared_ptr& transport) + : Parent(transport) {} + + /** + * Helper function to create a shared_ptr. + * + * This passes in the correct destructor object, since TBinaryAsyncChannel's + * destructor is protected and cannot be invoked directly. + */ + static boost::shared_ptr newChannel( + const boost::shared_ptr& transport) { + return boost::shared_ptr( + new TBinaryAsyncChannel(transport), Destructor()); + } + + // Note that we inherit setMaxMessageSize() and getMaxMessageSize() + // from TUnframedAsyncChannel. + + void setStrictRead(bool strictRead) { + readState_.getProtocolTraits()->setStrictRead(strictRead); + } + bool getStrictRead() const { + return readState_.getProtocolTraits()->getStrictRead(); + } + + protected: + /** + * Protected destructor. + * + * Users of TBinaryAsyncChannel must never delete it directly. Instead, + * invoke destroy(). + */ + virtual ~TBinaryAsyncChannel() { } +}; + +class TBinaryAsyncChannelFactory : public TStreamAsyncChannelFactory { + public: + TBinaryAsyncChannelFactory() + : maxMessageSize_(0x7fffffff) + , recvTimeout_(0) + , sendTimeout_(0) + , strictRead_(true) {} + + void setMaxMessageSize(uint32_t bytes) { + maxMessageSize_ = bytes; + } + + void setRecvTimeout(uint32_t milliseconds) { + recvTimeout_ = milliseconds; + } + + void setSendTimeout(uint32_t milliseconds) { + sendTimeout_ = milliseconds; + } + + void setStrictRead(bool strict) { + strictRead_ = strict; + } + + virtual boost::shared_ptr newChannel( + const boost::shared_ptr& transport) { + boost::shared_ptr channel( + TBinaryAsyncChannel::newChannel(transport)); + transport->setSendTimeout(sendTimeout_); + channel->setMaxMessageSize(maxMessageSize_); + channel->setRecvTimeout(recvTimeout_); + channel->setStrictRead(strictRead_); + return channel; + } + + private: + uint32_t maxMessageSize_; + uint32_t recvTimeout_; + uint32_t sendTimeout_; + bool strictRead_; +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TBINARYASYNCCHANNEL_H_ diff --git a/thrift/lib/cpp/async/TDelayedDestruction.h b/thrift/lib/cpp/async/TDelayedDestruction.h new file mode 100644 index 00000000..2e484765 --- /dev/null +++ b/thrift/lib/cpp/async/TDelayedDestruction.h @@ -0,0 +1,178 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TDELAYEDDESTRUCTION_H_ +#define THRIFT_ASYNC_TDELAYEDDESTRUCTION_H_ 1 + +#include +#include +#include + +namespace apache { namespace thrift { namespace async { + +/** + * TDelayedDestruction is a helper class to ensure objects are not deleted + * while they still have functions executing in a higher stack frame. + * + * This is useful for objects that invoke callback functions, to ensure that a + * callback does not destroy the calling object. + * + * Classes needing this functionality should: + * - derive from TDelayedDestruction + * - make their destructor private or protected, so it cannot be called + * directly + * - create a DestructorGuard object on the stack in each public method that + * may invoke a callback + * + * TDelayedDestruction does not perform any locking. It is intended to be used + * only from a single thread. + */ +class TDelayedDestruction : private boost::noncopyable { + public: + /** + * Helper class to allow TDelayedDestruction classes to be used with + * boost::shared_ptr. + * + * This class can be specified as the destructor argument when creating the + * shared_ptr, and it will destroy the guarded class properly when all + * shared_ptr references are released. + */ + class Destructor { + public: + void operator()(TDelayedDestruction* dd) const { + dd->destroy(); + } + }; + + /** + * destroy() requests destruction of the object. + * + * This method will destroy the object after it has no more functions running + * higher up on the stack. (i.e., No more DestructorGuard objects exist for + * this object.) This method must be used instead of the destructor. + */ + virtual void destroy() { + // If guardCount_ is not 0, just set destroyPending_ to delay + // actual destruction. + if (guardCount_ != 0) { + destroyPending_ = true; + } else { + destroyNow(false); + } + } + + /** + * Classes should create a DestructorGuard object on the stack in any + * function that may invoke callback functions. + * + * The DestructorGuard prevents the guarded class from being destroyed while + * it exists. Without this, the callback function could delete the guarded + * object, causing problems when the callback function returns and the + * guarded object's method resumes execution. + */ + class DestructorGuard { + public: + explicit DestructorGuard(TDelayedDestruction* dd) : dd_(dd) { + ++dd_->guardCount_; + assert(dd_->guardCount_ > 0); // check for wrapping + } + + ~DestructorGuard() { + assert(dd_->guardCount_ > 0); + --dd_->guardCount_; + if (dd_->guardCount_ == 0 && dd_->destroyPending_) { + dd_->destroyNow(true); + } + } + + private: + TDelayedDestruction* dd_; + }; + + protected: + /** + * destroyNow() is invoked to actually destroy the object, after destroy() + * has been called and no more DestructorGuard objects exist. By default it + * calls "delete this", but subclasses may override this behavior. + * + * @param delayed This parameter is true if destruction was delayed because + * of a DestructorGuard object, or false if destroyNow() is + * being called directly from destroy(). + */ + virtual void destroyNow(bool delayed) { + delete this; + (void)delayed; // prevent unused variable warnings + } + + TDelayedDestruction() + : guardCount_(0) + , destroyPending_(false) {} + + /** + * Protected destructor. + * + * Making this protected ensures that users cannot delete TDelayedDestruction + * objects directly, and that everyone must use destroy() instead. + * Subclasses of TDelayedDestruction must also define their destructors as + * protected or private in order for this to work. + * + * This also means that TDelayedDestruction objects cannot be created + * directly on the stack; they must always be dynamically allocated on the + * heap. + * + * In order to use a TDelayedDestruction object with a shared_ptr, create the + * shared_ptr using a TDelayedDestruction::Destructor as the second argument + * to the shared_ptr constructor. + */ + virtual ~TDelayedDestruction() {} + + /** + * Get the number of DestructorGuards currently protecting this object. + * + * This is primarily intended for debugging purposes, such as asserting + * that an object has at least 1 guard. + */ + uint32_t getDestructorGuardCount() const { + return guardCount_; + } + + private: + /** + * guardCount_ is incremented by DestructorGuard, to indicate that one of + * the TDelayedDestruction object's methods is currently running. + * + * If destroy() is called while guardCount_ is non-zero, destruction will + * be delayed until guardCount_ drops to 0. This allows TDelayedDestruction + * objects to invoke callbacks without having to worry about being deleted + * before the callback returns. + */ + uint32_t guardCount_; + + /** + * destroyPending_ is set to true if destoy() is called while guardCount_ is + * non-zero. + * + * If destroyPending_ is true, the object will be destroyed the next time + * guardCount_ drops to 0. + */ + bool destroyPending_; +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TDELAYEDDESTRUCTION_H_ diff --git a/thrift/lib/cpp/async/TEventBase.h b/thrift/lib/cpp/async/TEventBase.h new file mode 100644 index 00000000..42009a75 --- /dev/null +++ b/thrift/lib/cpp/async/TEventBase.h @@ -0,0 +1,397 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef THRIFT_ASYNC_TEVENTBASE_H_ +#define THRIFT_ASYNC_TEVENTBASE_H_ 1 + +#include "thrift/lib/cpp/Thrift.h" +#include "thrift/lib/cpp/async/TAsyncTimeout.h" +#include "thrift/lib/cpp/server/TServer.h" +#include "thrift/lib/cpp/transport/TTransportUtils.h" +#include "thrift/lib/cpp/concurrency/ThreadManager.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // libevent +#include +#include + +namespace apache { namespace thrift { namespace async { + +typedef std::tr1::function Cob; +template +class TNotificationQueue; + +/** + * This class is a wrapper for all asynchronous I/O processing functionality + * used in thrift. + * + * TEventBase provides a main loop that notifies TEventHandler callback objects + * when I/O is ready on a file descriptor, and notifies TAsyncTimeout objects + * when a specified timeout has expired. More complex, higher-level callback + * mechanisms can then be built on top of TEventHandler and TAsyncTimeout. + * + * A TEventBase object can only drive an event loop for a single thread. To + * take advantage of multiple CPU cores, most asynchronous I/O servers have one + * thread per CPU, and use a separate TEventBase for each thread. + * + * In general, most TEventBase methods may only be called from the thread + * running the TEventBase's loop. There are a few exceptions to this rule, for + * methods that are explicitly intended to allow communication with a + * TEventBase from other threads. When it is safe to call a method from + * another thread it is explicitly listed in the method comments. + */ +class TEventBase : private boost::noncopyable { + public: + /** + * A callback interface to use with runInLoop() + * + * Derive from this class if you need to delay some code execution until the + * next iteration of the event loop. This allows you to schedule code to be + * invoked from the top-level of the loop, after your immediate callers have + * returned. + * + * If a LoopCallback object is destroyed while it is scheduled to be run in + * the next loop iteration, it will automatically be cancelled. + */ + class LoopCallback { + public: + virtual ~LoopCallback() {} + + virtual void runLoopCallback() THRIFT_NOEXCEPT = 0; + void cancelLoopCallback() { + hook_.unlink(); + } + + bool isLoopCallbackScheduled() const { + return hook_.is_linked(); + } + + private: + typedef boost::intrusive::list_member_hook< + boost::intrusive::link_mode > ListHook; + + ListHook hook_; + + typedef boost::intrusive::list< + LoopCallback, + boost::intrusive::member_hook, + boost::intrusive::constant_time_size > List; + + // TEventBase needs access to LoopCallbackList (and therefore to hook_) + friend class TEventBase; + }; + + /** + * Create a new TEventBase object. + */ + TEventBase(); + + /** + * Create a new TEventBase object that will use the specified libevent + * event_base object to drive the event loop. + * + * The TEventBase will take ownership of this event_base, and will call + * event_base_free(evb) when the TEventBase is destroyed. + */ + explicit TEventBase(event_base* evb); + ~TEventBase(); + + /** + * Runs the event loop. + * + * loop() will loop waiting for I/O or timeouts and invoking TEventHandler + * and TAsyncTimeout callbacks as their events become ready. loop() will + * only return when there are no more events remaining to process, or after + * terminateLoopSoon() has been called. + * + * loop() may be called again to restart event processing after a previous + * call to loop() or loopForever() has returned. + * + * Returns true if the loop completed normally (if it processed all + * outstanding requests, or if terminateLoopSoon() was called). If an error + * occurs waiting for events, false will be returned. + */ + bool loop(); + + /** + * Runs the event loop. + * + * loopForever() behaves like loop(), except that it keeps running even if + * when there are no more user-supplied TEventHandlers or TAsyncTimeouts + * registered. It will only return after terminateLoopSoon() has been + * called. + * + * This is useful for callers that want to wait for other threads to call + * runInEventBaseThread(), even when there are no other scheduled events. + * + * loopForever() may be called again to restart event processing after a + * previous call to loop() or loopForever() has returned. + * + * Throws a TLibraryException if an error occurs. + */ + void loopForever(); + + /** + * Causes the event loop to exit soon. + * + * This will cause an existing call to loop() or loopForever() to stop event + * processing and return, even if there are still events remaining to be + * processed. + * + * It is safe to call terminateLoopSoon() from another thread to cause loop() + * to wake up and return in the TEventBase loop thread. terminateLoopSoon() + * may also be called from the loop thread itself (for example, a + * TEventHandler or TAsyncTimeout callback may call terminateLoopSoon() to + * cause the loop to exit after the callback returns.) + * + * Note that the caller is responsible for ensuring that cleanup of all event + * callbacks occurs properly. Since terminateLoopSoon() causes the loop to + * exit even when there are pending events present, there may be remaining + * callbacks present waiting to be invoked. If the loop is later restarted + * pending events will continue to be processed normally, however if the + * TEventBase is destroyed after calling terminateLoopSoon() it is the + * caller's responsibility to ensure that cleanup happens properly even if + * some outstanding events are never processed. + */ + void terminateLoopSoon(); + + /** + * Adds the given callback to a queue of things run after the current pass + * through the event loop completes. Note that if this callback calls + * runInLoop() the new callback won't be called until the main event loop + * has gone through a cycle. + * + * This method may only be called from the TEventBase's thread. This + * essentially allows an event handler to schedule an additional callback to + * be invoked after it returns. + * + * Use runInEventBaseThread() to schedule functions from another thread. + */ + void runInLoop(LoopCallback* callback); + + /** + * Convenience function to call runInLoop() with a tr1::function. + * + * This creates a LoopCallback object to wrap the tr1::function, and invoke + * the tr1::function when the loop callback fires. This is slightly more + * expensive than defining your own LoopCallback, but more convenient in + * areas that aren't performance sensitive where you just want to use + * tr1::bind. (tr1::bind is fairly slow on even by itself.) + * + * This method may only be called from the TEventBase's thread. This + * essentially allows an event handler to schedule an additional callback to + * be invoked after it returns. + * + * Use runInEventBaseThread() to schedule functions from another thread. + */ + void runInLoop(const Cob& c); + + /** + * Run the specified function in the TEventBase's thread. + * + * This method is thread-safe, and may be called from another thread. + * + * If runInEventBaseThread() is called when the TEventBase loop is not + * running, the function call will be delayed until the next time the loop is + * started. + * + * If runInEventBaseThread() returns true the function has successfully been + * scheduled to run in the loop thread. However, if the loop is terminated + * (and never later restarted) before it has a chance to run the requested + * function, the function may never be run at all. The caller is responsible + * for handling this situation correctly if they may terminate the loop with + * outstanding runInEventBaseThread() calls pending. + * + * If two calls to runInEventBaseThread() are made from the same thread, the + * functions will always be run in the order that they were scheduled. + * Ordering between functions scheduled from separate threads is not + * guaranteed. + * + * @param fn The function to run. The function must not throw any + * exceptions. + * @param arg An argument to pass to the function. + * + * @return Returns true if the function was successfully scheduled, or false + * if there was an error scheduling the function. + */ + template + bool runInEventBaseThread(void (*fn)(T*), T* arg) { + return runInEventBaseThread(reinterpret_cast(fn), + reinterpret_cast(arg)); + } + + bool runInEventBaseThread(void (*fn)(void*), void* arg); + + /** + * Run the specified function in the TEventBase's thread + * + * This version of runInEventBaseThread() takes a tr1::function object. + * Note that this is less efficient than the version that takes a plain + * function pointer and void* argument, as it has to allocate memory to copy + * the tr1::function object. + * + * If the TEventBase loop is terminated before it has a chance to run this + * function, the allocated memory will be leaked. The caller is responsible + * for ensuring that the TEventBase loop is not terminated before this + * function can run. + * + * The function must not throw any exceptions. + */ + bool runInEventBaseThread(const std::tr1::function& fn); + + /** + * Runs the given Cob at some time after the specified number of + * milliseconds. (No guarantees exactly when.) + * + * @return true iff the cob was successfully registered. + */ + bool runAfterDelay(const Cob& c, int milliseconds); + + /** + * Set the maximum desired latency in us and provide a callback which will be + * called when that latency is exceeded. + */ + void setMaxLatency(int64_t maxLatency, const Cob& maxLatencyCob) { + maxLatency_ = maxLatency; + maxLatencyCob_ = maxLatencyCob; + } + /** + * Set smoothing coefficient for loop load average; # of milliseconds + * for exp(-1) (1/2.71828...) decay. + */ + void setLoadAvgMsec(uint32_t ms); + + /** + * Get the average loop time in microseconds (an exponentially-smoothed ave) + */ + double getAvgLoopTime() const { + return avgLoopTime_; + } + + /** + * Verify that current thread is the TEventBase thread, if the TEventBase is + * running. + * + * This is primarily intended for debugging, to assert that functions that + * register or unregister events are only ever invoked in the TEventBase's + * thread. + */ + bool isInEventBaseThread() const { + return !running_ || pthread_equal(loopThread_, pthread_self()); + } + + // --------- interface to underlying libevent base ------------ + // Avoid using these functions if possible. These functions are not + // guaranteed to always be present if we ever provide alternative TEventBase + // implementations that do not use libevent internally. + event_base* getLibeventBase() const { return evb_; } + static const char* getLibeventVersion() { return event_get_version(); } + static const char* getLibeventMethod() { return event_get_method(); } + + private: + // --------- libevent callbacks (not for client use) ------------ + + /** + * Called after a delay to break out of an idle event loop. We need to + * use this instead of event_base_loopexit() since the latter installs + * an event within libevent which is queued until it expires. Installing + * our own timed event lets us delete it when another event causes the + * loop to exit earlier.. + */ + static void loopTimerCallback(int fd, short which, void* arg); + + static void runTr1FunctionPtr(std::tr1::function* fn); + + // small object used as a callback arg with enough info to execute the + // appropriate client-provided Cob + class CobTimeout : public TAsyncTimeout { + public: + CobTimeout(TEventBase* b, const Cob& c) : TAsyncTimeout(b), cob_(c) {} + + virtual void timeoutExpired() THRIFT_NOEXCEPT; + + private: + Cob cob_; + + public: + typedef boost::intrusive::list_member_hook< + boost::intrusive::link_mode > ListHook; + + ListHook hook; + + typedef boost::intrusive::list< + CobTimeout, + boost::intrusive::member_hook, + boost::intrusive::constant_time_size > List; + }; + + typedef LoopCallback::List LoopCallbackList; + class FunctionRunner; + + // executes any callbacks queued by runInLoop() + void runLoopCallbacks(); + + void initNotificationQueue(); + + CobTimeout::List pendingCobTimeouts_; + + LoopCallbackList loopCallbacks_; + + // stop_ is set by terminateLoopSoon() and is used by the main loop + // to determine if it should exit + bool stop_; + // running_ is set to true while loop() is running + bool running_; + // The ID of the thread running the main loop. + // Only valid while running_ is true. + pthread_t loopThread_; + + // pointer to underlying event_base class doing the heavy lifting + event_base* evb_; + + // A notification queue for runInEventBaseThread() to use + // to send function requests to the TEventBase thread. + std::unique_ptr>> queue_; + std::unique_ptr fnRunner_; + + // limit for latency in microseconds (0 disables) + int64_t maxLatency_; + + // smoothed loop time used to invoke latency callbacks; differs from + // avgLoopTime_ in that it's scaled down after triggering a callback + // to reduce spamminess + double maxLatencyLoopTime_; + + // exponentially-smoothed average loop time for latency-limiting + double avgLoopTime_; + + // set to true if the event_base_loop(EVLOOP_ONCE) returned because + // the loop timeout fired, rather than because it found events to process + bool loopTimedOut_; + + // factor used for exponential smoothing of load average + double expCoeff_; + + // callback called when latency limit is exceeded + Cob maxLatencyCob_; + + // we'll wait this long before running deferred callbacks if the event + // loop is idle. + static const int kDEFAULT_IDLE_WAIT_USEC = 20000; // 20ms +}; + +}}} // apache::thrift::async + +#endif // #ifndef THRIFT_ASYNC_TEVENTBASE_H_ diff --git a/thrift/lib/cpp/async/TEventBaseManager.h b/thrift/lib/cpp/async/TEventBaseManager.h new file mode 100644 index 00000000..d6d1ae01 --- /dev/null +++ b/thrift/lib/cpp/async/TEventBaseManager.h @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TEVENTBASEMANAGER_H +#define THRIFT_ASYNC_TEVENTBASEMANAGER_H 1 + +#include "thrift/lib/cpp/concurrency/ThreadLocal.h" + +namespace apache { namespace thrift { namespace async { + +class TEventBase; + +/** + * Manager for per-thread TEventBase objects. + * This class will find or create a TEventBase for the current + * thread, associated with thread-specific storage for that thread. + * Although a typical application will generally only have one + * TEventBaseManager, there is no restriction on multiple instances; + * the TEventBases belong to one instance are isolated from those of + * another. + */ +class TEventBaseManager { + public: + TEventBaseManager() {} + ~TEventBaseManager() {} + + /** + * Get the TEventBase for this thread, or create one if none exists yet. + * + * If no TEventBase exists for this thread yet, a new one will be created and + * returned. May throw std::bad_alloc if allocation fails. + */ + TEventBase* getEventBase() const { + // localStore_.get() will never return NULL. + // InfoManager::allocate() will throw an exception instead if it cannot + // allocate a new EventBaseInfo or TEventBase. + return localStore_.get()->eventBase; + } + + /** + * Get the TEventBase for this thread. + * + * Returns NULL if no TEventBase has been created for this thread yet. + */ + TEventBase* getExistingEventBase() const { + EventBaseInfo* info = localStore_.getNoAlloc(); + if (info == NULL) { + return NULL; + } + return info->eventBase; + } + + /** + * Set the TEventBase to be used by this thread. + * + * This may only be called if no TEventBase has been defined for this thread + * yet. If a TEventBase is already defined for this thread, a + * TLibraryException is thrown. std::bad_alloc may also be thrown if + * allocation fails while setting the TEventBase. + * + * This should typically be invoked by the code that will call loop() on the + * TEventBase, to make sure the TEventBaseManager points to the correct + * TEventBase that is actually running in this thread. + */ + void setEventBase(TEventBase *eventBase, bool takeOwnership); + + /** + * Clear the TEventBase for this thread. + * + * This can be used if the code driving the TEventBase loop() has finished + * the loop and new events should no longer be added to the TEventBase. + */ + void clearEventBase(); + + private: + struct EventBaseInfo { + EventBaseInfo(TEventBase *evb, bool owned) + : eventBase(evb), + owned(owned) {} + + TEventBase *eventBase; + bool owned; + }; + + class InfoManager { + public: + EventBaseInfo* allocate(); + void destroy(EventBaseInfo* info); + + void replace(EventBaseInfo* oldInfo, EventBaseInfo* newInfo) { + if (oldInfo != newInfo) { + destroy(oldInfo); + } + } + }; + + // Forbidden copy constructor and assignment opererator + TEventBaseManager(TEventBaseManager const &); + TEventBaseManager& operator=(TEventBaseManager const &); + + concurrency::ThreadLocal localStore_; +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TEVENTBASEMANAGER_H diff --git a/thrift/lib/cpp/async/TEventConnection.h b/thrift/lib/cpp/async/TEventConnection.h new file mode 100644 index 00000000..c46c749b --- /dev/null +++ b/thrift/lib/cpp/async/TEventConnection.h @@ -0,0 +1,239 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef THRIFT_ASYNC_TEVENTCONNECTION_H_ +#define THRIFT_ASYNC_TEVENTCONNECTION_H_ 1 + +#include "thrift/lib/cpp/server/TConnectionContext.h" +#include "thrift/lib/cpp/transport/TSocketAddress.h" +#include "thrift/lib/cpp/async/TEventServer.h" +#include +#include + +namespace apache { namespace thrift { + +class TProcessor; + +namespace protocol { +class TProtocol; +} + +namespace server { +class TServerEventHandler; +} + +namespace transport { +class TMemoryBuffer; +} + +namespace async { + +class TAsyncEventChannel; +class TAsyncProcessor; +class TEventWorker; +class TAsyncSocket; +class TaskCompletionMessage; + +/** + * Represents a connection that is handled via libevent. This connection + * essentially encapsulates a socket that has some associated libevent state. + */ +class TEventConnection : private boost::noncopyable, + public TEventBase::LoopCallback { + public: + + /** + * Constructor for TEventConnection. + * + * @param asyncSocket shared pointer to the async socket + * @param address the peer address of this connection + * @param worker the worker instance that is handling this connection + */ + TEventConnection(boost::shared_ptr asyncSocket, + const transport::TSocketAddress* address, + TEventWorker* worker, TEventServer::TransportType transport); + + /** + * (Re-)Initialize a TEventConnection. We break this out from the + * constructor to allow for pooling. + * + * @param asyncSocket shared pointer to the async socket + * @param address the peer address of this connection + * @param worker the worker instance that is handling this connection + */ + void init(boost::shared_ptr asyncSocket, + const transport::TSocketAddress* address, + TEventWorker* worker, TEventServer::TransportType transport); + + /// First cause -- starts i/o on connection + void start(); + + /// Shut down the connection even if it's OK; used for load reduction. + void stop() { + shutdown_ = true; + } + + /// Return a pointer to the worker that owns us + TEventWorker* getWorker() const { + return worker_; + } + + /// cause the notification callback to occur within the appropriate context + bool notifyCompletion(TaskCompletionMessage &&msg); + + /// Run scheduled read when there are too many reads on the stack + void runLoopCallback() THRIFT_NOEXCEPT; + + boost::shared_ptr getProcessor() const { + return processor_; + } + + boost::shared_ptr + getInputProtocol() const { + return inputProtocol_; + } + + boost::shared_ptr + getOutputProtocol() const { + return outputProtocol_; + } + + /// Get the per-server event handler set for this server, if any + boost::shared_ptr + getServerEventHandler() const { + return serverEventHandler_; + } + + /// Get the TConnectionContext for this connection + server::TConnectionContext* getConnectionContext() { + return &context_; + } + + /// Destructor -- close down the connection. + ~TEventConnection(); + + /** + * Check the size of our memory buffers and resize if needed. Do not call + * when a call is in progress. + */ + void checkBufferMemoryUsage(); + + private: + class ConnContext : public server::TConnectionContext { + public: + void init(const transport::TSocketAddress* address, + boost::shared_ptr inputProtocol, + boost::shared_ptr outputProtocol) { + address_ = *address; + inputProtocol_ = inputProtocol; + outputProtocol_ = outputProtocol; + } + + virtual const transport::TSocketAddress* getPeerAddress() const { + return &address_; + } + + void reset() { + address_.reset(); + cleanupUserData(); + } + + // TODO(dsanduleac): implement the virtual getInputProtocol() & such + + virtual boost::shared_ptr getInputProtocol() const { + // from TEventConnection + return inputProtocol_; + } + + virtual boost::shared_ptr getOutputProtocol() const { + return outputProtocol_; + } + + private: + transport::TSocketAddress address_; + boost::shared_ptr inputProtocol_; + boost::shared_ptr outputProtocol_; + }; + + void readNextRequest(); + void handleReadSuccess(); + void handleReadFailure(); + void handleAsyncTaskComplete(bool success); + void handleSendSuccess(); + void handleSendFailure(); + + void handleEOF(); + void handleFailure(const char* msg); + void cleanup(); + + //! The worker instance handling this connection. + TEventWorker* worker_; + + //! This connection's socket. + boost::shared_ptr asyncSocket_; + + //! Transport that the processor reads from. + boost::shared_ptr inputTransport_; + + //! Transport that the processor writes to. + boost::shared_ptr outputTransport_; + + /// Largest size of read buffer seen since buffer was constructed + size_t largestReadBufferSize_; + + /// Largest size of write buffer seen since buffer was constructed + size_t largestWriteBufferSize_; + + /// Count of the number of calls for use with getResizeBufferEveryN(). + int32_t callsForResize_; + + //! Protocol decoder. + boost::shared_ptr inputProtocol_; + + //! Protocol encoder. + boost::shared_ptr outputProtocol_; + + //! Channel that actually performs the socket I/O and callbacks. + TAsyncEventChannel* asyncChannel_; + + /// Count of outstanding processor callbacks (generally 0 or 1). + int32_t processorActive_; + + //! Count of the number of handleReadSuccess frames on the stack + int32_t readersActive_; + + /// Sync processor if we're in queuing mode + boost::shared_ptr processor_; + + /// Flag used to shut down connection (used for load-shedding mechanism). + bool shutdown_; + + /// Flag indicating that we have deferred closing down (processor was active) + bool closing_; + + /// The per-server event handler set for this erver, if any + boost::shared_ptr + serverEventHandler_; + + /// per-connection context + ConnContext context_; + + /// Our processor + boost::shared_ptr asyncProcessor_; + + /// So that TEventWorker can call handleAsyncTaskComplete(); + friend class TEventWorker; + + /// Make the server a friend so it can manage tasks when overloaded + friend class TEventServer; + + /// Make an async task a friend so it can communicate a cleanup() to us. + friend class TEventTask; +}; + +}}} // apache::thrift::async + +#endif // #ifndef THRIFT_ASYNC_TEVENTCONNECTION_H_ diff --git a/thrift/lib/cpp/async/TEventHandler.h b/thrift/lib/cpp/async/TEventHandler.h new file mode 100644 index 00000000..0d720ed3 --- /dev/null +++ b/thrift/lib/cpp/async/TEventHandler.h @@ -0,0 +1,182 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TEVENTHANDLER_H_ +#define THRIFT_ASYNC_TEVENTHANDLER_H_ 1 + +#include "thrift/lib/cpp/thrift_config.h" +#include "thrift/lib/cpp/async/TEventUtil.h" +#include +#include + +namespace apache { namespace thrift { namespace async { + +class TEventBase; + +/** + * The TEventHandler class is used to asynchronously wait for events on a file + * descriptor. + * + * Users that wish to wait on I/O events should derive from TEventHandler and + * implement the handlerReady() method. + */ +class TEventHandler : private boost::noncopyable { + public: + enum EventFlags { + NONE = 0, + READ = EV_READ, + WRITE = EV_WRITE, + READ_WRITE = (READ | WRITE), + PERSIST = EV_PERSIST + }; + + /** + * Create a new TEventHandler object. + * + * @param eventBase The TEventBase to use to drive this event handler. + * This may be NULL, in which case the TEventBase must be + * set separately using initHandler() or attachEventBase() + * before the handler can be registered. + * @param fd The file descriptor that this TEventHandler will + * monitor. This may be -1, in which case the file + * descriptor must be set separately using initHandler() or + * changeHandlerFD() before the handler can be registered. + */ + explicit TEventHandler(TEventBase* eventBase = NULL, int fd = -1); + + /** + * TEventHandler destructor. + * + * The event will be automatically unregistered if it is still registered. + */ + virtual ~TEventHandler(); + + /** + * handlerReady() is invoked when the handler is ready. + * + * @param events A bitset indicating the events that are ready. + */ + virtual void handlerReady(uint16_t events) THRIFT_NOEXCEPT = 0; + + /** + * Register the handler. + * + * If the handler is already registered, the registration will be updated + * to wait on the new set of events. + * + * @param events A bitset specifying the events to monitor. + * If the PERSIST bit is set, the handler will remain + * registered even after handlerReady() is called. + * + * @return Returns true if the handler was successfully registered, + * or false if an error occurred. After an error, the handler is + * always unregistered, even if it was already registered prior to + * this call to registerHandler(). + */ + bool registerHandler(uint16_t events) { + return registerImpl(events, false); + } + + /** + * Unregister the handler, if it is registered. + */ + void unregisterHandler(); + + /** + * Returns true if the handler is currently registered. + */ + bool isHandlerRegistered() const { + return TEventUtil::isEventRegistered(&event_); + } + + /** + * Attach the handler to a TEventBase. + * + * This may only be called if the handler is not currently attached to a + * TEventBase (either by using the default constructor, or by calling + * detachEventBase()). + * + * This method must be invoked in the TEventBase's thread. + */ + void attachEventBase(TEventBase* eventBase); + + /** + * Detach the handler from its TEventBase. + * + * This may only be called when the handler is not currently registered. + * Once detached, the handler may not be registered again until it is + * re-attached to a TEventBase by calling attachEventBase(). + * + * This method must be called from the current TEventBase's thread. + */ + void detachEventBase(); + + /** + * Change the file descriptor that this handler is associated with. + * + * This may only be called when the handler is not currently registered. + */ + void changeHandlerFD(int fd); + + /** + * Attach the handler to a TEventBase, and change the file descriptor. + * + * This method may only be called if the handler is not currently attached to + * a TEventBase. This is primarily intended to be used to initialize + * TEventHandler objects created using the default constructor. + */ + void initHandler(TEventBase* eventBase, int fd); + + /** + * Return the set of events that we're currently registered for. + */ + uint16_t getRegisteredEvents() const { + return (isHandlerRegistered()) ? + event_.ev_events : 0; + } + + /** + * Register the handler as an internal event. + * + * This event will not count as an active event for determining if the + * TEventBase loop has more events to process. The TEventBase loop runs + * only as long as there are active TEventHandlers, however "internal" event + * handlers are not counted. Therefore this event handler will not prevent + * TEventBase loop from exiting with no more work to do if there are no other + * non-internal event handlers registered. + * + * This is intended to be used only in very rare cases by the internal + * TEventBase code. This API is not guaranteed to remain stable or portable + * in the future. + */ + bool registerInternalHandler(uint16_t events) { + return registerImpl(events, true); + } + + private: + bool registerImpl(uint16_t events, bool internal); + void ensureNotRegistered(const char* fn); + + static void libeventCallback(int fd, short events, void* arg); + + struct event event_; +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TEVENTHANDLER_H_ diff --git a/thrift/lib/cpp/async/TEventServer.h b/thrift/lib/cpp/async/TEventServer.h new file mode 100644 index 00000000..a79fccc9 --- /dev/null +++ b/thrift/lib/cpp/async/TEventServer.h @@ -0,0 +1,1037 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TEVENTSERVER_H_ +#define THRIFT_ASYNC_TEVENTSERVER_H_ 1 + +#include "thrift/lib/cpp/Thrift.h" +#include "thrift/lib/cpp/server/TServer.h" +#include "thrift/lib/cpp/async/TAsyncProcessor.h" +#include "thrift/lib/cpp/transport/TTransportUtils.h" +#include "thrift/lib/cpp/transport/TSSLSocket.h" +#include "thrift/lib/cpp/protocol/THeaderProtocol.h" +#include "thrift/lib/cpp/concurrency/Mutex.h" +#include "thrift/lib/cpp/concurrency/ThreadLocal.h" +#include "thrift/lib/cpp/async/TEventBase.h" +#include "thrift/lib/cpp/async/TEventBaseManager.h" +#include +#include +#include +#include + +namespace apache { namespace thrift { + +namespace concurrency { +class ThreadFactory; +class ThreadManager; +} + +namespace async { + +using apache::thrift::protocol::TDualProtocolFactory; + +// Forward declaration of classes +class TAsyncServerSocket; +class TEventConnection; +class TEventWorker; + +/** + This is a non-blocking event-based server for high performance that + operates an I/O thread for each cpu core and uses callbacks for + notification of processing or I/O operations. + + It does not use the TServerTransport framework, but rather has socket + operations hardcoded for use with libevent and implements framing + compatible with TFramedTransport. A single "listener" thread accepts + connections and sends them to the server threads via a single socketpair(); + the server threads are each responsible for allocating and pooling actual + connection objects, avoiding the need for the locks required by a common + pool. + + The original Thrift server was by Mark Slee . + A non-blocking variant was produced which allowed for a large number + of processing threads but restricted network I/O to a single thread -- + suboptimal on a multi-core CPU. David Reiss + and Mark Rabkin refactored this server into a + callback-driven event-based configuration. Ed Hall + elaborated on this to support network I/O on multiple threads (ideally + one per CPU core). + + @author Mark Slee + @author David Reiss + @author Mark Rabkin + @author Ed Hall + */ + +class TEventServer : public apache::thrift::server::TServer { + + public: + enum TransportType { + FRAMED = 0, + HEADER = 1, + + /*********** Deprecation Warning ******************* + * * + * The unframed transports are deprecated ! * + * They should be used for legancy services only * + * Also note: they only works with TBinaryProtocol * + ***************************************************/ + + UNFRAMED_BINARY = 2 + }; + + protected: + //! Default max size of per-worker connection pool. + static const uint32_t T_ASYNC_MAX_CONNECTION_POOL_SIZE = 64; + + /// Starting size of a TEventConnection's read buffer + static const int T_ASYNC_READ_BUFFER_DEFAULT_SIZE = 1024; + + /// Starting size of a TEventConnection's write buffer + static const int T_ASYNC_WRITE_BUFFER_DEFAULT_SIZE = 1024; + + /// Maximum size of read buffer allocated to idle connection (0 = unlimited) + static const int T_ASYNC_IDLE_READ_BUFFER_LIMIT = 0; + + /// Maximum size of write buffer allocated to idle connection (0 = unlimited) + static const int T_ASYNC_IDLE_WRITE_BUFFER_LIMIT = 0; + + /// # of calls before resizing oversized buffers (0 = check only on close) + static const int T_ASYNC_RESIZE_BUFFER_EVERY_N = 0; + + //! Default number of worker threads (should be # of processor cores). + static const int T_ASYNC_DEFAULT_WORKER_THREADS = 4; + + //! Maximum size of a frame we'll accept (default = 64MB) + static const int T_ASYNC_DEFAULT_MAX_FRAME_SIZE = 67108864; + + static const uint32_t T_MAX_NUM_MESSAGES_IN_PIPE = 0xffffffff; + + /// Listen backlog + static const int T_LISTEN_BACKLOG = 1024; + + //! Transport type + static const TransportType T_ASYNC_DEFAULT_TRANSPORT_TYPE = FRAMED; + + private: + struct WorkerInfo { + boost::shared_ptr worker; + boost::shared_ptr thread; + }; + + //! Max size of per-worker connection pool (may be set). + uint32_t maxConnectionPoolSize_; + + //! SSL context + boost::shared_ptr sslContext_; + + //! Factory that creates connection processor objects. + boost::shared_ptr asyncProcessorFactory_; + + //! Port to listen on + uint16_t port_; + + //! Listen socket + TAsyncServerSocket* socket_; + + //! The TEventBase currently driving serve(). NULL when not serving. + TEventBase* serveEventBase_; + + //! Number of worker threads (may be set) (should be # of CPU cores) + int nWorkers_; + + //! Milliseconds we'll wait for data to appear (0 = infinity) + int timeout_; + + //! Manager of per-thread TEventBase objects. + TEventBaseManager eventBaseManager_; + + //! Last worker chosen -- used to select workers in round-robin sequence. + uint32_t workerChoice_; + + //! List of workers. + typedef std::vector WorkerVector; + WorkerVector workers_; + + //! Maximum number of bytes accepted in a frame. + uint32_t maxFrameSize_; + + /// We initialize (and reinitialize) TEventConnection's read buffer to + /// this size. + size_t readBufferDefaultSize_; + + /// We initialize (and reinitialize) TEventConnection's write buffer to + /// this size. + size_t writeBufferDefaultSize_; + + /** + * Max read buffer size for an idle TConnection. When we place an idle + * TConnection into TEventWorker::connectionStack_ or on every + * resizeBufferEveryN_ calls, we insure that its read buffer is <= to + * this size; otherwise we replace it with a new one to insure that idle + * connections don't hog memory. 0 disables this check. + */ + size_t idleReadBufferLimit_; + + /** + * Max write buffer size for an idle connection. When we place an idle + * TConnection into TEventWorker::connectionStack_ or on every + * resizeBufferEveryN_ calls, we insure that its write buffer is <= to + * this size; otherwise we replace it with a new one to insure that idle + * connections don't hog memory. 0 disables this check. + */ + size_t idleWriteBufferLimit_; + + /** + * Every N calls we check the buffer size limits on a connected + * TEventConnection. 0 disables (i.e. the checks are only done when a + * connection closes). + */ + int32_t resizeBufferEveryN_; + + /** + * Call timeout in ms. When nonzero, limits the amount of time we allow + * between the start of a call and the actual invokation of its processor. + * The connection closes if it is exceeded. + */ + int32_t callTimeout_; + + /** + * The thread manager used when we're in queuing mode. + */ + boost::shared_ptr threadManager_; + + /** + * Thread local storage to track the current connection being processed + */ + concurrency::ThreadLocal > + currentConnection_; + + /** + * The time in milliseconds before an unperformed task expires -- + * queuing mode only. (0 == infinite) + */ + uint64_t taskExpireTime_; + + /** + * Set true if we are in queuing mode, false if not. + */ + bool queuingMode_; + + /** + * The speed for adjusting connection accept rate. + * 0 for disabling auto adjusting connection accept rate. + */ + double acceptRateAdjustSpeed_; + + /** + * The maximum number of unprocessed messages which a NotificationPipe + * can hold. + */ + uint32_t maxNumMsgsInPipe_; + + /** + * The max number of active connections for each worker + */ + int32_t maxNumActiveConnectionsPerWorker_; + + /** + * The transport type to use + */ + TransportType transportType_; + + void addWorker(concurrency::ThreadFactory* threadFactory); + + /** + * No-op signal handler (for SIGPIPE) + */ + static void sigNoOp(int signo) { + (void)signo; + } + + /** + * Set the current connection + */ + void setCurrentConnection(TEventConnection* conn) { + assert(currentConnection_.get() == NULL); + currentConnection_.set(conn); + } + + /** + * Clear the current connection + */ + void clearCurrentConnection() { + currentConnection_.clear(); + } + // Allow TEventConnection and TEventTask to access setCurrentConnection() + // and clearCurrentConnection(). Only these two private + // methods are meant to be used by TEventConnection and TEventTask. + friend class TEventConnection; + friend class TEventTask; + + public: + /** Construct an async Thrift server. + You need to compile your thrift configuration with thrift_cpp_options = + "cob_style" to get the required TAsyncProcessor class; this differs + from the usual TProcessor object by adding a completion callback. + TBinaryProtocol is assumed for both input and output with this + constructor. + @param processor the TAsyncProcessor object for this service + @param port the TCP port number for this service + @param nWorkers the number of worker threads -- should be the same + as the number of CPU cores, though if a process has + more than one TEventServer the cores can be split + between them. + */ + template + TEventServer(boost::shared_ptr processor, + int port, + int nWorkers = T_ASYNC_DEFAULT_WORKER_THREADS, + THRIFT_OVERLOAD_IF(AsyncProcessor, TAsyncProcessor)) : + apache::thrift::server::TServer(boost::shared_ptr()), + maxConnectionPoolSize_(T_ASYNC_MAX_CONNECTION_POOL_SIZE), + asyncProcessorFactory_(new TAsyncSingletonProcessorFactory(processor)), + port_(port), + socket_(NULL), + serveEventBase_(NULL), + nWorkers_(nWorkers), + timeout_(0), + eventBaseManager_(), + workerChoice_(0), + maxFrameSize_(T_ASYNC_DEFAULT_MAX_FRAME_SIZE), + readBufferDefaultSize_(T_ASYNC_READ_BUFFER_DEFAULT_SIZE), + writeBufferDefaultSize_(T_ASYNC_WRITE_BUFFER_DEFAULT_SIZE), + idleReadBufferLimit_(T_ASYNC_IDLE_READ_BUFFER_LIMIT), + idleWriteBufferLimit_(T_ASYNC_IDLE_WRITE_BUFFER_LIMIT), + resizeBufferEveryN_(T_ASYNC_RESIZE_BUFFER_EVERY_N), + callTimeout_(0), + taskExpireTime_(0), + queuingMode_(false), + acceptRateAdjustSpeed_(0), + maxNumMsgsInPipe_(T_MAX_NUM_MESSAGES_IN_PIPE), + maxNumActiveConnectionsPerWorker_(0), + transportType_(T_ASYNC_DEFAULT_TRANSPORT_TYPE) { + processor->setAsyncServer(this); + } + + /** Construct an async Thrift server for a particular TProtocol. + See above; adds a "protocolFactory" parameter to replace the + default TBinaryProtocol. + @param processor the TAsyncProcessor object for this service + @param protocolFactory the TProtocolFactory to use for input & output + @param port the TCP port number for this service + @param nWorkers the number of worker threads + */ + template + TEventServer(boost::shared_ptr processor, + boost::shared_ptr + protocolFactory, + int port, + int nWorkers = T_ASYNC_DEFAULT_WORKER_THREADS, + THRIFT_OVERLOAD_IF(AsyncProcessor, TAsyncProcessor)) : + apache::thrift::server::TServer(boost::shared_ptr()), + maxConnectionPoolSize_(T_ASYNC_MAX_CONNECTION_POOL_SIZE), + asyncProcessorFactory_(new TAsyncSingletonProcessorFactory(processor)), + port_(port), + socket_(NULL), + serveEventBase_(NULL), + nWorkers_(nWorkers), + timeout_(0), + eventBaseManager_(), + workerChoice_(0), + maxFrameSize_(T_ASYNC_DEFAULT_MAX_FRAME_SIZE), + readBufferDefaultSize_(T_ASYNC_READ_BUFFER_DEFAULT_SIZE), + writeBufferDefaultSize_(T_ASYNC_WRITE_BUFFER_DEFAULT_SIZE), + idleReadBufferLimit_(T_ASYNC_IDLE_READ_BUFFER_LIMIT), + idleWriteBufferLimit_(T_ASYNC_IDLE_WRITE_BUFFER_LIMIT), + resizeBufferEveryN_(T_ASYNC_RESIZE_BUFFER_EVERY_N), + callTimeout_(0), + taskExpireTime_(0), + queuingMode_(false), + acceptRateAdjustSpeed_(0), + maxNumMsgsInPipe_(T_MAX_NUM_MESSAGES_IN_PIPE), + maxNumActiveConnectionsPerWorker_(0), + transportType_(T_ASYNC_DEFAULT_TRANSPORT_TYPE) { + processor->setAsyncServer(this); + + setProtocolFactory(protocolFactory); + } + + /** Construct an async Thrift server with different input & output TProtocol. + See above; adds "inputProtocolFactory" and "outputProtocolFactory" + parameters. + @param processor the TAsyncProcessor object for this service + @param inputProtocolFactory the TProtocolFactory to use for input + @param outputProtocolFactory the TProtocolFactory to use for output + @param port the TCP port number for this service + @param nWorkers the number of worker threads + + @deprecated use TDuplex* ctor below + */ + template + TEventServer(boost::shared_ptr processor, + boost::shared_ptr + inputProtocolFactory, + boost::shared_ptr + outputProtocolFactory, + int port, + int nWorkers = T_ASYNC_DEFAULT_WORKER_THREADS, + THRIFT_OVERLOAD_IF(AsyncProcessor, TAsyncProcessor)) : + apache::thrift::server::TServer(boost::shared_ptr()), + maxConnectionPoolSize_(T_ASYNC_MAX_CONNECTION_POOL_SIZE), + asyncProcessorFactory_(new TAsyncSingletonProcessorFactory(processor)), + port_(port), + socket_(NULL), + serveEventBase_(NULL), + nWorkers_(nWorkers), + timeout_(0), + eventBaseManager_(), + workerChoice_(0), + maxFrameSize_(T_ASYNC_DEFAULT_MAX_FRAME_SIZE), + readBufferDefaultSize_(T_ASYNC_READ_BUFFER_DEFAULT_SIZE), + writeBufferDefaultSize_(T_ASYNC_WRITE_BUFFER_DEFAULT_SIZE), + idleReadBufferLimit_(T_ASYNC_IDLE_READ_BUFFER_LIMIT), + idleWriteBufferLimit_(T_ASYNC_IDLE_WRITE_BUFFER_LIMIT), + resizeBufferEveryN_(T_ASYNC_RESIZE_BUFFER_EVERY_N), + callTimeout_(0), + taskExpireTime_(0), + queuingMode_(false), + acceptRateAdjustSpeed_(0), + maxNumMsgsInPipe_(T_MAX_NUM_MESSAGES_IN_PIPE), + maxNumActiveConnectionsPerWorker_(0), + transportType_(T_ASYNC_DEFAULT_TRANSPORT_TYPE) { + processor->setAsyncServer(this); + + setDuplexProtocolFactory( + boost::shared_ptr( + new TDualProtocolFactory(inputProtocolFactory, outputProtocolFactory))); + } + + + /** Construct an async Thrift server with custom input & output TProtocol. + See above; Replaces protocolFactory with duplexProtocolFactory + parameters. + @param processor the TAsyncProcessor object for this service + @param duplexProtocolFactory the TProtocolFactory to use for input/output + @param port the TCP port number for this service + @param nWorkers the number of worker threads + */ + template + TEventServer( + boost::shared_ptr processor, + boost::shared_ptr + duplexProtocolFactory, + int port, + int nWorkers = T_ASYNC_DEFAULT_WORKER_THREADS, + THRIFT_OVERLOAD_IF(AsyncProcessor, TAsyncProcessor)): + apache::thrift::server::TServer(boost::shared_ptr()), + maxConnectionPoolSize_(T_ASYNC_MAX_CONNECTION_POOL_SIZE), + asyncProcessorFactory_(new TAsyncSingletonProcessorFactory(processor)), + port_(port), + socket_(NULL), + serveEventBase_(NULL), + nWorkers_(nWorkers), + timeout_(0), + eventBaseManager_(), + workerChoice_(0), + maxFrameSize_(T_ASYNC_DEFAULT_MAX_FRAME_SIZE), + readBufferDefaultSize_(T_ASYNC_READ_BUFFER_DEFAULT_SIZE), + writeBufferDefaultSize_(T_ASYNC_WRITE_BUFFER_DEFAULT_SIZE), + idleReadBufferLimit_(T_ASYNC_IDLE_READ_BUFFER_LIMIT), + idleWriteBufferLimit_(T_ASYNC_IDLE_WRITE_BUFFER_LIMIT), + resizeBufferEveryN_(T_ASYNC_RESIZE_BUFFER_EVERY_N), + callTimeout_(0), + taskExpireTime_(0), + queuingMode_(false), + acceptRateAdjustSpeed_(0), + maxNumMsgsInPipe_(T_MAX_NUM_MESSAGES_IN_PIPE), + maxNumActiveConnectionsPerWorker_(0), + transportType_(T_ASYNC_DEFAULT_TRANSPORT_TYPE) { + processor->setAsyncServer(this); + + setDuplexProtocolFactory(duplexProtocolFactory); + } + + + /** Construct a task-queuing Thrift server for a particular TProtocol. + Largely compatible with TNonblockingServer. + + @param processor the TProcessor object for this service + @param protocolFactory the TProtocolFactory to use for input & output + @param port the TCP port number for this service + @param threadManager the thread manager we use for task queuing + @param nWorkers the number of worker threads + */ + template + TEventServer( + boost::shared_ptr processor, + boost::shared_ptr + protocolFactory, + int port, + boost::shared_ptr const& threadManager = + boost::shared_ptr(), + int nWorkers = T_ASYNC_DEFAULT_WORKER_THREADS, + THRIFT_OVERLOAD_IF(Processor, TProcessor)) : + apache::thrift::server::TServer(processor), + maxConnectionPoolSize_(T_ASYNC_MAX_CONNECTION_POOL_SIZE), + port_(port), + socket_(NULL), + serveEventBase_(NULL), + nWorkers_(nWorkers), + timeout_(0), + eventBaseManager_(), + workerChoice_(0), + maxFrameSize_(T_ASYNC_DEFAULT_MAX_FRAME_SIZE), + readBufferDefaultSize_(T_ASYNC_READ_BUFFER_DEFAULT_SIZE), + writeBufferDefaultSize_(T_ASYNC_WRITE_BUFFER_DEFAULT_SIZE), + idleReadBufferLimit_(T_ASYNC_IDLE_READ_BUFFER_LIMIT), + idleWriteBufferLimit_(T_ASYNC_IDLE_WRITE_BUFFER_LIMIT), + resizeBufferEveryN_(T_ASYNC_RESIZE_BUFFER_EVERY_N), + callTimeout_(0), + taskExpireTime_(0), + queuingMode_(true), + acceptRateAdjustSpeed_(0), + maxNumMsgsInPipe_(T_MAX_NUM_MESSAGES_IN_PIPE), + maxNumActiveConnectionsPerWorker_(0), + transportType_(T_ASYNC_DEFAULT_TRANSPORT_TYPE) { + setProtocolFactory(protocolFactory); + setThreadManager(threadManager); + } + + /** Construct a task-queuing Thrift server for a particular TProtocol. + Largely compatible with TNonblockingServer. + + @param processor the TProcessor object for this service + @param protocolFactory the TProtocolFactory to use for input & output + @param port the TCP port number for this service + @param threadManager the thread manager we use for task queuing + @param nWorkers the number of worker threads + */ + template + TEventServer( + boost::shared_ptr processor, + boost::shared_ptr + duplexProtocolFactory, + int port, + boost::shared_ptr const& threadManager = + boost::shared_ptr(), + int nWorkers = T_ASYNC_DEFAULT_WORKER_THREADS, + THRIFT_OVERLOAD_IF(Processor, TProcessor)) : + apache::thrift::server::TServer(processor), + maxConnectionPoolSize_(T_ASYNC_MAX_CONNECTION_POOL_SIZE), + port_(port), + socket_(NULL), + serveEventBase_(NULL), + nWorkers_(nWorkers), + timeout_(0), + eventBaseManager_(), + workerChoice_(0), + maxFrameSize_(T_ASYNC_DEFAULT_MAX_FRAME_SIZE), + readBufferDefaultSize_(T_ASYNC_READ_BUFFER_DEFAULT_SIZE), + writeBufferDefaultSize_(T_ASYNC_WRITE_BUFFER_DEFAULT_SIZE), + idleReadBufferLimit_(T_ASYNC_IDLE_READ_BUFFER_LIMIT), + idleWriteBufferLimit_(T_ASYNC_IDLE_WRITE_BUFFER_LIMIT), + resizeBufferEveryN_(T_ASYNC_RESIZE_BUFFER_EVERY_N), + callTimeout_(0), + taskExpireTime_(0), + queuingMode_(true), + acceptRateAdjustSpeed_(0), + maxNumMsgsInPipe_(T_MAX_NUM_MESSAGES_IN_PIPE), + maxNumActiveConnectionsPerWorker_(0), + transportType_(T_ASYNC_DEFAULT_TRANSPORT_TYPE) { + setDuplexProtocolFactory(duplexProtocolFactory); + setThreadManager(threadManager); + } + + virtual ~TEventServer() { + } + + /** + * + */ + void setSSLContext(boost::shared_ptr context) { + sslContext_ = context; + } + + boost::shared_ptr getSSLContext() const { + return sslContext_; + } + + /** + * Use the provided socket rather than binding to port_. The caller must + * call ::bind on this socket, but should not call ::listen. + * + * NOTE: TEventServe takes ownership of this 'socket' so if binding fails + * we destroy this socket, while cleaning itself up. So, 'accept' better + * work the first time :) + */ + void useExistingSocket(int socket); + + /** + * Return the file descriptor associated with the listening socket + */ + int getListenSocket() const; + + /** + * Get the TAsyncProcessorFactory object used by this server. + * + * @return a pointer to the processorFactory. + */ + boost::shared_ptr getAsyncProcessorFactory() const { + return asyncProcessorFactory_; + } + + /** + * Set the TAsyncProcessor object used by this server. + */ + void setAsyncProcessorFactory(boost::shared_ptr pf) { + asyncProcessorFactory_ = pf; + } + + /** + * Get the TEventBase used by the current thread. + * This will be different between each worker and the listener. Use this + * for any event monitoring within a processor and be careful NOT to + * cache between connections (since they may be executed by different + * workers). + * + * @return a pointer to the TEventBase. + */ + TEventBase* getEventBase() const { + return eventBaseManager_.getEventBase(); + } + + /** + * Get the TEventServer's main event base. + * + * @return a pointer to the TEventBase. + */ + TEventBase* getServeEventBase() const { + return serveEventBase_; + } + + /** + * Get the TEventBaseManager used by this server. + * This can be used to find or create the TEventBase associated with + * any given thread, including any new threads created by clients. + * + * @return a pointer to the TEventBaseManager. + */ + TEventBaseManager* getEventBaseManager() { + return &eventBaseManager_; + } + const TEventBaseManager* getEventBaseManager() const { + return &eventBaseManager_; + } + + /** + * Set the port to serve + */ + void setPort(uint16_t port) { + port_ = port ; + } + + /** + *Set the maximum number of inactive connection objects pooled. + * Since these objects consume memory, we need to limit how many we keep. + * You can disable pooling altogether by setting this to zero. Note that + * the actual maximum is nWorkers*size since each worker thread maintains + * its own pool (to avoid the need for locks). + * + * @param size the maximum number of inactive connections to pool. + */ + void setMaxConnectionPoolSize(uint32_t size) { + maxConnectionPoolSize_ = size; + } + + /** Get the maximum number of inactive connection objects pooled. + @return the maximum pool size. + */ + uint32_t getMaxConnectionPoolSize() const { + return maxConnectionPoolSize_; + } + + /** + * Get the maximum number of unprocessed messages which a NotificationPipe + * can hold. + */ + uint32_t getMaxNumMessagesInPipe() const { + return maxNumMsgsInPipe_; + } + /** + * Set the maximum number of unprocessed messages in NotificationPipe. + * No new message will be sent to that NotificationPipe if there are more + * than such number of unprocessed messages in that pipe. + */ + void setMaxNumMessagesInPipe(uint32_t num) { + maxNumMsgsInPipe_ = num; + } + + /** + * Get the maxmum number of active connections each TAsyncWorker can have + */ + int32_t getMaxNumActiveConnectionsPerWorker() const { + return maxNumActiveConnectionsPerWorker_; + } + + /** + * Set the maxmum number of active connections each TAsyncWorker can have. + * Zero means unlimited + */ + void setMaxNumActiveConnectionsPerWorker(int32_t num) { + maxNumActiveConnectionsPerWorker_ = num; + } + + /** + * Get the speed of adjusting connection accept rate. + */ + double getAcceptRateAdjustSpeed() const { + return acceptRateAdjustSpeed_; + } + + /** + * Set the speed of adjusting connection accept rate. + */ + void setAcceptRateAdjustSpeed(double speed) { + acceptRateAdjustSpeed_ = speed; + } + + /** + * Get the number of connections dropped by the TAsyncServerSocket + */ + uint64_t getNumDroppedConnections() const; + + /** Reset the maximum number of inactive connection objects to the default. + */ + void resetMaxConnectionPoolSize() { + setMaxConnectionPoolSize(T_ASYNC_MAX_CONNECTION_POOL_SIZE); + } + + /** Get maximum number of milliseconds we'll wait for data (0 = infinity). + * + * @return number of milliseconds, or 0 if no timeout set. + */ + int getRecvTimeout() const { + return timeout_; + } + + /** Set maximum number of milliseconds we'll wait for data (0 = infinity). + * Note: existing connections are unaffected by this call. + * + * @param timeout number of milliseconds, or 0 to disable timeouts. + */ + void setRecvTimeout(int timeout) { + timeout_ = timeout; + } + + /** Set the maximum frame size server will accept. + * + * @param size the maximum size in bytes of a frame we'll accept. + */ + void setMaxFrameSize(uint32_t size) { + maxFrameSize_ = size; + } + + /** Get the maximum frame size server will accept. + * + * @return the maximum pool size. + */ + uint32_t getMaxFrameSize() const { + return maxFrameSize_; + } + + /** + * Get the starting size of a TEventConnection object's read buffer. + * + * @return # bytes we init a TEventConnection object's read buffer to. + */ + size_t getReadBufferDefaultSize() const { + return readBufferDefaultSize_; + } + + /** + * Set the starting size of a TEventConnection object's read buffer. + * + * @param size # bytes we init a TEventConnection object's read buffer to. + */ + void setReadBufferDefaultSize(size_t size) { + readBufferDefaultSize_ = size; + } + + /** + * Get the starting size of a TEventConnection object's write buffer. + * + * @return # bytes we init a TEventConnection object's write buffer to. + */ + size_t getWriteBufferDefaultSize() const { + return writeBufferDefaultSize_; + } + + /** + * Set the starting size of a TEventConnection object's write buffer. + * + * @param size # bytes we init a TEventConnection object's write buffer to. + */ + void setWriteBufferDefaultSize(size_t size) { + writeBufferDefaultSize_ = size; + } + + /** + * Get the maximum size of read buffer allocated to idle TConnection objects. + * + * @return # bytes beyond which we will shrink buffers when idle. + */ + size_t getIdleReadBufferLimit() const { + return idleReadBufferLimit_; + } + + /** + * Set the maximum size read buffer allocated to idle TEventConnection + * objects. If a TEventConnection object is found (either on connection + * close or between calls when resizeBufferEveryN_ is set) with more than + * this much memory + * allocated to its read buffer, we shrink it to this value. + * + * @param limit of bytes beyond which we will shrink buffers when checked. + */ + void setIdleReadBufferLimit(size_t limit) { + idleReadBufferLimit_ = limit; + } + + /** + * Get the maximum size of write buffer allocated to idle TEventConnection + * objects. + * + * @return # bytes beyond which we will reallocate buffers when checked. + */ + size_t getIdleWriteBufferLimit() const { + return idleWriteBufferLimit_; + } + + /** + * Set the maximum size write buffer allocated to idle TEventConnection + * objects. If a TEventConnection object is found (either on connection + * close or between calls when resizeBufferEveryN_ is set) with more than + * this much memory allocated to its write buffer, we destroy and construct + * that buffer. + * + * @param limit of bytes beyond which we will shrink buffers when idle. + */ + void setIdleWriteBufferLimit(size_t limit) { + idleWriteBufferLimit_ = limit; + } + + /** + * Get # of calls made between buffer size checks. 0 means disabled. + * + * @return # of calls between buffer size checks. + */ + int32_t getResizeBufferEveryN() const { + return resizeBufferEveryN_; + } + + /** + * Check buffer sizes every "count" calls. This allows buffer limits + * to be enforced for persistant connections with a controllable degree + * of overhead. 0 disables checks except at connection close. + * + * @param count the number of calls between checks, or 0 to disable + */ + void setResizeBufferEveryN(int32_t count) { + resizeBufferEveryN_ = count; + } + + /** + * Set a call timeout in milliseconds. + * + * When a worker's TEventBase starts taking longer than this amount of time + * to process a single loop, start dropping connections to reduce loadj + * + * TODO: This should be renamed something other than "call timeout" + * + * @param milliseconds the call timeout (0 inhibits) + */ + void setCallTimeout(int32_t milliseconds) { + callTimeout_ = milliseconds; + } + + /** + * Get the call timeout in milliseconds. 0 (default) disables. + * + * @return the call timeout in milliseconds + */ + int32_t getCallTimeout() const { + return callTimeout_; + } + + /** + * Set Thread Manager (for queuing mode). + * + * @param threadManager a shared pointer to the thread manager + */ + void setThreadManager(boost::shared_ptr + threadManager) { + threadManager_ = threadManager; + } + + /** + * Get Thread Manager (for queuing mode). + * + * @return a shared pointer to the thread manager + */ + boost::shared_ptr getThreadManager() { + return threadManager_; + } + + /** + * Get the task expire time (for queuing mode). + * + * @return task expire time + */ + int64_t getTaskExpireTime() const { + return taskExpireTime_; + } + + /** + * Return whether we are in queuing mode or not. + * + * @return true if we are in queuing mode, false if not. + */ + bool queuingMode() const { + return queuingMode_; + } + + /** + * Set the transport type to use + * + * @param transportType transport type + */ + void setTransportType(TransportType transportType) { + + /*********** Deprecation Warning ******************* + * * + * The unframed transports are deprecated ! * + * They should be used for legancy services only * + * Also note: they only works with TBinaryProtocol * + ***************************************************/ + + if (transportType == UNFRAMED_BINARY && + !dynamic_cast( + getDuplexProtocolFactory()->getInputProtocolFactory().get())) { + throw TLibraryException( + "UnFramedTransport can only be used with TBinaryProtocol"); + } else if (transportType == HEADER && + !dynamic_cast( + getDuplexProtocolFactory()->getInputProtocolFactory().get())) { + throw TLibraryException( + "HEADER transport can only be used with THeaderProtocol"); + } + + transportType_ = transportType; + } + + /** + * Get the transport type to use + * + * @return transport type + */ + TransportType getTransportType() { + return transportType_; + } + + + /** + * Call this to complete initialization + */ + void setup(); + + /** + * Kill the workers and wait for listeners to quit + */ + void cleanUp(); + + /** + * One stop solution: + * + * starts worker threads, enters accept loop; when + * the accept loop exits, shuts down and joins workers. + */ + void serve(); + + /** + * Call this to stop the server, if started by serve() + * + * This causes the main serve() function to stop listening for new + * connections, closes existing connections, shut down the worker threads, + * and then return. + */ + void stop(); + + /** + * Call this to stop listening on the server port. + * + * This causes the main serve() function to stop listening for new + * connections while still allows the worker threads to process + * existing connections. stop() still needs to be called to clear + * up the worker threads. + */ + void stopListening(); + + /** + * Terminate a given pending task. Callable by the thread manager or + * from the server context. + */ + void expireClose( + boost::shared_ptr task); + + /** + * In task queue mode, drop a task from the head of the queue and shut + * down the associated connection. + */ + bool drainPendingTask(); + + /** + * Get the TConnectionContext for the connection currently being processed. + * + * This is intended to be invoked from within the TAsyncProcessor (or the + * handler used by the TProcessor). + * + * @return Return a pointer to the TConnectionContext for the current + * connection, or NULL if invoked outside of a call to + * TAsyncProcessor::process(). The returned TConnectionContext + * object is guaranteed to remain valid until the + * TAsyncProcessor invokes its success or error callback. However, + * getConnectionContext() may return NULL when invoked after + * process() has returned. + * + * In other words, async handlers may continue using the + * TConnectionContext object for the duration of the handler + * processing. However, they must retrieve the TConnectionContext + * inside the call to process() and cache it for later use if + * they need it later. + */ + virtual server::TConnectionContext* getConnectionContext() const; + + // We use this to get the processor when in task queue mode + using TServer::getProcessor; +}; + +}}} // apache::thrift::async + +#endif // #ifndef THRIFT_ASYNC_TEVENTSERVER_H_ diff --git a/thrift/lib/cpp/async/TEventTask.h b/thrift/lib/cpp/async/TEventTask.h new file mode 100644 index 00000000..ab21081c --- /dev/null +++ b/thrift/lib/cpp/async/TEventTask.h @@ -0,0 +1,49 @@ +#ifndef _THRIFT_TEVENTTASK_H_ +#define _THRIFT_TEVENTTASK_H_ 1 + +#include "thrift/lib/cpp/Thrift.h" +#include "thrift/lib/cpp/server/TServer.h" +#include "thrift/lib/cpp/transport/TBufferTransports.h" +#include "thrift/lib/cpp/concurrency/ThreadManager.h" +#include "thrift/lib/cpp/async/TEventConnection.h" +#include +#include +#include "thrift/lib/cpp/TProcessor.h" +#include "thrift/lib/cpp/protocol/TProtocol.h" + +namespace apache { namespace thrift { namespace async { + +class TEventTask : public apache::thrift::concurrency::Runnable { + public: + explicit TEventTask(TEventConnection* connection); + + void run(); + + TEventConnection* getConnection() const { + return connection_; + } + + private: + boost::shared_ptr processor_; + boost::shared_ptr input_; + boost::shared_ptr output_; + TEventConnection* connection_; + TConnectionContext* connectionContext_; +}; + +class TaskCompletionMessage { + public: + explicit TaskCompletionMessage(TEventConnection *inConnection) + : connection(inConnection) {} + + TaskCompletionMessage(TaskCompletionMessage &&msg) + : connection(msg.connection) { + msg.connection = NULL; + } + + TEventConnection *connection; +}; + +} } } // namespace apache::thrift::async + +#endif // !_THRIFT_TEVENTTASK_H_ diff --git a/thrift/lib/cpp/async/TEventUtil.h b/thrift/lib/cpp/async/TEventUtil.h new file mode 100644 index 00000000..4d0b62b6 --- /dev/null +++ b/thrift/lib/cpp/async/TEventUtil.h @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TEVENTUTIL_H_ +#define THRIFT_ASYNC_TEVENTUTIL_H_ 1 + +#include // libevent + +namespace apache { namespace thrift { namespace async { + +/** + * low-level libevent utility functions + */ +class TEventUtil { + public: + static bool isEventRegistered(const struct event* ev) { + // If any of these flags are set, the event is registered. + enum { + EVLIST_REGISTERED = (EVLIST_INSERTED | EVLIST_ACTIVE | + EVLIST_TIMEOUT | EVLIST_SIGNAL) + }; + return (ev->ev_flags & EVLIST_REGISTERED); + } +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TEVENTUTIL_H_ diff --git a/thrift/lib/cpp/async/TEventWorker.h b/thrift/lib/cpp/async/TEventWorker.h new file mode 100644 index 00000000..8fcbd21c --- /dev/null +++ b/thrift/lib/cpp/async/TEventWorker.h @@ -0,0 +1,276 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef THRIFT_SERVER_TEVENTWORKER_H_ +#define THRIFT_SERVER_TEVENTWORKER_H_ 1 + +#include "thrift/lib/cpp/async/TAsyncServerSocket.h" +#include "thrift/lib/cpp/async/TAsyncSSLSocket.h" +#include "thrift/lib/cpp/async/TEventServer.h" +#include "thrift/lib/cpp/async/TEventBase.h" +#include "thrift/lib/cpp/async/TEventHandler.h" +#include "thrift/lib/cpp/async/TNotificationQueue.h" +#include "thrift/lib/cpp/server/TServer.h" +#include +#include +#include + +namespace apache { namespace thrift { namespace async { + +// Forward declaration of classes +class TAsyncProcessorFactory; +class TEventConnection; +class TEventServer; +class TaskCompletionMessage; +/** + * TEventWorker drives the actual I/O for TEventServer connections. + * + * The TEventServer itself accepts incoming connections, then hands off each + * connection to a TEventWorker running in another thread. There should + * typically be around one TEventWorker thread per core. + */ +class TEventWorker : + public apache::thrift::server::TServer, + public TAsyncServerSocket::AcceptCallback, + public TAsyncSSLSocket::HandshakeCallback, + public TNotificationQueue::Consumer { + private: + /// Object that processes requests. + boost::shared_ptr asyncProcessorFactory_; + + /// The mother ship. + TEventServer* server_; + + /// An instance's TEventBase for I/O. + TEventBase eventBase_; + + /// Our ID in [0:nWorkers). + uint32_t workerID_; + + /// Pipe that task completion notifications are sent over + TNotificationQueue notificationQueue_; + + /** + * A stack of idle TEventConnection objects for reuse. + * When we close a connection, we place it on this stack so that the + * object can be reused later, rather than freeing the memory and + * reallocating a new object later. + */ + std::stack connectionStack_; + + /// Transport type to use + TEventServer::TransportType transportType_; + + /** + * Called when the connection is fully accepted (after SSL accept if needed) + */ + void finishConnectionAccepted(TAsyncSocket *asyncSock); + + /** + * Create or reuse a TEventConnection initialized for the given socket FD. + * + * @param socket the FD of a freshly-connected socket. + * @param address the peer address of the socket. + * @return pointer to a TConenction object for that socket. + */ + TEventConnection* createConnection( + boost::shared_ptr asyncSocket, + const transport::TSocketAddress* address); + + /** + * Handler called when a new connection may be available. + */ + void acceptConnections(); + + void makeCompletionCallback(); + + /** + * Initialize our TEventBase to generate incoming connection events. + * Note that this is called once before the main loop is executed and + * sets up a READ event on the output of the listener's socktpair. + */ + void registerEvents(); + + /** + * Callback used when loop latency exceeds the requested threshold. + */ + void maxLatencyCob(); + + typedef std::list ConnectionList; + + // pointer hash functor + static const uint64_t kPtrHashMult = 5700357409661599291LL; + static const uint64_t kPtrHashShift = 3; + template + struct hash { }; + template + struct hash { + size_t operator()(T* p) const { + return ((size_t)p ^ ((size_t)p >> kPtrHashShift)) * kPtrHashMult; + } + size_t operator()(const T* p) const { + return ((size_t)p ^ ((size_t)p >> kPtrHashShift)) * kPtrHashMult; + } + }; + typedef __gnu_cxx::hash_map > ConnectionMap; + + /** + * The list of active connections (used to allow the oldest connections + * to be shed during overload). + */ + ConnectionList activeConnectionList_; + /** + * A hash map used to map connections to their place in the connection list + */ + ConnectionMap activeConnectionMap_; + + // Max number of active connections + int32_t maxNumActiveConnections_; + + public: + + /** + * TEventWorker is the actual server object for existing connections. + * One or more of these should be created by TEventServer (one per + * CPU core is recommended). + * + * @param processorFactory a TAsyncProcessorFactory object as + * obtained from the generated Thrift code (the user service + * is integrated through this). + * @param inputProtocolFactory the TProtocolFactory class supporting + * inbound Thrift requests. + * @param outputProtocolFactory the TProtocolFactory class supporting + * responses (if any) after processing completes. + * @param server the TEventServer which created us. + * @param workerID the ID assigned to this worker + */ + TEventWorker(boost::shared_ptr processorFactory, + boost::shared_ptr + protocolFactory, + TEventServer* server, + uint32_t workerID) : + TServer(boost::shared_ptr()), + asyncProcessorFactory_(processorFactory), + server_(server), + eventBase_(), + workerID_(workerID), + transportType_(TEventServer::FRAMED), + maxNumActiveConnections_(0) { + + setDuplexProtocolFactory(protocolFactory); + transportType_ = server->getTransportType(); + if (transportType_ == TEventServer::FRAMED) { + // do the dynamic cast once rather than per connection + if (dynamic_cast( + protocolFactory.get())) { + transportType_ = TEventServer::HEADER; + } + } + } + + /** + * Destroy a TEventWorker. We've use boost::scoped_ptr<> to take care + * of freeing up memory, so nothing to be done here but release the + * connection stack. + */ + virtual ~TEventWorker(); + + /** + * Get my TAsyncProcessorFactory object. + * + * @returns pointer to my TAsyncProcessorFactory object. + */ + boost::shared_ptr getAsyncProcessorFactory() { + return asyncProcessorFactory_; + } + + /** + * Get my TEventBase object. + * + * @returns pointer to my TEventBase object. + */ + TEventBase* getEventBase() { + return &eventBase_; + } + + /** + * Get underlying server. + * + * @returns pointer to TEventServer + */ + TEventServer* getServer() const { + return server_; + } + + /** + * Get my numeric worker ID (for diagnostics). + * + * @return integer ID of this worker + */ + int32_t getID() { + return workerID_; + } + + void setMaxNumActiveConnections(int32_t numActiveConnections) { + maxNumActiveConnections_ = numActiveConnections; + } + + int32_t getMaxNumActiveConnections() const { + return maxNumActiveConnections_; + } + + /** + * Dispose of a TEventConnection object. + * Will add to a pool of these objects or destroy as necessary. + * + * @param connection a now-idle connection. + */ + void returnConnection(TEventConnection* connection); + + /** + * Cause a completion callback for the requested connection to occur + * within that connection's context. + * + * @param msg task completion message + * @return true if notification was sent, false if it failed. + */ + bool notifyCompletion(TaskCompletionMessage &&msg); + + /** + * Task completed (called in this worker's thread) + */ + void messageAvailable(TaskCompletionMessage &&msg); + + virtual void connectionAccepted(int fd, + const transport::TSocketAddress& clientAddr) + THRIFT_NOEXCEPT; + virtual void acceptError(const std::exception& ex) THRIFT_NOEXCEPT; + virtual void acceptStopped() THRIFT_NOEXCEPT; + + /** + * TAsyncSSLSocket::HandshakeCallback interface + */ + void handshakeSuccess(TAsyncSSLSocket *sock) THRIFT_NOEXCEPT; + void handshakeError(TAsyncSSLSocket *sock, + const transport::TTransportException& ex) THRIFT_NOEXCEPT; + + + /** + * Enter event loop and serve. + */ + void serve(); + + /** + * Exit event loop. + */ + void shutdown(); +}; + +}}} // apache::thrift::async + +#endif // #ifndef THRIFT_SERVER_TEVENTWORKER_H_ diff --git a/thrift/lib/cpp/async/TFramedAsyncChannel.h b/thrift/lib/cpp/async/TFramedAsyncChannel.h new file mode 100644 index 00000000..40a6819e --- /dev/null +++ b/thrift/lib/cpp/async/TFramedAsyncChannel.h @@ -0,0 +1,204 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TFRAMEDASYNCCHANNEL_H_ +#define THRIFT_ASYNC_TFRAMEDASYNCCHANNEL_H_ 1 + +#include "thrift/lib/cpp/async/TStreamAsyncChannel.h" + +namespace apache { namespace thrift { namespace async { + +namespace detail { + +/** + * Encapsulation of one outstanding write request on a TFramedAsyncChannel. + */ +class TFramedACWriteRequest : + public TAsyncChannelWriteRequestBase { + public: + TFramedACWriteRequest(const VoidCallback& callback, + const VoidCallback& errorCallback, + transport::TMemoryBuffer* message, + TAsyncEventChannel* channel); + + void write(TAsyncTransport* transport, + TAsyncTransport::WriteCallback* callback) THRIFT_NOEXCEPT; + + void writeSuccess() THRIFT_NOEXCEPT; + void writeError(size_t bytesWritten, + const transport::TTransportException& ex) THRIFT_NOEXCEPT; + + private: + union { + uint32_t frameSize_; + char frameSizeBuf_[sizeof(uint32_t)]; + }; +}; + +/** + * Read state for TFramedAsyncChannel + */ +class TFramedACReadState { + public: + typedef std::tr1::function VoidCallback; + + TFramedACReadState(); + + // Methods required by TStreamAsyncChannel + + void setCallbackBuffer(transport::TMemoryBuffer* buffer) { + buffer_ = buffer; + bytesRead_ = 0; + } + void unsetCallbackBuffer() { + buffer_ = NULL; + } + + bool hasReadAheadData() { + assert(bytesRead_ == 0); + return false; + } + bool hasPartialMessage() { + return (bytesRead_ > 0); + } + + void getReadBuffer(void** bufReturn, size_t* lenReturn); + bool readDataAvailable(size_t len); + + // Other methods specifict to TFramedAsyncChannel + + void setMaxFrameSize(uint32_t size) { + maxFrameSize_ = size; + } + + uint32_t getMaxFrameSize() const { + return maxFrameSize_; + } + + private: + /// maximum frame size accepted + uint32_t maxFrameSize_; + + union { + uint32_t frameSize_; + char frameSizeBuf_[sizeof(uint32_t)]; + }; + + /** + * The number of bytes read. + * + * This includes the bytes in the frame size. When bytesRead_ is less than + * sizeof(uint32_t), we are still reading the frame size. Otherwise, we have + * read bytesRead_ - sizeof(uint32_t) bytes of the body. + */ + uint32_t bytesRead_; + apache::thrift::transport::TMemoryBuffer* buffer_; +}; + +} // namespace detail + +/** + * TFramedAsyncChannel + * + * This is a TAsyncChannel implementation that reads and writes messages + * prefixed with a 4-byte frame length. + * + * Its messages are compatible with TFramedTransport. + */ +class TFramedAsyncChannel : + public TStreamAsyncChannel { + private: + typedef TStreamAsyncChannel Parent; + + public: + explicit TFramedAsyncChannel( + const boost::shared_ptr& transport + ) + : Parent(transport) {} + + /** + * Helper function to create a shared_ptr. + * + * This passes in the correct destructor object, since TFramedAsyncChannel's + * destructor is protected and cannot be invoked directly. + */ + static boost::shared_ptr newChannel( + const boost::shared_ptr& transport) { + return boost::shared_ptr( + new TFramedAsyncChannel(transport), Destructor()); + } + + /// size in bytes beyond which we'll reject a given frame size. + void setMaxFrameSize(uint32_t size) { + readState_.setMaxFrameSize(size); + } + + uint32_t getMaxFrameSize() const { + return readState_.getMaxFrameSize(); + } + + protected: + /** + * Protected destructor. + * + * Users of TFramedAsyncChannel must never delete it directly. Instead, + * invoke destroy(). + */ + virtual ~TFramedAsyncChannel() { } +}; + +class TFramedAsyncChannelFactory : public TStreamAsyncChannelFactory { + public: + TFramedAsyncChannelFactory() + : maxFrameSize_(0x7fffffff) + , recvTimeout_(0) + , sendTimeout_(0) {} + + void setMaxFrameSize(uint32_t bytes) { + maxFrameSize_ = bytes; + } + + void setRecvTimeout(uint32_t milliseconds) { + recvTimeout_ = milliseconds; + } + + void setSendTimeout(uint32_t milliseconds) { + sendTimeout_ = milliseconds; + } + + virtual boost::shared_ptr newChannel( + const boost::shared_ptr& transport) { + boost::shared_ptr channel( + TFramedAsyncChannel::newChannel(transport)); + transport->setSendTimeout(sendTimeout_); + channel->setMaxFrameSize(maxFrameSize_); + channel->setRecvTimeout(recvTimeout_); + return channel; + } + + private: + uint32_t maxFrameSize_; + uint32_t recvTimeout_; + uint32_t sendTimeout_; +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TFRAMEDASYNCCHANNEL_H_ diff --git a/thrift/lib/cpp/async/THeaderAsyncChannel.h b/thrift/lib/cpp/async/THeaderAsyncChannel.h new file mode 100644 index 00000000..ecb77c3f --- /dev/null +++ b/thrift/lib/cpp/async/THeaderAsyncChannel.h @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_THEADERASYNCCHANNEL_H_ +#define THRIFT_ASYNC_THEADERASYNCCHANNEL_H_ 1 + +#include "thrift/lib/cpp/async/TUnframedAsyncChannel.h" + +namespace apache { namespace thrift { namespace async { + +namespace detail { + +/** + * A class to determine the end of a THeaderProtocol message. This is not as + * sophisticated as the logic in THeaderTransport, so it cannot yet handle any + * unframed transports, just THeader and TFramed. However, the previous + * implementation used TFramedAsyncChannel, so the limitation is not new. + */ +class THeaderACProtocolTraits { + public: + + THeaderACProtocolTraits() + : maxMessageSize_(0x7ffffff) {} + + // Methods required by TUnframedACReadState + bool getMessageLength(uint8_t* buffer, + uint32_t bufferLength, + uint32_t* messageLength); + + void setMaxMessageSize(uint32_t maxMessageSize) { + maxMessageSize_ = maxMessageSize; + } + + private: + uint32_t maxMessageSize_; +}; + +} // namespace detail + +/** + * THeaderAsyncChannel + * + * This is a TAsyncChannel implementation that reads and writes + * messages encoded using THeaderProtocol. + */ +class THeaderAsyncChannel : + public TUnframedAsyncChannel { + private: + typedef TUnframedAsyncChannel Parent; + + public: + explicit THeaderAsyncChannel( + const boost::shared_ptr& transport) + : Parent(transport) {} + + /** + * Helper function to create a shared_ptr. + * + * This passes in the correct destructor object, since THeaderAsyncChannel's + * destructor is protected and cannot be invoked directly. + */ + static boost::shared_ptr newChannel( + const boost::shared_ptr& transport) { + return boost::shared_ptr( + new THeaderAsyncChannel(transport), Destructor()); + } + + void setMaxMessageSize(uint32_t size) { + Parent::setMaxMessageSize(size); + readState_.getProtocolTraits()->setMaxMessageSize(size); + } + + // Note that we inherit getMaxMessageSize() from TUnframedAsyncChannel. + + protected: + /** + * Protected destructor. + * + * Users of THeaderAsyncChannel must never delete it directly. Instead, + * invoke destroy(). + */ + virtual ~THeaderAsyncChannel() { } +}; + +class THeaderAsyncChannelFactory : public TStreamAsyncChannelFactory { + public: + THeaderAsyncChannelFactory() + : maxMessageSize_(0x7fffffff) + , recvTimeout_(0) + , sendTimeout_(0) {} + + void setMaxMessageSize(uint32_t bytes) { + maxMessageSize_ = bytes; + } + + void setRecvTimeout(uint32_t milliseconds) { + recvTimeout_ = milliseconds; + } + + void setSendTimeout(uint32_t milliseconds) { + sendTimeout_ = milliseconds; + } + + virtual boost::shared_ptr newChannel( + const boost::shared_ptr& transport) { + boost::shared_ptr channel( + THeaderAsyncChannel::newChannel(transport)); + transport->setSendTimeout(sendTimeout_); + channel->setMaxMessageSize(maxMessageSize_); + channel->setRecvTimeout(recvTimeout_); + return channel; + } + + private: + uint32_t maxMessageSize_; + uint32_t recvTimeout_; + uint32_t sendTimeout_; +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_THEADERASYNCCHANNEL_H_ diff --git a/thrift/lib/cpp/async/THttpAsyncChannel.h b/thrift/lib/cpp/async/THttpAsyncChannel.h new file mode 100644 index 00000000..9eafc3a8 --- /dev/null +++ b/thrift/lib/cpp/async/THttpAsyncChannel.h @@ -0,0 +1,204 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_THTTPASYNCCHANNEL_H_ +#define THRIFT_ASYNC_THTTPASYNCCHANNEL_H_ 1 + +#include "thrift/lib/cpp/async/TStreamAsyncChannel.h" +#include "thrift/lib/cpp/util/THttpParser.h" + +namespace apache { namespace thrift { namespace async { + +class THttpAsyncChannel; + +namespace detail { + +/** + * Encapsulation of one outstanding write request on a THttpAsyncChannel. + */ +class THttpACWriteRequest : + public TAsyncChannelWriteRequestBase { + public: + typedef std::tr1::function VoidCallback; + + THttpACWriteRequest(const VoidCallback& callback, + const VoidCallback& errorCallback, + transport::TMemoryBuffer* message, + TAsyncEventChannel* channel); + + void write(TAsyncTransport* transport, + TAsyncTransport::WriteCallback* callback) THRIFT_NOEXCEPT; + + void writeSuccess() THRIFT_NOEXCEPT; + void writeError(size_t bytesWritten, + const transport::TTransportException& ex) THRIFT_NOEXCEPT; + + private: + char lengthBuf_[64]; + THttpAsyncChannel* channel_; +}; + +/** + * Read state for THttpAsyncChannel + */ +class THttpACReadState { + public: + typedef std::tr1::function VoidCallback; + + THttpACReadState() { + } + + // Methods required by TStreamAsyncChannel + + void setCallbackBuffer(transport::TMemoryBuffer* buffer) { + parser_->setDataBuffer(buffer); + } + void unsetCallbackBuffer() { + parser_->unsetDataBuffer(); + } + + bool hasReadAheadData() { + return parser_->hasReadAheadData(); + } + bool hasPartialMessage() { + return parser_->hasPartialMessage(); + } + + void getReadBuffer(void** bufReturn, size_t* lenReturn); + bool readDataAvailable(size_t len); + + // Other methods specific to THttpAsyncChannel + void setParser(boost::shared_ptr parser) { + parser_ = parser; + } + private: + boost::shared_ptr parser_; +}; + +} // namespace detail + +/** + * THttpAsyncChannel + * + * This is a TAsyncChannel implementation that reads and writes messages + * encapuated in HTTP. + * + * Its messages are compatible with THttpTransport. + */ +class THttpAsyncChannel : + public TStreamAsyncChannel { + private: + typedef TStreamAsyncChannel Parent; + boost::shared_ptr parser_; + + public: + explicit THttpAsyncChannel( + const boost::shared_ptr& transport) + : Parent(transport) { + } + + /** + * Helper function to create a shared_ptr. + * + * This passes in the correct destructor object, since THttpAsyncChannel's + * destructor is protected and cannot be invoked directly. + */ + static boost::shared_ptr newChannel( + const boost::shared_ptr& transport) { + return boost::shared_ptr( + new THttpAsyncChannel(transport), Destructor()); + } + + /// size in bytes beyond which we'll reject a given http size. + void setMaxHttpSize(uint32_t size) { + parser_->setMaxSize(size); + } + + uint32_t getMaxHttpSize() const { + return parser_->getMaxSize(); + } + + void setParser(boost::shared_ptr parser) { + parser_ = parser; + readState_.setParser(parser); + } + + boost::shared_ptr getParser() const { + return parser_; + } + + int constructHeader(iovec* ops, + int opsLen, + int contentLength, + char* contentLengthBuf) { + return parser_->constructHeader(ops, + opsLen, + contentLength, + contentLengthBuf); + } + + protected: + /** + * Protected destructor. + * + * Users of THttpAsyncChannel must never delete it directly. Instead, + * invoke destroy(). + */ + virtual ~THttpAsyncChannel() { } +}; + +class THttpAsyncChannelFactory : public TStreamAsyncChannelFactory { + public: + THttpAsyncChannelFactory() + : maxHttpSize_(0x7fffffff) + , recvTimeout_(0) + , sendTimeout_(0) {} + + void setMaxHttpSize(uint32_t bytes) { + maxHttpSize_ = bytes; + } + + void setRecvTimeout(uint32_t milliseconds) { + recvTimeout_ = milliseconds; + } + + void setSendTimeout(uint32_t milliseconds) { + sendTimeout_ = milliseconds; + } + + virtual boost::shared_ptr newChannel( + const boost::shared_ptr& transport) { + boost::shared_ptr channel( + THttpAsyncChannel::newChannel(transport)); + transport->setSendTimeout(sendTimeout_); + channel->setMaxHttpSize(maxHttpSize_); + channel->setRecvTimeout(recvTimeout_); + return channel; + } + + private: + uint32_t maxHttpSize_; + uint32_t recvTimeout_; + uint32_t sendTimeout_; +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_THTTPASYNCCHANNEL_H_ diff --git a/thrift/lib/cpp/async/TNotificationPipe.h b/thrift/lib/cpp/async/TNotificationPipe.h new file mode 100644 index 00000000..40b2f51d --- /dev/null +++ b/thrift/lib/cpp/async/TNotificationPipe.h @@ -0,0 +1,337 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TNOTIFICATIONPIPE_H +#define THRIFT_ASYNC_TNOTIFICATIONPIPE_H 1 + +#include "thrift/lib/cpp/async/TDelayedDestruction.h" +#include "thrift/lib/cpp/async/TEventBase.h" +#include "thrift/lib/cpp/async/TEventHandler.h" +#include "thrift/lib/cpp/concurrency/Mutex.h" +#include +#include +#include + +namespace apache { namespace thrift { namespace async { + +/** + * A simple notification pipe for sending messages to a TEventBase thread. + * + * TNotificationPipe is a unidirectional pipe for sending small, atomic + * messages. + * + * TNotificationPipe cannot be send messages larger than a fixed size. + * TNotificationPipe::kMaxMessageSize defines the maximum message size + * supported. If you need to pass larger amounts of data between threads, + * consider just passing a pointer to the data over the pipe, and using some + * external mechanism to synchronize management of the memory. + * + * + * TNotificationPipe provides two parallel APIs for writing and closing the + * pipe: a thread-safe version and a non-thread-safe version. Which version to + * use depends on how the caller uses the pipe: + * + * - If there is only a single writer thread, you can use the non-thread-safe + * versions of trySendMessage() and close(). This guarantees close() is + * never called by one thread while another thread is attempting to send a + * message. + * + * - If there are multiple writers, but the pipe is never closed by the + * writers, you can use the non-thread-safe version of trySendMessage(). + * Multiple simultaneous trySendMessage() calls will not interfere with each + * other. Since none of the writer threads call close, a call to close() + * cannot be running simultaneously with a write attempt. (With this model, + * the TNotificationPipe is never closed until it is destroyed. It is up to + * the caller to ensure the TNotificationPipe is not destroyed while write + * threads still have a pointer or reference to it.) + * + * In other circumstances (if one thread may call close while another thread is + * simultaneously trying to write), the thread-safe versions + * trySendMessageSync() and closeSync() must be used. + */ +class TNotificationPipe : public TDelayedDestruction, + private TEventHandler, + private TEventBase::LoopCallback { + public: + /** + * A callback interface for receiving notification of messages from the pipe. + */ + class Callback { + public: + virtual ~Callback() {} + + /** + * notificationMessage() will be invoked whenever a new + * message is available from the pipe. + */ + virtual void notificationMessage(const void *msg, uint32_t msgSize) = 0; + + /** + * notificationPipeError() will be invoked if an error occurs while reading + * from the pipe. Before notificationPipeError() is invoked, the read + * callback will automatically be uninstalled and the pipe will be closed. + */ + virtual void notificationPipeError(const std::exception& ex) = 0; + + /** + * notificationPipeClosed() is invoked in the read thread after the write + * end of the pipe is closed. + */ + virtual void notificationPipeClosed() = 0; + }; + + /** + * Helper function to create a new shared_ptr. + * + * This simply sets the correct destructor to call destroy() instead of + * directly deleting the TNotificationPipe. + */ + static boost::shared_ptr newPipe(TEventBase *base) { + return boost::shared_ptr(new TNotificationPipe(base), + Destructor()); + } + + /** + * Create a new TNotificationPipe. + * + * @param eventBase The TEventBase to use for receiving read notifications + * from this pipe. All read events will be processed in this + * TEventBase's thread. trySendMessage() may be called from any thread. + */ + TNotificationPipe(TEventBase *eventBase); + + /** + * Destroy this TNotificationPipe. + * + * This method may only be called from the read thread. + * + * This will automatically close the pipe if it is not already closed. + */ + virtual void destroy(); + + /** + * Close the pipe. + * + * This version of close() is not thread-safe. It should only be used if the + * caller is sure no other thread is attempting to write a message at the + * same time. + * + * Use closeSync() if other threads may be attempting to send a message + * simultaneously. The other threads must use also use the thread-safe + * trySendMessageSync() or trySendFrameSync() calls. + */ + void close(); + + /** + * A thread-safe version of close(). + */ + void closeSync(); + + /** + * Send a message over the pipe. + * + * trySendMessage() is best-effort. It will either immediately succeed to + * send the message, or it will fail immediately if the pipe reader is too + * busy and it's backlog of unread messages is too large. + * + * trySendMessage() also does not support arbitrarily large messages. + * It will also fail immediately if msgSize is larger than (PIPE_BUF - 4). + * + * If trySendMessage() succeeds, the message is guaranteed to be delivered to + * the pipe reader, except in the case where the pipe reader explicitly stops + * reading and destroys the pipe before processing all of its messages. + * + * On failure a TTransportException is thrown. The error code will be + * TTransportException::BAD_ARGS if the message is too large, + * TTransportException::TIMED_OUT if the message cannot be sent right now + * because the pipe is full, or TTransportException::NOT_OPEN if the pipe has + * already been closed. + * + * This method is thread safe with other simultaneous trySendMessage() calls, + * but not with close() calls. Use trySendMessageSync() and closeSync() if a + * close may occur simultaneously on another thread. + */ + void trySendMessage(const void *msg, uint32_t msgSize); + + /** + * A thread-safe version of trySendMessage(). + * + * This may be called simultaneously with closeSync(). + */ + void trySendMessageSync(const void *msg, uint32_t msgSize); + + /** + * Send a message over the pipe. + * + * This is identical to trySendMessage(), except that the caller must provide + * 4 bytes at the beginning of the message where we can write a frame length. + * This allows us to avoid copying the message into a new buffer. + * (trySendMessage() always has to make a copy of the message.) + * + * @param frame A pointer to the frame buffer. trySendFrame() will + * overwrite the first 4 bytes of this buffer. When the read callback + * receives the message, it will not see these first 4 bytes. + * @param frameSize The full size of the frame buffer. This must be at + * least 4 bytes long. The actual message size that will be sent is + * frameSize - 4. + */ + void trySendFrame(void *frame, uint32_t frameSize); + + /** + * A thread-safe version of trySendFrame(). + * + * This may be called simultaneously with closeSync(). + */ + void trySendFrameSync(void *frame, uint32_t frameSize); + + /** + * Get the number of messages which haven't been processed. + */ + int64_t getNumNotProcessed() const { + return numInputs_ - numOutputs_; + } + + /** + * Set the callback to receive read notifications from this pipe. + * + * This method must be invoked from the pipe's read thread. + * + * May throw TLibraryException on error. The callback will always be unset + * (NULL) after an error. + */ + void setReadCallback(Callback *callback); + + /** + * Mark the pipe read event handler as an "internal" event handler. + * + * This causes the notification pipe not to be counted when determining if + * the TEventBase has any more active events to wait on. This is intended to + * be used only be internal TEventBase code. This API is not guaranteed to + * remain stable or portable in the future. + * + * May throw TLibraryException if it fails to re-register its event handler + * with the correct flags. + */ + void setInternal(bool internal); + + /** + * Get the maximum number of messages that will be read on a single iteration + * of the event loop. + */ + uint32_t getMaxReadAtOnce() const { + return maxReadAtOnce_; + } + + /** + * Set the maximum number of messages to read each iteration of the event + * loop. + * + * If messages are being received faster than they can be processed, this + * helps limit the rate at which they will be read. This can be used to + * prevent the notification pipe reader from starving other users of the + * event loop. + */ + void setMaxReadAtOnce(uint32_t numMessages) { + maxReadAtOnce_ = numMessages; + } + + /** + * The maximum message size that can be sent over a TNotificationPipe. + * + * This restriction ensures that trySendMessage() can send all messages + * atomically. This is (PIPE_BUF - 4) bytes. (On Linux, this is 4092 + * bytes.) + */ + static const uint32_t kMaxMessageSize = PIPE_BUF - 4; + + /** + * The default maximum number of messages that will be read each time around + * the event loop. + * + * This value used for each TNotificationPipe can be changed using the + * setMaxReadAtOnce() method. + */ + static const uint32_t kDefaultMaxReadAtOnce = 10; + + private: + enum ReadAction { + kDoNothing, + kContinue, + kWaitForRead, + kRunInNextLoop, + }; + + // Forbidden copy constructor and assignment opererator + TNotificationPipe(TNotificationPipe const &); + TNotificationPipe& operator=(TNotificationPipe const &); + + // TEventHandler methods + virtual void handlerReady(uint16_t events) THRIFT_NOEXCEPT; + + // TEventBase::LoopCallback methods + virtual void runLoopCallback() THRIFT_NOEXCEPT; + + void initPipe(); + void registerPipeEvent(); + void readMessages(ReadAction action); + ReadAction performRead(); + ReadAction processReadData(uint32_t* messagesProcessed); + ReadAction handleError(const char* fmt, ...) + __attribute__((format(printf, 2, 3))); + void checkMessage(uint32_t msgSize); + void writeFrame(const void *frame, uint32_t frameSize); + + TEventBase *eventBase_; + Callback *readCallback_; + int readPipe_; + int writePipe_; + bool internal_; + uint32_t maxReadAtOnce_; + int64_t numInputs_; + int64_t numOutputs_; + + /** + * Mutex for guarding numInputs_ + */ + concurrency::Mutex numInputsMutex_; + + /** + * A mutex that guards writePipe_. + * + * This is used by closeSync(), trySendMessageSync(), and trySendFrameSync(), + * since trySendMessageSync() and trySendFrameSync() read writePipe_ + * and closeSync() resets it to -1. + */ + concurrency::NoStarveReadWriteMutex writePipeMutex_; + + /** + * A pointer to the end of valid read data in the read buffer. + */ + uint8_t *readPtr_; + /** + * An internal read buffer + * + * This is large enough to contain the maximum possible message plus the + * mssage length. + */ + uint8_t readBuffer_[kMaxMessageSize + 4]; +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TNOTIFICATIONPIPE_H diff --git a/thrift/lib/cpp/async/TNotificationQueue.h b/thrift/lib/cpp/async/TNotificationQueue.h new file mode 100644 index 00000000..e2538e07 --- /dev/null +++ b/thrift/lib/cpp/async/TNotificationQueue.h @@ -0,0 +1,592 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TNOTIFICATIONQUEUE_H_ +#define THRIFT_ASYNC_TNOTIFICATIONQUEUE_H_ 1 + +#include "thrift/lib/cpp/Thrift.h" +#include "thrift/lib/cpp/async/TEventBase.h" +#include "thrift/lib/cpp/async/TEventHandler.h" + +#include "external/google_base/spinlock.h" +#include "external/glog/logging.h" +#include +#include "folly/eventfd.h" + +namespace apache { namespace thrift { namespace async { + +/** + * An exception class to be thrown when a TNotificationQueue is full. + */ +class TQueueFullException : public TLibraryException { + public: + TQueueFullException() : + TLibraryException("unable to add message to TNotificationQueue: " + "queue is full") {} +}; + +/** + * A producer-consumer queue for passing messages between TEventBase threads. + * + * Messages can be added to the queue from any thread. Multiple consumers may + * listen to the queue from multiple TEventBase threads. + * + * A TNotificationQueue may not be destroyed while there are still consumers + * registered to receive events from the queue. It is the user's + * responsibility to ensure that all consumers are unregistered before the + * queue is destroyed. + * + * MessageT should be MoveConstructible (i.e., must support either a move + * constructor or a copy constructor, or both). Ideally it's move constructor + * (or copy constructor if no move constructor is provided) should never throw + * exceptions. If the constructor may throw, the consumers could end up + * spinning trying to move a message off the queue and failing, and then + * retrying. + */ +template +class TNotificationQueue { + public: + /** + * A callback interface for consuming messages from the queue as they arrive. + */ + class Consumer : private TEventHandler { + public: + enum : uint16_t { kDefaultMaxReadAtOnce = 10 }; + + Consumer() + : queue_(NULL), + destroyedFlagPtr_(NULL), + maxReadAtOnce_(kDefaultMaxReadAtOnce) {} + + virtual ~Consumer(); + + /** + * messageAvailable() will be invoked whenever a new + * message is available from the pipe. + */ + virtual void messageAvailable(MessageT&& message) = 0; + + /** + * Begin consuming messages from the specified queue. + * + * messageAvailable() will be called whenever a message is available. This + * consumer will continue to consume messages until stopConsuming() is + * called. + * + * A Consumer may only consume messages from a single TNotificationQueue at + * a time. startConsuming() should not be called if this consumer is + * already consuming. + */ + void startConsuming(TEventBase* eventBase, TNotificationQueue* queue) { + init(eventBase, queue); + registerHandler(READ | PERSIST); + } + + /** + * Same as above but registers this event handler as internal so that it + * doesn't count towards the pending reader count for the IOLoop. + */ + void startConsumingInternal( + TEventBase* eventBase, TNotificationQueue* queue) { + init(eventBase, queue); + registerInternalHandler(READ | PERSIST); + } + + /** + * Stop consuming messages. + * + * startConsuming() may be called again to resume consumption of messages + * at a later point in time. + */ + void stopConsuming(); + + /** + * Get the TNotificationQueue that this consumer is currently consuming + * messages from. Returns NULL if the consumer is not currently consuming + * events from any queue. + */ + TNotificationQueue* getCurrentQueue() const { + return queue_; + } + + /** + * Set a limit on how many messages this consumer will read each iteration + * around the event loop. + * + * This helps rate-limit how much work the Consumer will do each event loop + * iteration, to prevent it from starving other event handlers. + * + * A limit of 0 means no limit will be enforced. If unset, the limit + * defaults to kDefaultMaxReadAtOnce (defined to 10 above). + */ + void setMaxReadAtOnce(uint32_t maxAtOnce) { + maxReadAtOnce_ = maxAtOnce; + } + uint32_t getMaxReadAtOnce() const { + return maxReadAtOnce_; + } + + private: + void init(TEventBase* eventBase, TNotificationQueue* queue); + + virtual void handlerReady(uint16_t events) THRIFT_NOEXCEPT; + + TNotificationQueue* queue_; + bool* destroyedFlagPtr_; + uint32_t maxReadAtOnce_; + }; + + enum class FdType { + EVENTFD, + PIPE + }; + + /** + * Create a new TNotificationQueue. + * + * If the maxSize parameter is specified, this sets the maximum queue size + * that will be enforced by tryPutMessage(). (This size is advisory, and may + * be exceeded if producers explicitly use putMessage() instead of + * tryPutMessage().) + * + * The fdType parameter determines the type of file descriptor used + * internally to signal message availability. The default (eventfd) is + * preferable for performance and because it won't fail when the queue gets + * too long. It is not available on on older and non-linux kernels, however. + * In this case the code will fall back to using a pipe, the parameter is + * mostly for testing purposes. + */ + explicit TNotificationQueue(uint32_t maxSize = 0, + FdType fdType = FdType::EVENTFD) + : spinlock_(), + eventfd_(-1), + pipeFds_{-1, -1}, + advisoryMaxQueueSize_(maxSize), + queue_() { + if (fdType == FdType::EVENTFD) { + eventfd_ = folly::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK | EFD_SEMAPHORE); + if (eventfd_ == -1) { + if (errno == ENOSYS || errno == EINVAL) { + // eventfd not availalble + T_ERROR("failed to create eventfd for TNotificationQueue: %d, " + "falling back to pipe mode", errno); + fdType = FdType::PIPE; + } else { + // some other error + throw TLibraryException("Failed to create eventfd for " + "TNotificationQueue", errno); + } + } + } + if (fdType == FdType::PIPE) { + if (pipe(pipeFds_)) { + throw TLibraryException("Failed to create pipe for TNotificationQueue", + errno); + } + try { + // put both ends of the pipe into non-blocking mode + if (fcntl(pipeFds_[0], F_SETFL, O_RDONLY | O_NONBLOCK) != 0) { + throw TLibraryException("failed to put TNotificationQueue pipe read " + "endpoint into non-blocking mode", errno); + } + if (fcntl(pipeFds_[1], F_SETFL, O_WRONLY | O_NONBLOCK) != 0) { + throw TLibraryException("failed to put TNotificationQueue pipe write " + "endpoint into non-blocking mode", errno); + } + } catch (...) { + ::close(pipeFds_[0]); + ::close(pipeFds_[1]); + throw; + } + } + } + + ~TNotificationQueue() { + if (eventfd_ >= 0) { + ::close(eventfd_); + eventfd_ = -1; + } + if (pipeFds_[0] >= 0) { + ::close(pipeFds_[0]); + pipeFds_[0] = -1; + } + if (pipeFds_[1] >= 0) { + ::close(pipeFds_[1]); + pipeFds_[1] = -1; + } + } + + /** + * Set the advisory maximum queue size. + * + * This maximum queue size affects calls to tryPutMessage(). Message + * producers can still use the putMessage() call to unconditionally put a + * message on the queue, ignoring the configured maximum queue size. This + * can cause the queue size to exceed the configured maximum. + */ + void setMaxQueueSize(uint32_t max) { + advisoryMaxQueueSize_ = max; + } + + /** + * Attempt to put a message on the queue if the queue is not already full. + * + * If the queue is full, a TQueueFullException will be thrown. The + * setMaxQueueSize() function controls the maximum queue size. + * + * This method may contend briefly on a spinlock if many threads are + * concurrently accessing the queue, but for all intents and purposes it will + * immediately place the message on the queue and return. + * + * tryPutMessage() may throw std::bad_alloc if memory allocation fails, and + * may throw any other exception thrown by the MessageT move/copy + * constructor. + */ + void tryPutMessage(MessageT&& message) { + putMessageImpl(std::move(message), advisoryMaxQueueSize_); + } + void tryPutMessage(const MessageT& message) { + putMessageImpl(message, advisoryMaxQueueSize_); + } + + /** + * Unconditionally put a message on the queue. + * + * This method is like tryPutMessage(), but ignores the maximum queue size + * and always puts the message on the queue, even if the maximum queue size + * would be exceeded. + * + * putMessage() may throw std::bad_alloc if memory allocation fails, and may + * throw any other exception thrown by the MessageT move/copy constructor. + */ + void putMessage(MessageT&& message) { + putMessageImpl(std::move(message), 0); + } + void putMessage(const MessageT& message) { + putMessageImpl(message, 0); + } + + /** + * Put several messages on the queue. + */ + template + void putMessages(InputIteratorT first, InputIteratorT last) { + typedef typename std::iterator_traits::iterator_category + IterCategory; + putMessagesImpl(first, last, IterCategory()); + } + + /** + * Try to immediately pull a message off of the queue, without blocking. + * + * If a message is immediately available, the result parameter will be + * updated to contain the message contents and true will be returned. + * + * If no message is available, false will be returned and result will be left + * unmodified. + */ + bool tryConsume(MessageT& result) { + if (!tryConsumeEvent()) { + return false; + } + + try { + facebook::SpinLockHolder guard(&spinlock_); + result = std::move(queue_.front()); + queue_.pop_front(); + } catch (...) { + // Handle an exception if the assignment operator happens to throw. + // We consumed an event but weren't able to pop the message off the + // queue. Signal the event again since the message is still in the + // queue. + signalEvent(1); + throw; + } + + return true; + } + + private: + // Forbidden copy constructor and assignment operator + TNotificationQueue(TNotificationQueue const &) = delete; + TNotificationQueue& operator=(TNotificationQueue const &) = delete; + + inline void checkQueueSize(size_t maxSize) const { + assert(spinlock_.IsHeld()); + if (maxSize > 0 && queue_.size() >= maxSize) { + throw TQueueFullException(); + } + } + + inline void signalEvent(uint64_t numAdded = 1) const { + static const uint8_t kPipeMessage[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + }; + + ssize_t bytes_written = 0; + ssize_t bytes_expected = 0; + if (eventfd_ >= 0) { + bytes_expected = static_cast(sizeof(numAdded)); + bytes_written = ::write(eventfd_, &numAdded, sizeof(numAdded)); + } else { + // pipe semantics, add one message for each numAdded + bytes_expected = numAdded; + do { + size_t messageSize = std::min(numAdded, sizeof(kPipeMessage)); + ssize_t rc = ::write(pipeFds_[1], kPipeMessage, messageSize); + if (rc < 0) { + // TODO: if the pipe is full, write will fail with EAGAIN. + // See task #1044651 for how this could be handled + break; + } + numAdded -= rc; + bytes_written += rc; + } while (numAdded > 0); + } + if (bytes_written != bytes_expected) { + throw TLibraryException("failed to signal TNotificationQueue after " + "write", errno); + } + } + + bool tryConsumeEvent() { + uint64_t value = 0; + ssize_t rc = -1; + if (eventfd_ >= 0) { + rc = ::read(eventfd_, &value, sizeof(value)); + } else { + uint8_t value8; + rc = ::read(pipeFds_[0], &value8, sizeof(value8)); + value = value8; + } + if (rc < 0) { + // EAGAIN should pretty much be the only error we can ever get. + // This means someone else already processed the only available message. + assert(errno == EAGAIN); + return false; + } + assert(value == 1); + return true; + } + + void putMessageImpl(MessageT&& message, size_t maxSize) { + { + facebook::SpinLockHolder guard(&spinlock_); + checkQueueSize(maxSize); + queue_.push_back(std::move(message)); + } + signalEvent(); + } + + void putMessageImpl(const MessageT& message, size_t maxSize) { + { + facebook::SpinLockHolder guard(&spinlock_); + checkQueueSize(maxSize); + queue_.push_back(message); + } + signalEvent(); + } + + template + void putMessagesImpl(InputIteratorT first, InputIteratorT last, + std::input_iterator_tag) { + uint64_t numAdded = 0; + { + facebook::SpinLockHolder guard(&spinlock_); + while (first != last) { + queue_.push_back(*first); + ++first; + ++numAdded; + } + } + signalEvent(numAdded); + } + + template + void putMessagesImpl(InputIteratorT first, InputIteratorT last, + std::forward_iterator_tag) { + uint64_t numAdded = std::distance(first, last); + { + facebook::SpinLockHolder guard(&spinlock_); + queue_.insert(queue_.end(), first, last); + } + signalEvent(numAdded); + } + + facebook::SpinLock spinlock_; + int eventfd_; + int pipeFds_[2]; // to fallback to on older/non-linux systems + uint32_t advisoryMaxQueueSize_; + std::deque queue_; +}; + +template +TNotificationQueue::Consumer::~Consumer() { + // If we are in the middle of a call to handlerReady(), destroyedFlagPtr_ + // will be non-NULL. Mark the value that it points to, so that + // handlerReady() will know the callback is destroyed, and that it cannot + // access any member variables anymore. + if (destroyedFlagPtr_) { + *destroyedFlagPtr_ = true; + } +} + +template +void TNotificationQueue::Consumer::handlerReady(uint16_t events) + THRIFT_NOEXCEPT { + uint32_t numProcessed = 0; + while (true) { + // Try to decrement the eventfd. + // + // We decrement the eventfd before checking the queue, and only pop a + // message off the queue if we read from the eventfd. + // + // Reading the eventfd first allows us to not have to hold the spinlock + // while accessing the eventfd. If we popped from the queue first, we + // would have to hold the lock while reading from or writing to the + // eventfd. (Multiple consumers may be woken up from a single eventfd + // notification. If we popped from the queue first, we could end up + // popping a message from the queue before the eventfd has been notified by + // the producer, unless the consumer and producer both held the spinlock + // around the entire operation.) + if (!queue_->tryConsumeEvent()) { + // no message available right now + return; + } + + // Now pop the message off of the queue. + // We successfully consumed the eventfd notification. + // There should be a message available for us to consume. + // + // We have to manually acquire and release the spinlock here, rather than + // using SpinLockHolder since the MessageT has to be constructed while + // holding the spinlock and available after we release it. SpinLockHolder + // unfortunately doesn't provide a release() method. (We can't construct + // MessageT first since we have no guarantee that MessageT has a default + // constructor. + queue_->spinlock_.Lock(); + bool locked = true; + + try { + // The eventfd is incremented once for every message, and only + // decremented when a message is popped off. There should always be a + // message here to read. + CHECK(!queue_->queue_.empty()); + + // Pull a message off the queue. + MessageT msg(std::move(queue_->queue_.front())); + queue_->queue_.pop_front(); + + // Check to see if the queue is empty now. + // We use this as an optimization to see if we should bother trying to + // loop again and read another message after invoking this callback. + bool wasEmpty = queue_->queue_.empty(); + + // Now unlock the spinlock before we invoke the callback. + queue_->spinlock_.Unlock(); + locked = false; + + // Call the callback + bool callbackDestroyed = false; + CHECK(destroyedFlagPtr_ == NULL); + destroyedFlagPtr_ = &callbackDestroyed; + messageAvailable(std::move(msg)); + + // If the callback was destroyed before it returned, we are done + if (callbackDestroyed) { + return; + } + destroyedFlagPtr_ = NULL; + + // If the callback is no longer installed, we are done. + if (queue_ == NULL) { + return; + } + + // If we have hit maxReadAtOnce_, we are done. + ++numProcessed; + if (maxReadAtOnce_ > 0 && numProcessed >= maxReadAtOnce_) { + return; + } + + // If the queue was empty before we invoked the callback, it's probable + // that it is still empty now. Just go ahead and return, rather than + // looping again and trying to re-read from the eventfd. (If a new + // message had in fact arrived while we were invoking the callback, we + // will simply be woken up the next time around the event loop and will + // process the message then.) + if (wasEmpty) { + return; + } + } catch (const std::exception& ex) { + // This catch block is really just to handle the case where the MessageT + // constructor throws. The messageAvailable() callback itself is + // declared as noexcept and should never throw. + // + // If the MessageT constructor does throw we try to handle it as best as + // we can, but we can't work miracles. We will just ignore the error for + // now and return. The next time around the event loop we will end up + // trying to read the message again. If MessageT continues to throw we + // will never make forward progress and will keep trying each time around + // the event loop. + if (locked) { + // Unlock the spinlock. + queue_->spinlock_.Unlock(); + + // Push a notification back on the eventfd since we didn't actually + // read the message off of the queue. + queue_->signalEvent(1); + } + + return; + } + } +} + +template +void TNotificationQueue::Consumer::init( + TEventBase* eventBase, + TNotificationQueue* queue) { + assert(eventBase->isInEventBaseThread()); + assert(queue_ == NULL); + assert(!isHandlerRegistered()); + + queue_ = queue; + if (queue_->eventfd_ >= 0) { + initHandler(eventBase, queue_->eventfd_); + } else { + initHandler(eventBase, queue_->pipeFds_[0]); + } +} + +template +void TNotificationQueue::Consumer::stopConsuming() { + if (queue_ == NULL) { + assert(!isHandlerRegistered()); + return; + } + + assert(isHandlerRegistered()); + unregisterHandler(); + detachEventBase(); + queue_ = NULL; +} + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TNOTIFICATIONQUEUE_H_ diff --git a/thrift/lib/cpp/async/TQueuingAsyncProcessor.h b/thrift/lib/cpp/async/TQueuingAsyncProcessor.h new file mode 100644 index 00000000..5f2c6498 --- /dev/null +++ b/thrift/lib/cpp/async/TQueuingAsyncProcessor.h @@ -0,0 +1,70 @@ +#ifndef _THRIFT_TQUEUINGASYNCPROCESSOR_H_ +#define _THRIFT_TQUEUINGASYNCPROCESSOR_H_ 1 + +#include +#include +#include "thrift/lib/cpp/TProcessor.h" +#include "thrift/lib/cpp/async/TAsyncProcessor.h" +#include "thrift/lib/cpp/async/TEventTask.h" +#include "thrift/lib/cpp/concurrency/Exception.h" + +namespace apache { namespace thrift { namespace async { + +/** + * Adapter to allow a TProcessor to be used as a TAsyncProcessor. + * + * Note: this is not intended for use outside of TEventConnection since the + * callback mechanism used in TEventTask will invoke handleAsyncTaskComplete() + * regardless of what is passed in as the cob. + * + * Uses a per-server task queue for all calls. + */ +class TQueuingAsyncProcessor : public TAsyncProcessor { + public: + TQueuingAsyncProcessor( + boost::shared_ptr processor, + boost::shared_ptr threadManager, + int64_t taskExpireTime, + TEventConnection* connection) + : processor_(processor) + , threadManager_(threadManager) + , taskExpireTime_(taskExpireTime) + , connection_(connection) + {} + + virtual void process( + std::tr1::function cob, + boost::shared_ptr in, + boost::shared_ptr out, + TConnectionContext* context) { + + boost::shared_ptr task = + boost::shared_ptr( + new TEventTask(connection_)); + + try { + threadManager_->add(task, 0LL, taskExpireTime_); + } catch (apache::thrift::concurrency::IllegalStateException & ise) { + T_ERROR("IllegalStateException: TQueuingAsyncProcessor::process() %s", + ise.what()); + // no task will be making a callback + return cob(false); + } + } + + private: + boost::shared_ptr processor_; + + /// For processing via thread pool + boost::shared_ptr threadManager_; + + /// Time in milliseconds before an unperformed task expires (0 == infinite). + int64_t taskExpireTime_; + + /// The worker that started us + TEventConnection* connection_; +}; + +}}} // apache::thrift::async + +#endif // #ifndef _THRIFT_TQUEUINGASYNCPROCESSOR_H_ diff --git a/thrift/lib/cpp/async/TStreamAsyncChannel.h b/thrift/lib/cpp/async/TStreamAsyncChannel.h new file mode 100644 index 00000000..3e9ec9f0 --- /dev/null +++ b/thrift/lib/cpp/async/TStreamAsyncChannel.h @@ -0,0 +1,456 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TSTREAMASYNCCHANNEL_H_ +#define THRIFT_ASYNC_TSTREAMASYNCCHANNEL_H_ 1 + +#include "thrift/lib/cpp/async/TAsyncEventChannel.h" +#include "thrift/lib/cpp/async/TAsyncTransport.h" +#include "thrift/lib/cpp/async/TAsyncTimeout.h" + +#include + +namespace apache { namespace thrift { namespace async { + +class TAsyncTransport; + +template +class TAsyncChannelWriteRequestBase { + public: + typedef std::tr1::function VoidCallback; + + TAsyncChannelWriteRequestBase(const VoidCallback& callback, + const VoidCallback& errorCallback, + transport::TMemoryBuffer* message) + : buffer_(message), + next_(NULL), + callback_(callback), + errorCallback_(errorCallback) { + + // The WriteRequest's buffer consumes all of the data in message, + // so we don't attempt to resend data; yet is also an observer + // which prevents consumed data from being overwritten while it's pending + // for the transport + uint32_t len = message->available_read(); + message->borrow(NULL, &len); + message->consume(len); + } + + virtual ~TAsyncChannelWriteRequestBase() { + } + + void setNext(Subclass_* next) { + assert(next_ == NULL); + next_ = next; + } + + Subclass_* getNext() const { + return next_; + } + + protected: + apache::thrift::transport::TMemoryBuffer buffer_; + + void invokeCallback() { + // unlink the buffer before invoking the callback, since we are + // now done with it. Not strictly required but faster. + buffer_.unlink(); + callback_(); + } + + void invokeErrorCallback() { + // unlink the buffer before invoking the callback, since we are + // now done with it. Not strictly required but faster. + buffer_.unlink(); + errorCallback_(); + } + + private: + TAsyncChannelWriteRequestBase(); + + Subclass_* next_; + + VoidCallback callback_; + VoidCallback errorCallback_; +}; + + +/** + * TStreamAsyncChannel is a helper class for channel implementations that use + * TAsyncTransport underneath. + * + * TStreamAsyncChannel provides the basic functionality for implementing a + * message-based asynchronous channel on top of a streaming TAsyncTransport. + * + * It requires two template arguments that control how the stream is broken up + * into messagess: + * + * WriteRequest_: + * + * This template parameter controls how messages are written to the + * underlying stream. It must implement the following methods: + * + * - WriteRequest_(const VoidCallback& callback, + * const VoidCallback& errorCallback, + * transport::TMemoryBuffer* message); + * + * The WriteRequest_ constructor accepts the success and error callbacks, + * and the TMemoryBuffer containing the data to send. The WriteRequest_ + * may consume data from the message, but does not own the TMemoryBuffer + * (i.e., it should not delete the TMemoryBuffer.) + * + * - void setNext(WriteRequest_* next); + * - WriteRequest_* getNext() const; + * + * These two methods support chaining together a list of WriteRequest_ + * objects. This is used when multiple write requests are pending on the + * channel. + * + * - void write(TAsyncTransport* transport, + * TAsyncTransport::WriteCallback* callback) THRIFT_NOEXCEPT; + * + * This method will be called to schedule the write. The WriteRequest_ + * should invoke the transport's write() or writev() method with the data + * to send, and set the specified callback as the transport callback. + * + * Note that this API requires the WriteRequest_ to write the entire + * message with a single write() or writev() call. This allows the code + * to let the TAsyncTransport perform the write queuing when multiple + * messages are pending. (If needed we could rewrite this API in the + * future to relax this restriction.) + * + * - void writeSuccess() THRIFT_NOEXCEPT; + * - void writeError(size_t bytesWritten, + * const TTransportException& ex) THRIFT_NOEXCEPT; + * + * Either writeSuccess() or writeError() will be invoked once the message + * write has completed. + * + * ReadState_: + * + * This template parameter controls how the incoming stream is broken up into + * individual messages. It must implement the following methods: + * + * - ReadState_(); + * + * The ReadState_ constructor takes no arguments. + * + * - void setCallbackBuffer(transport::TMemoryBuffer* buffer); + * + * When a new read is started, setCallbackBuffer() is called to set the + * buffer into which the message data should be placed. + * + * - void unsetCallbackBuffer(); + * + * unsetCallbackBuffer() is called to clear the callback buffer when after + * a full message has been read. + * + * - bool hasReadAheadData(); + * + * Some ReadState_ implementations may perform read-ahead, and read past + * the end of the message when reading from the underlying transport. + * hasReadAheadData() is called when a new read starts, to see if the + * ReadState_ has pending data for a new message that has already been read + * from the transport. + * + * If hasReadAheadData() returns true, readDataAvailable(0) will be called + * immediately, rather than waiting for new data from the transport. + * + * - bool hasPartialMessage(); + * + * When EOF is read from the underlying transport, hasPartialMessage() is + * called to see if the EOF should be treated as an error or a normal + * close. (It is an error if hasPartialMessage() returns true.) + * + * - void getReadBuffer(void** bufReturn, size_t* lenReturn); + * + * When data becomes available on the underlying transport, getReadBuffer() + * is called to get the buffer where the data should be placed. + * + * - bool readDataAvailable(size_t len); + * + * readDataAvailable() is called when new data has been read from the + * underlying transport. The data will have been placed in the buffer + * returned by the previous getReadBuffer() call. + */ +template +class TStreamAsyncChannel : public TAsyncEventChannel, + protected TAsyncTransport::ReadCallback, + protected TAsyncTransport::WriteCallback, + protected TAsyncTimeout { + public: + explicit TStreamAsyncChannel( + const boost::shared_ptr& transport); + + /** + * Helper function to create a shared_ptr. + * + * This passes in the correct destructor object, since TStreamAsyncChannel's + * destructor is protected and cannot be invoked directly. + */ + static boost::shared_ptr newChannel( + const boost::shared_ptr& transport) { + return boost::shared_ptr( + new TStreamAsyncChannel(transport), Destructor()); + } + + /** + * Destroy the channel. + * + * destroy() must be called to destroy the channel. The normal destructor + * is private, and should not be invoked directly. This prevents callers + * from deleting a TStreamAsyncChannel while it is invoking a callback. + */ + virtual void destroy(); + + // Methods inherited from TAsyncEventChannel + virtual bool readable() const; + virtual bool good() const; + virtual bool error() const; + virtual bool timedOut() const; + + /** + * Send a message to the channel; note that "errorCob" will be called + * after a partial write as well as other errors. We will call "errorCob" + * immediately (before return) if the channel is unusable for some reason, + * and "cob" immediately if we're able to perform the write without delay. + */ + virtual void sendMessage(const VoidCallback& cob, + const VoidCallback& errorCob, + apache::thrift::transport::TMemoryBuffer* message); + + /** + * Receive a message from the channel; note that "errorCob" will be called + * after a partial read as well as other errors. We will call "errorCob" + * immediately (before return) if the channel is unusable for some reason, + * and "cob" immediately if we're able to perform the read without delay. + * + * Note that an EOF is considered normal, so "cob" will be called although + * "good()" will be false. + */ + virtual void recvMessage(const VoidCallback& cob, + const VoidCallback& errorCob, + apache::thrift::transport::TMemoryBuffer* message); + + /** + * Send a message to the channel and receive the response; note that the + * "errorCob: will be called after a write error and no receive is attempted. + * Also, a partial write or read will result in errorCob being called. + * We call "errorCob" before return if the channel is unusable for some + * reason. It is conceivable that "cob" will be called before return if data + * is somehow available in the channel when a read is first attempted. + */ + virtual void sendAndRecvMessage( + const VoidCallback& cob, + const VoidCallback& errorCob, + transport::TMemoryBuffer* sendBuf, + transport::TMemoryBuffer* recvBuf); + + /** + * Close this channel. + * + * This gracefully closes the channel, waiting for all pending send + * requests to complete before actually closing the underlying transport. + * + * If a recvMessage() call is pending, it will be immediately failed. + */ + void close(); + + /** + * Close the channel immediately. + * + * This closes the channel immediately, dropping any outstanding messages + * waiting to be sent. + * + * If a recvMessage() call is pending, it will be immediately failed. + */ + void closeNow(); + + /** + * Attach the channel to a TEventBase. + * + * This may only be called if the channel is not currently attached to a + * TEventBase (by an earlier call to detachEventBase()). + * + * This method must be invoked in the TEventBase's thread. + */ + void attachEventBase(TEventBase* eventBase); + + /** + * Detach the channel from its TEventBase. + * + * This may only be called when the channel is idle and has no reads or + * writes pending. Once detached, the channel may not be used again until it + * is re-attached to a TEventBase by calling attachEventBase(). + * + * This method must be called from the current TEventBase's thread. + */ + void detachEventBase(); + + /** + * Get the TEventBase used by this channel. + */ + TEventBase* getEventBase() const; + + /** + * Set the timeout for receiving messages. + * + * When set to a non-zero value, the entire message must be received within + * the specified number of milliseconds, or the receive will fail and the + * channel will be closed. + * + * If setRecvTimeout() is invoked while a recvMessage() call is currently in + * progress, the timeout will be restarted using the new value. + */ + void setRecvTimeout(uint32_t milliseconds); + + /** + * Get the receive timeout. + * + * @return Returns the current receive timeout, in milliseconds. A return + * value of 0 indicates that no timeout is set. + */ + uint32_t getRecvTimeout() const { + return recvTimeout_; + } + + /** + * Cancel pending callbacks. Use this when the channel is closing because the + * server had been shut down. + */ + virtual void cancelCallbacks() { + readCallback_ = NULL; + readErrorCallback_ = NULL; + } + + /** + * Get the TAsyncTransport used by this channel. + */ + virtual boost::shared_ptr getTransport() { + return transport_; + } + + /** + * Determine if this channel is idle (i.e., has no outstanding reads or + * writes). + */ + bool isIdle() const { + return (writeReqHead_ == NULL) && (!readCallback_) && + !transport_->connecting(); + } + + protected: + struct ReadQueueEntry { + ReadQueueEntry(const VoidCallback& cob, + const VoidCallback& errorCob, + apache::thrift::transport::TMemoryBuffer* message) { + readCallback = cob; + readErrorCallback = errorCob; + readBuffer = message; + } + VoidCallback readCallback; + VoidCallback readErrorCallback; + transport::TMemoryBuffer *readBuffer; + int64_t startTime; + }; + + /** + * Protected destructor. + * + * Users of TStreamAsyncChannel must never delete it directly. Instead, + * invoke destroy(). + */ + virtual ~TStreamAsyncChannel() {} + + // callbacks from TAsyncTransport + void getReadBuffer(void** bufReturn, size_t* lenReturn); + void readDataAvailable(size_t len) THRIFT_NOEXCEPT; + void readEOF() THRIFT_NOEXCEPT; + void readError(const transport::TTransportException& ex) THRIFT_NOEXCEPT; + + void writeSuccess() THRIFT_NOEXCEPT; + void writeError(size_t bytesWritten, + const transport::TTransportException& ex) THRIFT_NOEXCEPT; + + // callback from TAsyncTimeout + void timeoutExpired() THRIFT_NOEXCEPT; + + bool invokeReadDataAvailable(size_t len) THRIFT_NOEXCEPT; + void processReadEOF() THRIFT_NOEXCEPT; + void invokeReadCallback(VoidCallback cb, + char const* callbackName) THRIFT_NOEXCEPT; + + void pushWriteRequest(WriteRequest_* req) { + if (writeReqTail_ == NULL) { + assert(writeReqHead_ == NULL); + writeReqHead_ = req; + } else { + writeReqTail_->setNext(req); + } + writeReqTail_ = req; + } + + WriteRequest_* popWriteRequest() { + assert(writeReqHead_ != NULL); + + WriteRequest_* req = writeReqHead_; + writeReqHead_ = req->getNext(); + if (writeReqHead_ == NULL) { + assert(writeReqTail_ == req); + writeReqTail_ = NULL; + } + return req; + } + + void clearCallbacks() { + readCallback_ = NULL; + readErrorCallback_ = NULL; + } + + void failAllReads(); + + boost::shared_ptr transport_; + WriteRequest_* writeReqHead_; + WriteRequest_* writeReqTail_; + + ReadState_ readState_; + VoidCallback readCallback_; + VoidCallback readErrorCallback_; + std::list readCallbackQ_; + + uint32_t recvTimeout_; + // true if a timeout has occurred + bool timedOut_; + + private: + // Forbidden copy constructor and assignment opererator + TStreamAsyncChannel(TStreamAsyncChannel const &); + TStreamAsyncChannel& operator=(TStreamAsyncChannel const &); +}; + +class TStreamAsyncChannelFactory { + public: + virtual ~TStreamAsyncChannelFactory() {} + + virtual boost::shared_ptr newChannel( + const boost::shared_ptr& transport) = 0; +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TSTREAMASYNCCHANNEL_H_ diff --git a/thrift/lib/cpp/async/TStreamAsyncChannel.tcc b/thrift/lib/cpp/async/TStreamAsyncChannel.tcc new file mode 100644 index 00000000..f149e0f2 --- /dev/null +++ b/thrift/lib/cpp/async/TStreamAsyncChannel.tcc @@ -0,0 +1,488 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TSTREAMASYNCCHANNEL_TCC_ +#define THRIFT_ASYNC_TSTREAMASYNCCHANNEL_TCC_ 1 + +#include "thrift/lib/cpp/async/TStreamAsyncChannel.h" +#include "thrift/lib/cpp/transport/TSocketAddress.h" + +namespace apache { namespace thrift { namespace async { + +template +TStreamAsyncChannel::TStreamAsyncChannel( + const boost::shared_ptr& transport) + : TAsyncTimeout(transport->getEventBase()) + , transport_(transport) + , writeReqHead_(NULL) + , writeReqTail_(NULL) + , readState_() + , readCallback_() + , readErrorCallback_() + , recvTimeout_(0) + , timedOut_(false) { +} + +template +void TStreamAsyncChannel::destroy() { + // When destroy is called, close the channel immediately + closeNow(); + + // Then call TDelayedDestruction::destroy() to take care of + // whether or not we need immediate or delayed destruction + TDelayedDestruction::destroy(); +} + +template +bool TStreamAsyncChannel::readable() const { + return transport_->readable(); +} + +template +bool TStreamAsyncChannel::good() const { + return transport_->good(); +} + +template +bool TStreamAsyncChannel::error() const { + return (timedOut_ || transport_->error()); +} + +template +bool TStreamAsyncChannel::timedOut() const { + return timedOut_; +} + +template +void TStreamAsyncChannel::sendMessage( + const VoidCallback& cob, + const VoidCallback& errorCob, + transport::TMemoryBuffer* message) { + assert(message); + DestructorGuard dg(this); + + if (!good()) { + T_DEBUG_T("sendMessage: transport went bad, bailing out."); + return errorCob(); + } + + if (message->available_read() == 0) { + T_ERROR("sendMessage: buffer is empty"); + return errorCob(); + } + + WriteRequest_* writeReq; + try { + writeReq = new WriteRequest_(cob, errorCob, message, this); + } catch (const std::exception& ex) { + T_ERROR("sendMessage: failed to allocate new write request object"); + errorCob(); + return; + } + + pushWriteRequest(writeReq); + writeReq->write(transport_.get(), this); +} + +template +void TStreamAsyncChannel::recvMessage( + const VoidCallback& cob, + const VoidCallback& errorCob, + transport::TMemoryBuffer* message) { + assert(message); + DestructorGuard dg(this); + + if (!good()) { + T_DEBUG_T("recvMessage: transport went bad, bailing out."); + return errorCob(); + } + + if (message->available_read() != 0) { + T_ERROR("recvMessage: buffer is not empty."); + return errorCob(); + } + + if (readCallbackQ_.empty() && readCallback_ == NULL) { + readState_.setCallbackBuffer(message); + readCallback_ = cob; + readErrorCallback_ = errorCob; + } else { + readCallbackQ_.push_back(ReadQueueEntry(cob, errorCob, message)); + return; + } + + // Some ReadState implementations perform read-ahead, + // and they may already have data waiting to be processed. + // If so, we need to invoke readDataAvailable() immediately, rather than + // waiting for new data from the transport. + if (readState_.hasReadAheadData()) { + if (invokeReadDataAvailable(0)) { + // We already invoked the callback + return; + } + } + + // start the read timeout + if (recvTimeout_ > 0) { + scheduleTimeout(recvTimeout_); + } + + // start reading from the transport + // Note that setReadCallback() may invoke our read callback methods + // immediately, so the read may complete before setReadCallback() returns. + transport_->setReadCallback(this); +} + +template +void TStreamAsyncChannel::sendAndRecvMessage( + const VoidCallback& cob, + const VoidCallback& errorCob, + transport::TMemoryBuffer* sendBuf, + transport::TMemoryBuffer* recvBuf) { + // TODO: it would be better to perform this bind once, rather than + // each time sendAndRecvMessage() is called. + const VoidCallback& send_done = + std::tr1::bind(&TStreamAsyncChannel::recvMessage, this, cob, errorCob, + recvBuf); + + return sendMessage(send_done, errorCob, sendBuf); +} + +template +void TStreamAsyncChannel::close() { + DestructorGuard dg(this); // transport::close can invoke callbacks + + transport_->setReadCallback(NULL); + transport_->close(); + + if (readCallback_) { + processReadEOF(); + } + + // no need to free the write-queue here. The underlying transport will + // drain the writes first +} + +template +void TStreamAsyncChannel::closeNow() { + DestructorGuard dg(this); // transport::closeNow can invoke callbacks + + transport_->setReadCallback(NULL); + transport_->closeNow(); + + if (readCallback_) { + processReadEOF(); + } + + // no need to free the write-queue here. The underlying transport will + // fail pending writes first +} + +template +void TStreamAsyncChannel::attachEventBase( + TEventBase* eventBase) { + TAsyncTimeout::attachEventBase(eventBase); + transport_->attachEventBase(eventBase); +} + +template +void TStreamAsyncChannel::detachEventBase() { + // detachEventBase() may not be called while in the middle of reading or + // writing a message. Make sure there are no read callbacks + assert(!readCallback_ && readCallbackQ_.empty()); + // Even though readCallback_ is unset, the read timeout might still be + // installed. This happens when detachEventBase() is invoked by the + // recvMessage() callback, because invokeReadDataAvailable() optimizes and + // leaves the timeout and transport read callback installed while invoking + // the recvMessage() callback. Make sure we cancel the read timeout before + // detaching from the event base. + if (transport_->getReadCallback() == this) { + cancelTimeout(); + transport_->setReadCallback(NULL); + } + + TAsyncTimeout::detachEventBase(); + transport_->detachEventBase(); +} + +template +TEventBase* +TStreamAsyncChannel::getEventBase() const { + return transport_->getEventBase(); +} + +template +void TStreamAsyncChannel::setRecvTimeout( + uint32_t milliseconds) { + recvTimeout_ = milliseconds; + // If we are currently reading, update the timeout + if (transport_->getReadCallback() == this) { + if (milliseconds > 0) { + scheduleTimeout(milliseconds); + } else { + cancelTimeout(); + } + } +} + +template +void TStreamAsyncChannel::getReadBuffer( + void** bufReturn, size_t* lenReturn) { + readState_.getReadBuffer(bufReturn, lenReturn); +} + +template +void TStreamAsyncChannel::readDataAvailable( + size_t len) THRIFT_NOEXCEPT { + invokeReadDataAvailable(len); +} + +template +void TStreamAsyncChannel::readEOF() THRIFT_NOEXCEPT { + // readCallback_ may be NULL if readEOF() is invoked while the read callback + // is already running inside invokeReadDataAvailable(), since + // invokeReadDataAvailable() leaves the transport read callback installed + // while calling the channel read callback. + if (readCallback_) { + processReadEOF(); + } +} + +template +void TStreamAsyncChannel::readError( + const transport::TTransportException& ex) THRIFT_NOEXCEPT { + // readCallback_ may be NULL if readEOF() is invoked while the read callback + // is already running inside invokeReadDataAvailable(), since + // invokeReadDataAvailable() leaves the transport read callback installed + // while calling the channel read callback. + if (!readCallback_) { + return; + } + + DestructorGuard dg(this); + + cancelTimeout(); + failAllReads(); +} + +template +void TStreamAsyncChannel::writeSuccess() + THRIFT_NOEXCEPT { + DestructorGuard dg(this); + + WriteRequest_* req = popWriteRequest(); + req->writeSuccess(); + delete req; +} + +template +void TStreamAsyncChannel::writeError( + size_t bytesWritten, + const transport::TTransportException& ex) THRIFT_NOEXCEPT { + DestructorGuard dg(this); + + if (ex.getType() == transport::TTransportException::TIMED_OUT) { + timedOut_ = true; + } + + WriteRequest_* req = popWriteRequest(); + req->writeError(bytesWritten, ex); + delete req; +} + +template +void TStreamAsyncChannel::timeoutExpired() + THRIFT_NOEXCEPT { + DestructorGuard dg(this); + + timedOut_ = true; + + // Close the transport. It isn't usable anymore, since we are leaving + // it in a state with a partial message outstanding. + transport_->setReadCallback(NULL); + transport_->close(); + + // TODO: It would be nice not to have to always log an error message here; + // ideally the callback should decide if this is worth logging or not. + // Unfortunately the TAsyncChannel API doesn't allow us to pass any error + // info back to the callback. + T_ERROR("TStreamAsyncChannel: read timeout"); + + failAllReads(); +} + +template +bool TStreamAsyncChannel::invokeReadDataAvailable( + size_t len) THRIFT_NOEXCEPT { + DestructorGuard dg(this); + assert(readCallback_); + + bool readDone; + try { + readDone = readState_.readDataAvailable(len); + } catch (const std::exception& ex) { + // The channel is in an unknown state after an error processing read data. + // Close the channel to ensure that callers cannot try to read from this + // channel again. + // + // Make sure we do this after clearing our callbacks, so that the + // channel won't call our readEOF() method. + cancelTimeout(); + transport_->setReadCallback(NULL); + + std::string addressStr; + try { + transport::TSocketAddress addr; + transport_->getPeerAddress(&addr); + addressStr = addr.describe(); + } catch (const std::exception& e) { + addressStr = "unknown"; + } + + T_ERROR("error reading message from %s: %s", addressStr.c_str(), ex.what()); + failAllReads(); + return true; + } + + if (!readDone) { + // We read some data, but didn't finish reading a full message. + if (recvTimeout_ > 0) { + // Reset the timeout whenever we receive any data. + // TODO: This matches the old TAsyncChannel behavior, but it seems like + // it would make more sense to have the timeout apply to the entire + // message as a whole. Eventually we should remove this code that resets + // the timeout. + scheduleTimeout(recvTimeout_); + } + return false; + } + + TEventBase* ourEventBase = transport_->getEventBase(); + + // We read a full message. Invoke the read callback. + invokeReadCallback(readCallback_, "read callback"); + + // Note that we cleared readCallback_ and readErrorCallback_ before invoking + // the callback, but left ourself installed as the TAsyncTransport read + // callback. + // + // This allows us to avoid changing the TAsyncTransport read callback if the + // channel read callback immediately called recvMessage() again. This is + // fairly common, and we avoid 2 unnecessary epoll_ctl() calls by not + // changing the transport read callback. This results in a noticeable + // performance improvement. + // + // If readCallback_ is set again after the callback returns, we're still + // reading. recvMessage() will have taken care of reseting the receive + // timeout, so we have nothing else to do. + // + // If readCallback_ is unset, recvMessage() wasn't called again and we need + // to stop reading. If our TEventBase has changed, detachEventBase() will + // have already stopped reading. (Note that if the TEventBase has changed, + // it's possible that readCallback_ has already been set again to start + // reading in the other thread.) + if (transport_->getEventBase() == ourEventBase && !readCallback_) { + if (readCallbackQ_.empty()) { + cancelTimeout(); + transport_->setReadCallback(NULL); + } else { + // There are queued readers, pop one. This block should have the same + // effect as if recvMessage were called + const ReadQueueEntry &qentry = readCallbackQ_.front(); + readCallback_ = qentry.readCallback; + readErrorCallback_ = qentry.readErrorCallback; + readState_.setCallbackBuffer(qentry.readBuffer); + readCallbackQ_.pop_front(); + + if (readState_.hasReadAheadData()) { + return invokeReadDataAvailable(0); + } else if (recvTimeout_ > 0) { + scheduleTimeout(recvTimeout_); + } + } + } + return true; +} + +template +void TStreamAsyncChannel::failAllReads() { + invokeReadCallback(readErrorCallback_, "read error callback"); + + while (!readCallbackQ_.empty()) { + const ReadQueueEntry &qentry = readCallbackQ_.front(); + invokeReadCallback(qentry.readErrorCallback, "read error callback"); + readCallbackQ_.pop_front(); + } +} + +template +void TStreamAsyncChannel::processReadEOF() + THRIFT_NOEXCEPT { + DestructorGuard dg(this); + assert(readCallback_); + + VoidCallback cb; + const char* cbName; + if (readState_.hasPartialMessage()) { + cb = readErrorCallback_; + cbName = "read error callback"; + } else { + // We call the normal (non-error) callback if no data has been received yet + // when EOF occurs. + // + // TODO: It would be nicer to have a mechanism to indicate to the caller + // that EOF was received, instead of treating this just like 0-sized + // message. + cb = readCallback_; + cbName = "read callback"; + } + + cancelTimeout(); + invokeReadCallback(cb, cbName); + + // Any queued reads should be notified like the else case above as only + // the first reader can have partial data. + while (!readCallbackQ_.empty()) { + const ReadQueueEntry &qentry = readCallbackQ_.front(); + invokeReadCallback(qentry.readCallback, cbName); + readCallbackQ_.pop_front(); + } +} + +template +void TStreamAsyncChannel::invokeReadCallback( + VoidCallback cb, char const* callbackName) THRIFT_NOEXCEPT { + readState_.unsetCallbackBuffer(); + readCallback_ = VoidCallback(); + readErrorCallback_ = VoidCallback(); + + try { + cb(); + } catch (const std::exception& ex) { + T_ERROR("TAsyncChannel: %s threw %s exception: %s", + callbackName, typeid(ex).name(), ex.what()); + abort(); + } catch (...) { + T_ERROR("TAsyncChannel: %s threw exception", callbackName); + abort(); + } +} + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TSTREAMASYNCCHANNEL_TCC_ diff --git a/thrift/lib/cpp/async/TSyncToAsyncProcessor.h b/thrift/lib/cpp/async/TSyncToAsyncProcessor.h new file mode 100644 index 00000000..4099a9c0 --- /dev/null +++ b/thrift/lib/cpp/async/TSyncToAsyncProcessor.h @@ -0,0 +1,42 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TSYNCTOASYNCPROCESSOR_H_ +#define _THRIFT_TSYNCTOASYNCPROCESSOR_H_ 1 + +#include +#include +#include "thrift/lib/cpp/TProcessor.h" +#include "thrift/lib/cpp/async/TAsyncProcessor.h" + +namespace apache { namespace thrift { namespace async { + +/** + * Adapter to allow a TProcessor to be used as a TAsyncProcessor. + * + * Note that this should only be used for handlers that return quickly without + * blocking, since async servers can be stalled by a single blocking operation. + */ +class TSyncToAsyncProcessor : public TAsyncProcessor { + public: + TSyncToAsyncProcessor(boost::shared_ptr processor) + : processor_(processor) + {} + + virtual void process(std::tr1::function _return, + boost::shared_ptr in, + boost::shared_ptr out, + TConnectionContext* context) { + return _return(processor_->process(in, out, context)); + } + + private: + boost::shared_ptr processor_; +}; + +}}} // apache::thrift::async + +#endif // #ifndef _THRIFT_TSYNCTOASYNCPROCESSOR_H_ diff --git a/thrift/lib/cpp/async/TUndelayedDestruction.h b/thrift/lib/cpp/async/TUndelayedDestruction.h new file mode 100644 index 00000000..fcc9a5cb --- /dev/null +++ b/thrift/lib/cpp/async/TUndelayedDestruction.h @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TUNDELAYEDDESTRUCTION_H_ +#define THRIFT_ASYNC_TUNDELAYEDDESTRUCTION_H_ 1 + +#include +#include +#include +#include + +namespace apache { namespace thrift { namespace async { + +/** + * A helper class to allow a TDelayedDestruction object to be instantiated on + * the stack. + * + * This class derives from an existing TDelayedDestruction type and makes the + * destructor public again. This allows objects of this type to be declared on + * the stack or directly inside another class. Normally TDelayedDestruction + * objects must be dynamically allocated on the heap. + * + * However, the trade-off is that you lose some of the protections provided by + * TDelayedDestruction::destroy(). TDelayedDestruction::destroy() will + * automatically delay destruction of the object until it is safe to do so. + * If you use TUndelayedDestruction, you become responsible for ensuring that + * you only destroy the object where it is safe to do so. Attempting to + * destroy a TUndelayedDestruction object while it has a non-zero destructor + * guard count will abort the program. + */ +template +class TUndelayedDestruction : public TDD { + public: + // We want to expose all constructors provided by the parent class. + // C++11 adds constructor inheritance to support this. Unfortunately gcc + // does not implement constructor inheritance yet, so we have to fake it with + // variadic templates. +#if THRIFT_HAVE_CONSTRUCTOR_INHERITANCE + using TDD::TDD; +#else + // We unfortunately can't simulate constructor inheritance as well as I'd + // like. + // + // Ideally we would use std::enable_if<> and std::is_constructible<> to + // provide only constructor methods that are valid for our parent class. + // Unfortunately std::is_constructible<> doesn't work for types that aren't + // destructible. In gcc-4.6 it results in a compiler error. In the latest + // gcc code it looks like it has been fixed to return false. (The language + // in the standard seems to indicate that returning false is the correct + // behavior for non-destructible types, which is unfortunate.) + template + explicit TUndelayedDestruction(Args&& ...args) + : TDD(std::forward(args)...) {} +#endif + + /** + * Public destructor. + * + * The caller is responsible for ensuring that the object is only destroyed + * where it is safe to do so. (i.e., when the destructor guard count is 0). + * + * The exact conditions for meeting this may be dependant upon your class + * semantics. Typically you are only guaranteed that it is safe to destroy + * the object directly from the event loop (e.g., directly from a + * TEventBase::LoopCallback), or when the event loop is stopped. + */ + virtual ~TUndelayedDestruction() { + // Crash if the caller is destroying us with outstanding destructor guards. + if (this->getDestructorGuardCount() != 0) { + abort(); + } + // Invoke destroy. This is necessary since our base class may have + // implemented custom behavior in destroy(). + this->destroy(); + } + + protected: + /** + * Override our parent's destroy() method to make it protected. + * Callers should use the normal destructor instead of destroy + */ + virtual void destroy() { + this->TDD::destroy(); + } + + virtual void destroyNow(bool delayed) { + // Do nothing. This will always be invoked from the call to destroy inside + // our destructor. + assert(!delayed); + // prevent unused variable warnings when asserts are compiled out. + (void)delayed; + } + + private: + // Forbidden copy constructor and assignment operator + TUndelayedDestruction(TUndelayedDestruction const &) = delete; + TUndelayedDestruction& operator=(TUndelayedDestruction const &) = delete; +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TUNDELAYEDDESTRUCTION_H_ diff --git a/thrift/lib/cpp/async/TUnframedAsyncChannel.h b/thrift/lib/cpp/async/TUnframedAsyncChannel.h new file mode 100644 index 00000000..9dbffde3 --- /dev/null +++ b/thrift/lib/cpp/async/TUnframedAsyncChannel.h @@ -0,0 +1,168 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TUNFRAMEDASYNCCHANNEL_H_ +#define THRIFT_ASYNC_TUNFRAMEDASYNCCHANNEL_H_ 1 + +#include "thrift/lib/cpp/async/TStreamAsyncChannel.h" + +namespace apache { namespace thrift { namespace async { + +namespace detail { + +/** + * Encapsulation of one outstanding write request on a TUnframedAsyncChannel. + */ +class TUnframedACWriteRequest : + public TAsyncChannelWriteRequestBase { + public: + typedef std::tr1::function VoidCallback; + + TUnframedACWriteRequest(const VoidCallback& callback, + const VoidCallback& errorCallback, + transport::TMemoryBuffer* message, + TAsyncEventChannel* channel); + + void write(TAsyncTransport* transport, + TAsyncTransport::WriteCallback* callback) THRIFT_NOEXCEPT; + + void writeSuccess() THRIFT_NOEXCEPT; + void writeError(size_t bytesWritten, + const transport::TTransportException& ex) THRIFT_NOEXCEPT; +}; + +/** + * Read state for TUnframedAsyncChannel + */ +template +class TUnframedACReadState { + public: + typedef std::tr1::function VoidCallback; + typedef ProtocolTraits_ ProtocolTraits; + + TUnframedACReadState(); + ~TUnframedACReadState(); + + // Methods required by TStreamAsyncChannel + + void setCallbackBuffer(transport::TMemoryBuffer* buffer) { + callbackBuffer_ = buffer; + } + void unsetCallbackBuffer() { + callbackBuffer_ = NULL; + } + + bool hasReadAheadData() { + return (memBuffer_.available_read() > 0); + } + bool hasPartialMessage() { + return (memBuffer_.available_read() > 0); + } + + void getReadBuffer(void** bufReturn, size_t* lenReturn); + bool readDataAvailable(size_t len); + + // Methods specific to TUnframedACReadState + + void setMaxMessageSize(uint32_t size) { + maxMessageSize_ = size; + } + + uint32_t getMaxMessageSize() const { + return maxMessageSize_; + } + + ProtocolTraits_* getProtocolTraits() { + return &protocolTraits_; + } + const ProtocolTraits_* getProtocolTraits() const { + return &protocolTraits_; + } + + private: + bool getMessageLength(uint8_t* buffer, + uint32_t bufferLength, + uint32_t* messageLength); + + /// maximum frame size accepted + uint32_t maxMessageSize_; + + apache::thrift::transport::TMemoryBuffer memBuffer_; + apache::thrift::transport::TMemoryBuffer* callbackBuffer_; + ProtocolTraits_ protocolTraits_; +}; + +} // namespace detail + +/** + * TUnframedAsyncChannel + * + * This is a TAsyncChannel implementation that reads and writes raw (unframed) + * messages. When reading messages, ProtocolTraits_ is used to determine the + * end of a message. + */ +template +class TUnframedAsyncChannel : + public TStreamAsyncChannel > { + private: + typedef TStreamAsyncChannel > + Parent; + typedef TUnframedAsyncChannel Self; + + public: + explicit TUnframedAsyncChannel( + const boost::shared_ptr& transport + ) + : Parent(transport) {} + + /** + * Helper function to create a shared_ptr. + * + * This passes in the correct destructor object, since TUnframedAsyncChannel's + * destructor is protected and cannot be invoked directly. + */ + static boost::shared_ptr newChannel( + const boost::shared_ptr& transport) { + return boost::shared_ptr(new Self(transport), + typename Self::Destructor()); + } + + /// size in bytes beyond which we'll reject a given message. + void setMaxMessageSize(uint32_t size) { + this->readState_.setMaxMessageSize(size); + } + + uint32_t getMaxMessageSize() const { + return this->readState_.getMaxMessageSize(); + } + + protected: + /** + * Protected destructor. + * + * Users of TUnframedAsyncChannel must never delete it directly. Instead, + * invoke destroy(). + */ + virtual ~TUnframedAsyncChannel() { } +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TUNFRAMEDASYNCCHANNEL_H_ diff --git a/thrift/lib/cpp/async/TUnframedAsyncChannel.tcc b/thrift/lib/cpp/async/TUnframedAsyncChannel.tcc new file mode 100644 index 00000000..b23d2461 --- /dev/null +++ b/thrift/lib/cpp/async/TUnframedAsyncChannel.tcc @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TUNFRAMEDASYNCCHANNEL_TCC_ +#define THRIFT_ASYNC_TUNFRAMEDASYNCCHANNEL_TCC_ 1 + +#include "thrift/lib/cpp/async/TUnframedAsyncChannel.h" + +#include "thrift/lib/cpp/transport/TBufferTransports.h" + +namespace { +const uint32_t kInitialBufferSize = 4096; +} + +namespace apache { namespace thrift { namespace async { namespace detail { + +template +TUnframedACReadState::TUnframedACReadState() + : maxMessageSize_(0x7fffffff) + , memBuffer_(kInitialBufferSize) + , callbackBuffer_(NULL) + , protocolTraits_() { +} + +template +TUnframedACReadState::~TUnframedACReadState() { +} + +template +void TUnframedACReadState::getReadBuffer(void** bufReturn, + size_t* lenReturn) { + uint32_t bytesAvailable = memBuffer_.available_write(); + if (bytesAvailable > 0) { + // If there is room available in the buffer, just return it. + *lenReturn = bytesAvailable; + *bufReturn = memBuffer_.getWritePtr(bytesAvailable); + return; + } + + uint32_t bufferSize = memBuffer_.getBufferSize(); + uint32_t available_read = memBuffer_.available_read(); + // we get this much without growing the buffer capacity + uint32_t additionalSpace = bufferSize - available_read; + if (additionalSpace == 0) { + // We need more room. memBuffer_ will at least double it's capacity when + // asked for even a single byte. + additionalSpace = kInitialBufferSize; + } + + // Don't allow more than maxMessageSize_. + // Be careful not to over- or underflow uint32_t when checking. + // + // readDataAvailable() fails the read when we've already read maxMessageSize_ + // bytes, so available_read should always be less than maxMessageSize_ here. + // (Unless maxMessageSize_ is 0, but that's a programmer bug.) + assert(available_read < maxMessageSize_); + if (available_read > maxMessageSize_ - additionalSpace) { + // Don't ask for more than maxMessageSize_ total (but we might get more) + additionalSpace = maxMessageSize_ - available_read; + } + + try { + uint8_t* newBuffer = memBuffer_.getWritePtr(additionalSpace); + *lenReturn = memBuffer_.available_write(); + *bufReturn = newBuffer; + } catch (std::exception &ex) { + T_ERROR("TUnframedAsyncChannel: failed to allocate larger read buffer: %s", + ex.what()); + *lenReturn = 0; + *bufReturn = NULL; + } +} + +template +bool TUnframedACReadState::readDataAvailable(size_t len) { + assert(memBuffer_.available_read() + len <= memBuffer_.getBufferSize()); + memBuffer_.wroteBytes(len); + + uint32_t messageLength = 0; + uint32_t bytesRead = memBuffer_.available_read(); + uint8_t *buffer = (uint8_t *)memBuffer_.borrow(NULL, &bytesRead); + if (!protocolTraits_.getMessageLength(buffer, bytesRead, &messageLength)) { + // We're not at the end of the message yet. + // + // If we've hit maxMessageSize_ already, fail now instead of waiting until + // getReadBuffer() is called again. + if (bytesRead >= maxMessageSize_) { + throw transport::TTransportException( + transport::TTransportException::CORRUPTED_DATA, + "TUnframedAsyncChannel: max message size exceeded"); + } + return false; + } + + // We've read a full message. + // Swap the data into the callback's buffer. + // Note that we may have actually read more than one message, + // so we have to make sure to save any remaining data after the end of the + // message. + assert(messageLength <= bytesRead); + + callbackBuffer_->link(&memBuffer_, messageLength); + memBuffer_.consume(messageLength); + + // We've put a new message in callbackBuffer_ + return true; +} + +}}}} // apache::thrift::async::detail + +#endif // THRIFT_ASYNC_TUNFRAMEDASYNCCHANNEL_TCC_ diff --git a/thrift/lib/cpp/async/TZlibAsyncChannel.h b/thrift/lib/cpp/async/TZlibAsyncChannel.h new file mode 100644 index 00000000..bf32bc80 --- /dev/null +++ b/thrift/lib/cpp/async/TZlibAsyncChannel.h @@ -0,0 +1,180 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_ASYNC_TZLIBASYNCCHANNEL_H_ +#define THRIFT_ASYNC_TZLIBASYNCCHANNEL_H_ 1 + +#include "thrift/lib/cpp/async/TAsyncEventChannel.h" +#include "thrift/lib/cpp/transport/TZlibTransport.h" + +namespace apache { namespace thrift { namespace async { + +class TZlibAsyncChannel : public TAsyncEventChannel { + public: + explicit TZlibAsyncChannel( + const boost::shared_ptr& channel); + + /** + * Helper function to create a shared_ptr. + * + * This passes in the correct destructor object, since TZlibAsyncChannel's + * destructor is protected and cannot be invoked directly. + */ + static boost::shared_ptr newChannel( + const boost::shared_ptr& channel) { + return boost::shared_ptr( + new TZlibAsyncChannel(channel), Destructor()); + } + virtual bool readable() const { + return channel_->readable(); + } + virtual bool good() const { + return channel_->good(); + } + virtual bool error() const { + return channel_->error(); + } + virtual bool timedOut() const { + return channel_->timedOut(); + } + virtual bool isIdle() const { + return channel_->isIdle(); + } + + virtual void sendMessage(const VoidCallback& cob, + const VoidCallback& errorCob, + transport::TMemoryBuffer* message); + virtual void recvMessage(const VoidCallback& cob, + const VoidCallback& errorCob, + transport::TMemoryBuffer* message); + virtual void sendAndRecvMessage(const VoidCallback& cob, + const VoidCallback& errorCob, + transport::TMemoryBuffer* sendBuf, + transport::TMemoryBuffer* recvBuf); + + virtual boost::shared_ptr getTransport() { + return channel_->getTransport(); + } + + virtual void attachEventBase(TEventBase* eventBase) { + channel_->attachEventBase(eventBase); + } + virtual void detachEventBase() { + channel_->detachEventBase(); + } + + virtual uint32_t getRecvTimeout() const { + return channel_->getRecvTimeout(); + } + + virtual void setRecvTimeout(uint32_t milliseconds) { + channel_->setRecvTimeout(milliseconds); + } + + virtual void cancelCallbacks() { + sendRequest_.cancelCallbacks(); + recvRequest_.cancelCallbacks(); + } + + protected: + /** + * Protected destructor. + * + * Users of TZlibAsyncChannel must never delete it directly. Instead, + * invoke destroy(). + */ + virtual ~TZlibAsyncChannel() { } + + private: + class SendRequest { + public: + SendRequest(); + + bool isSet() const { + return static_cast(callback_); + } + + void set(const VoidCallback& callback, + const VoidCallback& errorCallback, + transport::TMemoryBuffer* message); + + void send(TAsyncEventChannel* channel); + + void cancelCallbacks() { + callback_ = NULL; + errorCallback_ = NULL; + } + + private: + void invokeCallback(VoidCallback callback); + void sendSuccess(); + void sendError(); + + boost::shared_ptr compressedBuffer_; + transport::TZlibTransport zlibTransport_; + VoidCallback sendSuccess_; + VoidCallback sendError_; + + VoidCallback callback_; + VoidCallback errorCallback_; + }; + + class RecvRequest { + public: + RecvRequest(); + + bool isSet() const { + return static_cast(callback_); + } + + void set(const VoidCallback& callback, + const VoidCallback& errorCallback, + transport::TMemoryBuffer* message); + + void recv(TAsyncEventChannel* channel); + + void cancelCallbacks() { + callback_ = NULL; + errorCallback_ = NULL; + } + + private: + void invokeCallback(VoidCallback callback); + void recvSuccess(); + void recvError(); + + boost::shared_ptr compressedBuffer_; + transport::TZlibTransport zlibTransport_; + VoidCallback recvSuccess_; + VoidCallback recvError_; + + VoidCallback callback_; + VoidCallback errorCallback_; + transport::TMemoryBuffer *callbackBuffer_; + }; + + boost::shared_ptr channel_; + + // TODO: support multiple pending send requests + SendRequest sendRequest_; + RecvRequest recvRequest_; +}; + +}}} // apache::thrift::async + +#endif // THRIFT_ASYNC_TZLIBASYNCCHANNEL_H_ diff --git a/thrift/lib/cpp/concurrency/Exception.h b/thrift/lib/cpp/concurrency/Exception.h new file mode 100644 index 00000000..bef1eb2f --- /dev/null +++ b/thrift/lib/cpp/concurrency/Exception.h @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_CONCURRENCY_EXCEPTION_H_ +#define _THRIFT_CONCURRENCY_EXCEPTION_H_ 1 + +#include +#include "thrift/lib/cpp/Thrift.h" + +namespace apache { namespace thrift { namespace concurrency { + +class NoSuchTaskException : public apache::thrift::TLibraryException {}; + +class UncancellableTaskException : public apache::thrift::TLibraryException {}; + +class InvalidArgumentException : public apache::thrift::TLibraryException {}; + +class IllegalStateException : public apache::thrift::TLibraryException { +public: + IllegalStateException() {} + IllegalStateException(const std::string& message) : TLibraryException(message) {} +}; + +class TimedOutException : public apache::thrift::TLibraryException { +public: + TimedOutException():TLibraryException("TimedOutException"){}; + TimedOutException(const std::string& message ) : + TLibraryException(message) {} +}; + +class TooManyPendingTasksException : public apache::thrift::TLibraryException { +public: + TooManyPendingTasksException():TLibraryException("TooManyPendingTasksException"){}; + TooManyPendingTasksException(const std::string& message ) : + TLibraryException(message) {} +}; + +class SystemResourceException : public apache::thrift::TLibraryException { +public: + SystemResourceException() {} + + SystemResourceException(const std::string& message) : + TLibraryException(message) {} +}; + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_EXCEPTION_H_ diff --git a/thrift/lib/cpp/concurrency/FunctionRunner.h b/thrift/lib/cpp/concurrency/FunctionRunner.h new file mode 100644 index 00000000..322d0c31 --- /dev/null +++ b/thrift/lib/cpp/concurrency/FunctionRunner.h @@ -0,0 +1,131 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H +#define _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H 1 + +#include +#include "thrift/lib/cpp/concurrency/Thread.h" + +namespace apache { namespace thrift { namespace concurrency { + +/** + * Convenient implementation of Runnable that will execute arbitrary callbacks. + * Interfaces are provided to accept both a generic 'void(void)' callback, and + * a 'void* (void*)' pthread_create-style callback. + * + * Example use: + * void* my_thread_main(void* arg); + * shared_ptr factory = ...; + * // To create a thread that executes my_thread_main once: + * shared_ptr thread = factory->newThread( + * FunctionRunner::create(my_thread_main, some_argument)); + * thread->start(); + * + * bool A::foo(); + * A* a = new A(); + * // To create a thread that executes a.foo() every 100 milliseconds: + * factory->newThread(FunctionRunner::create( + * std::tr1::bind(&A::foo, a), 100))->start(); + * + */ + +class FunctionRunner : public Runnable { + public: + // This is the type of callback 'pthread_create()' expects. + typedef void* (*PthreadFuncPtr)(void *arg); + // This a fully-generic void(void) callback for custom bindings. + typedef std::tr1::function VoidFunc; + + typedef std::tr1::function BoolFunc; + + /** + * Syntactic sugar to make it easier to create new FunctionRunner + * objects wrapped in shared_ptr. + */ + static boost::shared_ptr create(const VoidFunc& cob) { + return boost::shared_ptr(new FunctionRunner(cob)); + } + + static boost::shared_ptr create(PthreadFuncPtr func, + void* arg) { + return boost::shared_ptr(new FunctionRunner(func, arg)); + } + + static boost::shared_ptr create(const BoolFunc& cob, + int intervalMs) { + return boost::shared_ptr(new FunctionRunner(cob, + intervalMs)); + } + + /** + * Given a 'pthread_create' style callback, this FunctionRunner will + * execute the given callback. Note that the 'void*' return value is ignored. + */ + FunctionRunner(PthreadFuncPtr func, void* arg) + : func_(std::tr1::bind(func, arg)), repFunc_(0), initFunc_(0) + { } + + /** + * Given a generic callback, this FunctionRunner will execute it. + */ + FunctionRunner(const VoidFunc& cob) + : func_(cob), repFunc_(0), initFunc_(0) + { } + + /** + * Given a bool foo(...) type callback, FunctionRunner will execute + * the callback repeatedly with 'intervalMs' milliseconds between the calls, + * until it returns false. Note that the actual interval between calls will + * be intervalMs plus execution time of the callback. + */ + FunctionRunner(const BoolFunc& cob, int intervalMs) + : func_(0), repFunc_(cob), intervalMs_(intervalMs), initFunc_(0) + { } + + /** + * Set a callback to be called when the thread is started. + */ + void setInitFunc(const VoidFunc& initFunc) { + initFunc_ = initFunc; + } + + void run() { + if (initFunc_) { + initFunc_(); + } + if (repFunc_) { + while(repFunc_()) { + usleep(intervalMs_*1000); + } + } else { + func_(); + } + } + + private: + VoidFunc func_; + BoolFunc repFunc_; + int intervalMs_; + VoidFunc initFunc_; +}; + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H diff --git a/thrift/lib/cpp/concurrency/Monitor.h b/thrift/lib/cpp/concurrency/Monitor.h new file mode 100644 index 00000000..c5164ff9 --- /dev/null +++ b/thrift/lib/cpp/concurrency/Monitor.h @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_CONCURRENCY_MONITOR_H_ +#define _THRIFT_CONCURRENCY_MONITOR_H_ 1 + +#include "thrift/lib/cpp/concurrency/Exception.h" +#include "thrift/lib/cpp/concurrency/Mutex.h" + +#include + + +namespace apache { namespace thrift { namespace concurrency { + +/** + * A monitor is a combination mutex and condition-event. Waiting and + * notifying condition events requires that the caller own the mutex. Mutex + * lock and unlock operations can be performed independently of condition + * events. This is more or less analogous to java.lang.Object multi-thread + * operations. + * + * Note the Monitor can create a new, internal mutex; alternatively, a + * separate Mutex can be passed in and the Monitor will re-use it without + * taking ownership. It's the user's responsibility to make sure that the + * Mutex is not deallocated before the Monitor. + * + * Note that all methods are const. Monitors implement logical constness, not + * bit constness. This allows const methods to call monitor methods without + * needing to cast away constness or change to non-const signatures. + * + * @version $Id:$ + */ +class Monitor : boost::noncopyable { + public: + /** Creates a new mutex, and takes ownership of it. */ + Monitor(); + + /** Uses the provided mutex without taking ownership. */ + explicit Monitor(Mutex* mutex); + + /** Uses the mutex inside the provided Monitor without taking ownership. */ + explicit Monitor(Monitor* monitor); + + /** Deallocates the mutex only if we own it. */ + virtual ~Monitor(); + + Mutex& mutex() const; + + virtual void lock() const; + + virtual void unlock() const; + + /** + * Waits a maximum of the specified timeout in milliseconds for the condition + * to occur, or waits forever if timeout_ms == 0. + * + * Returns 0 if condition occurs, ETIMEDOUT on timeout, or an error code. + */ + int waitForTimeRelative(int64_t timeout_ms) const; + + /** + * Waits until the absolute time specified using struct timespec. + * Returns 0 if condition occurs, ETIMEDOUT on timeout, or an error code. + */ + int waitForTime(const timespec* abstime) const; + + /** + * Waits forever until the condition occurs. + * Returns 0 if condition occurs, or an error code otherwise. + */ + int waitForever() const; + + /** + * Exception-throwing version of waitForTimeRelative(), called simply + * wait(int64) for historical reasons. Timeout is in milliseconds. + * + * If the condition occurs, this function returns cleanly; on timeout or + * error an exception is thrown. + */ + void wait(int64_t timeout_ms = 0LL) const; + + + /** Wakes up one thread waiting on this monitor. */ + virtual void notify() const; + + /** Wakes up all waiting threads on this monitor. */ + virtual void notifyAll() const; + + private: + + class Impl; + + Impl* impl_; +}; + +class Synchronized { + public: + Synchronized(const Monitor* monitor) : g(monitor->mutex()) { } + Synchronized(const Monitor& monitor) : g(monitor.mutex()) { } + + private: + Guard g; +}; + + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_MONITOR_H_ diff --git a/thrift/lib/cpp/concurrency/Mutex.h b/thrift/lib/cpp/concurrency/Mutex.h new file mode 100644 index 00000000..a0e5ca56 --- /dev/null +++ b/thrift/lib/cpp/concurrency/Mutex.h @@ -0,0 +1,276 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_CONCURRENCY_MUTEX_H_ +#define THRIFT_CONCURRENCY_MUTEX_H_ 1 + +#include +#include + +namespace apache { namespace thrift { namespace concurrency { + +#ifndef THRIFT_NO_CONTENTION_PROFILING + +/** + * Determines if the Thrift Mutex and ReadWriteMutex classes will attempt to + * profile their blocking acquire methods. If this value is set to non-zero, + * Thrift will attempt to invoke the callback once every profilingSampleRate + * times. However, as the sampling is not synchronized the rate is not + * guaranteed, and could be subject to big bursts and swings. Please ensure + * your sampling callback is as performant as your application requires. + * + * The callback will get called with the wait time taken to lock the mutex in + * usec and a (void*) that uniquely identifies the Mutex (or ReadWriteMutex) + * being locked. + * + * The enableMutexProfiling() function is unsynchronized; calling this function + * while profiling is already enabled may result in race conditions. On + * architectures where a pointer assignment is atomic, this is safe but there + * is no guarantee threads will agree on a single callback within any + * particular time period. + */ +typedef void (*MutexWaitCallback)(const void* id, int64_t waitTimeMicros); +void enableMutexProfiling(int32_t profilingSampleRate, + MutexWaitCallback callback); + +#endif + +/** + * A simple mutex class + * + * @version $Id:$ + */ +class Mutex { + public: + typedef void (*Initializer)(void*); + + // Specifying the type of the mutex with one of the static Initializer + // methods defined in this class. + explicit Mutex(Initializer init = DEFAULT_INITIALIZER); + + // Specifying the type of the mutex with an integer. The value has + // to be supported by the underlying implementation, currently + // pthread_mutex. So the possible values are PTHREAD_MUTEX_NORMAL, + // PTHREAD_MUTEX_ERRORCHECK, PTHREAD_MUTEX_RECURSIVE and + // PTHREAD_MUTEX_DEFAULT. + explicit Mutex(int type); + + virtual ~Mutex() {} + virtual void lock() const; + virtual bool trylock() const; + virtual bool timedlock(int64_t milliseconds) const; + virtual void unlock() const; + + /** + * Determine if the mutex is locked. + * + * This is intended to be used primarily as a debugging aid, and is not + * guaranteed to be a fast operation. For example, a common use case is to + * assert(mutex.isLocked()) in functions that may only be called with a + * particular mutex already locked. + * + * TODO: This method currently always returns false for recursive mutexes. + * Avoid calling this method on recursive mutexes. + */ + virtual bool isLocked() const; + + void* getUnderlyingImpl() const; + + static void DEFAULT_INITIALIZER(void*); + static void ADAPTIVE_INITIALIZER(void*); + static void RECURSIVE_INITIALIZER(void*); + + private: + + class impl; + boost::shared_ptr impl_; +}; + +class ReadWriteMutex { +public: + ReadWriteMutex(); + virtual ~ReadWriteMutex() {} + + // these get the lock and block until it is done successfully + virtual void acquireRead() const; + virtual void acquireWrite() const; + + // these get the lock and block until it is done successfully + // or run out of time + virtual bool timedRead(int64_t milliseconds) const; + virtual bool timedWrite(int64_t milliseconds) const; + + // these attempt to get the lock, returning false immediately if they fail + virtual bool attemptRead() const; + virtual bool attemptWrite() const; + + // this releases both read and write locks + virtual void release() const; + +private: + + class impl; + boost::shared_ptr impl_; +}; + +/** + * A ReadWriteMutex that guarantees writers will not be starved by readers: + * When a writer attempts to acquire the mutex, all new readers will be + * blocked from acquiring the mutex until the writer has acquired and + * released it. In some operating systems, this may already be guaranteed + * by a regular ReadWriteMutex. + */ +class NoStarveReadWriteMutex : public ReadWriteMutex { +public: + NoStarveReadWriteMutex(); + + virtual void acquireRead() const; + virtual void acquireWrite() const; + + // these get the lock and block until it is done successfully + // or run out of time + virtual bool timedRead(int64_t milliseconds) const; + virtual bool timedWrite(int64_t milliseconds) const; + +private: + Mutex mutex_; + mutable volatile bool writerWaiting_; +}; + +class Guard : boost::noncopyable { + public: + explicit Guard(const Mutex& value, int64_t timeout = 0) : mutex_(&value) { + if (timeout == 0) { + value.lock(); + } else if (timeout < 0) { + if (!value.trylock()) { + mutex_ = NULL; + } + } else { + if (!value.timedlock(timeout)) { + mutex_ = NULL; + } + } + } + ~Guard() { + if (mutex_) { + mutex_->unlock(); + } + } + + /* + * This is really operator bool. However, implementing it to return + * bool is actually harmful. See + * www.artima.com/cppsource/safebool.html for the details; in brief, + * converting to bool allows a lot of nonsensical operations in + * addition to simple testing. To avoid that, we return a pointer to + * member which can only be used for testing. + */ + typedef const Mutex*const Guard::*const pBoolMember; + inline operator pBoolMember() const { + return mutex_ != NULL ? &Guard::mutex_ : NULL; + } + + private: + const Mutex* mutex_; +}; + +// Can be used as second argument to RWGuard to make code more readable +// as to whether we're doing acquireRead() or acquireWrite(). +enum RWGuardType { + RW_READ = 0, + RW_WRITE = 1, +}; + + +class RWGuard : boost::noncopyable { + public: + explicit RWGuard(const ReadWriteMutex& value, bool write = false, + int64_t timeout=0) + : rw_mutex_(value), locked_(true) { + if (write) { + if (timeout) { + locked_ = rw_mutex_.timedWrite(timeout); + } else { + rw_mutex_.acquireWrite(); + } + } else { + if (timeout) { + locked_ = rw_mutex_.timedRead(timeout); + } else { + rw_mutex_.acquireRead(); + } + } + } + + RWGuard(const ReadWriteMutex& value, RWGuardType type, int64_t timeout = 0) + : rw_mutex_(value), locked_(true) { + if (type == RW_WRITE) { + if (timeout) { + locked_ = rw_mutex_.timedWrite(timeout); + } else { + rw_mutex_.acquireWrite(); + } + } else { + if (timeout) { + locked_ = rw_mutex_.timedRead(timeout); + } else { + rw_mutex_.acquireRead(); + } + } + } + ~RWGuard() { + if (locked_) { + rw_mutex_.release(); + } + } + + typedef const bool RWGuard::*const pBoolMember; + operator pBoolMember() const { + return locked_ ? &RWGuard::locked_ : NULL; + } + + bool operator!() const { + return !locked_; + } + + bool release() { + if (!locked_) return false; + rw_mutex_.release(); + locked_ = false; + return true; + } + + private: + const ReadWriteMutex& rw_mutex_; + mutable bool locked_; +}; + + +// A little hack to prevent someone from trying to do "Guard(m);" +// Such a use is invalid because the temporary Guard object is +// destroyed at the end of the line, releasing the lock. +// Sorry for polluting the global namespace, but I think it's worth it. +#define Guard(m) incorrect_use_of_Guard(m) +#define RWGuard(m) incorrect_use_of_RWGuard(m) + + +}}} // apache::thrift::concurrency + +#endif // #ifndef THRIFT_CONCURRENCY_MUTEX_H_ diff --git a/thrift/lib/cpp/concurrency/PosixThreadFactory.h b/thrift/lib/cpp/concurrency/PosixThreadFactory.h new file mode 100644 index 00000000..7d7de185 --- /dev/null +++ b/thrift/lib/cpp/concurrency/PosixThreadFactory.h @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + + */ +#ifndef THRIFT_CONCURRENCY_POSIXTHREADFACTORY_H_ +#define THRIFT_CONCURRENCY_POSIXTHREADFACTORY_H_ 1 + +#include + +#include "thrift/lib/cpp/concurrency/Thread.h" + +#include + +namespace apache { namespace thrift { namespace concurrency { + +void getLiveThreadIds(std::set* tids); + +/** + * A thread factory to create posix threads + * + * @version $Id:$ + */ +class PosixThreadFactory : public ThreadFactory { + + public: + + /** + * POSIX Thread scheduler policies + */ + enum POLICY { + OTHER, + FIFO, + ROUND_ROBIN + }; + + /** + * POSIX Thread scheduler relative priorities, + * + * Absolute priority is determined by scheduler policy and OS. This + * enumeration specifies relative priorities such that one can specify a + * priority within a giving scheduler policy without knowing the absolute + * value of the priority. + */ + enum PRIORITY { + LOWEST = 0, + LOWER = 1, + LOW = 2, + NORMAL = 3, + HIGH = 4, + HIGHER = 5, + HIGHEST = 6, + INCREMENT = 7, + DECREMENT = 8 + }; + + static const POLICY kDefaultPolicy = ROUND_ROBIN; + static const PRIORITY kDefaultPriority = NORMAL; + static const int kDefaultStackSizeMB = 1; + + /** + * Posix thread (pthread) factory. All threads created by a factory are + * reference-counted via boost::shared_ptr and boost::weak_ptr. The factory + * guarantees that threads and the Runnable tasks they host will be properly + * cleaned up once the last strong reference to both is given up. + * + * Threads are created with the specified policy, priority, stack-size and + * detachable-mode detached means the thread is free-running and will release + * all system resources the when it completes. A detachable thread is not + * joinable. The join method of a detachable thread will return immediately + * with no error. + * + * By default threads are not joinable. + */ + explicit PosixThreadFactory(POLICY policy=kDefaultPolicy, + PRIORITY priority=kDefaultPriority, + int stackSize=kDefaultStackSizeMB, + bool detached=true); + + explicit PosixThreadFactory(DetachState detached); + + // From ThreadFactory; + boost::shared_ptr newThread( + const boost::shared_ptr& runnable) const; + boost::shared_ptr newThread( + const boost::shared_ptr& runnable, + DetachState detachState) const; + + // From ThreadFactory; + Thread::id_t getCurrentThreadId() const; + + /** + * Gets stack size for created threads + * + * @return int size in megabytes + */ + virtual int getStackSize() const; + + /** + * Sets stack size for created threads + * + * @param value size in megabytes + */ + virtual void setStackSize(int value); + + /** + * Gets priority relative to current policy + */ + virtual PRIORITY getPriority() const; + + /** + * Sets priority relative to current policy + */ + virtual void setPriority(PRIORITY priority); + + /** + * Sets detached mode of threads + */ + virtual void setDetached(bool detached); + virtual void setDetached(DetachState detached); + + /** + * Gets current detached mode + */ + virtual bool isDetached() const; + + private: + class Impl; + boost::shared_ptr impl_; +}; + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_POSIXTHREADFACTORY_H_ diff --git a/thrift/lib/cpp/concurrency/Thread.h b/thrift/lib/cpp/concurrency/Thread.h new file mode 100644 index 00000000..790d357b --- /dev/null +++ b/thrift/lib/cpp/concurrency/Thread.h @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_CONCURRENCY_THREAD_H_ +#define _THRIFT_CONCURRENCY_THREAD_H_ 1 + +#include +#include +#include + +namespace apache { namespace thrift { namespace concurrency { + +class Thread; + +/** + * Minimal runnable class. More or less analogous to java.lang.Runnable. + * + * @version $Id:$ + */ +class Runnable { + + public: + virtual ~Runnable() {}; + virtual void run() = 0; + + /** + * Gets the thread object that is hosting this runnable object - can return + * an empty boost::shared pointer if no references remain on the thread object + */ + virtual boost::shared_ptr thread() { return thread_.lock(); } + + /** + * Sets the thread that is executing this object. This is only meant for + * use by concrete implementations of Thread. + */ + virtual void thread(boost::shared_ptr value) { thread_ = value; } + + private: + boost::weak_ptr thread_; +}; + +/** + * Minimal thread class. Returned by thread factory bound to a Runnable object + * and ready to start execution. More or less analogous to java.lang.Thread + * (minus all the thread group, priority, mode and other baggage, since that + * is difficult to abstract across platforms and is left for platform-specific + * ThreadFactory implementations to deal with + * + * @see apache::thrift::concurrency::ThreadFactory) + */ +class Thread { + + public: + + typedef uint64_t id_t; + + virtual ~Thread() {}; + + /** + * Starts the thread. Does platform specific thread creation and + * configuration then invokes the run method of the Runnable object bound + * to this thread. + */ + virtual void start() = 0; + + /** + * Join this thread. Current thread blocks until this target thread + * completes. + */ + virtual void join() = 0; + + /** + * Gets the thread's platform-specific ID + */ + virtual id_t getId() = 0; + + /** + * Gets the runnable object this thread is hosting + */ + virtual boost::shared_ptr runnable() const { return _runnable; } + + protected: + virtual void runnable(boost::shared_ptr value) { _runnable = value; } + + private: + boost::shared_ptr _runnable; + +}; + +/** + * Factory to create platform-specific thread object and bind them to Runnable + * object for execution + */ +class ThreadFactory { + + public: + enum DetachState { + ATTACHED, + DETACHED + }; + + virtual ~ThreadFactory() {} + virtual boost::shared_ptr newThread( + const boost::shared_ptr& runnable) const = 0; + + virtual boost::shared_ptr newThread( + const boost::shared_ptr& runnable, + DetachState detachState) const = 0; + + /** Gets the current thread id or unknown_thread_id if the current thread is not a thrift thread */ + + static const Thread::id_t unknown_thread_id; + + virtual Thread::id_t getCurrentThreadId() const = 0; +}; + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_THREAD_H_ diff --git a/thrift/lib/cpp/concurrency/ThreadLocal.h b/thrift/lib/cpp/concurrency/ThreadLocal.h new file mode 100644 index 00000000..826f33c6 --- /dev/null +++ b/thrift/lib/cpp/concurrency/ThreadLocal.h @@ -0,0 +1,202 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_CONCURRENCY_THREADLOCAL_H_ +#define THRIFT_CONCURRENCY_THREADLOCAL_H_ 1 + +#include "thrift/lib/cpp/Thrift.h" +#include + +namespace apache { namespace thrift { namespace concurrency { + +template +class DefaultThreadLocalManager; + +/** + * ThreadLocal manages thread-local storage for a particular object type. + * + * Each ThreadLocal object contains a separate instance of an object for each + * thread that accesses the ThreadLocal object. + * + * Note that you should avoid creating too many ThreadLocal objects (e.g., such + * as keeping a ThreadLocal member variable in commonly allocated objects). + * The number of ThreadLocal objects cannot be larger than the value of + * PTHREAD_KEYS_MAX, which is 1024 on many systems. + * + * The ManagerT template parameter controls how object allocation and + * deallocation should be performed. When get() is called from a thread that + * does not already have an instance of the object, Manager::allocate() is + * called. When a thread exits, Manager::destroy() is called if the thread has + * an instance of this object. + */ +template > +class ThreadLocal { + public: + typedef T DataType; + typedef ManagerT Manager; + + /** + * Create a new ThreadLocal object. + */ + ThreadLocal() { + int ret = pthread_key_create(&key_, &ThreadLocal::onThreadExit); + if (ret != 0) { + throw TLibraryException("failed to allocate new thread-local key", ret); + } + } + + /** + * Access this thread's local instance of the object. + * + * If there is no instance of the object in this thread, Manager::allocate() + * will be called to allocate a new instance. (Though some Manager + * implementations may return NULL, if each thread's instance must be + * expilcitly initialized.) + */ + T *get() const { + T *obj = getNoAlloc(); + if (obj == NULL) { + Manager m; + obj = m.allocate(); + if (obj != NULL) { + setImpl(obj); + } + } + return obj; + } + + /** + * Access this thread's local instance of the object. + * + * If there is no instance of the object in this thread, NULL will be + * returned. Manager::allocate() will never be called. + */ + T *getNoAlloc() const { + return static_cast(pthread_getspecific(key_)); + } + + /** + * Operator overload to perform get() + */ + T *operator->() const { + return get(); + } + + /** + * Operator overload to perform get() + */ + T &operator*() const { + return *get(); + } + + /** + * Set the instance of the object to be used by this thread. + */ + void set(T* obj) { + T *old = getNoAlloc(); + Manager m; + m.replace(old, obj); + setImpl(obj); + } + + /** + * Clear the instance of the object used by this thread. + * + * If this thread had a non-NULL object, Manager::destroy() will be called. + */ + void clear() { + T *obj = getNoAlloc(); + if (obj != NULL) { + Manager m; + m.destroy(obj); + setImpl(NULL); + } + } + + private: + void setImpl(T* obj) const { + int ret = pthread_setspecific(key_, obj); + if (ret != 0) { + throw TLibraryException("failed to update thread-local key", ret); + } + } + + static void onThreadExit(void* arg) { + T *obj = static_cast(arg); + if (obj != NULL) { + Manager m; + m.destroy(obj); + } + } + + pthread_key_t key_; +}; + +template +class DefaultThreadLocalManager { + public: + T* allocate() { + return new T; + } + + void destroy(T* t) { + delete t; + } + + void replace(T* oldObj, T* newObj) { + if (oldObj != newObj) { + delete oldObj; + } + } +}; + +template +class DestroyOnlyThreadLocalManager { + public: + T* allocate() { + return NULL; + } + + void destroy(T* t) { + delete t; + } + + void replace(T* oldObj, T* newObj) { + if (oldObj != newObj) { + delete oldObj; + } + } +}; + +template +class NoopThreadLocalManager { + public: + T* allocate() { + return NULL; + } + + void destroy(T*) { + } + + void replace(T*, T*) { + } +}; + +}}} // apache::thrift::concurrency + +#endif // THRIFT_CONCURRENCY_THREADLOCAL_H_ diff --git a/thrift/lib/cpp/concurrency/ThreadManager.h b/thrift/lib/cpp/concurrency/ThreadManager.h new file mode 100644 index 00000000..bc23f90d --- /dev/null +++ b/thrift/lib/cpp/concurrency/ThreadManager.h @@ -0,0 +1,216 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_CONCURRENCY_THREADMANAGER_H_ +#define _THRIFT_CONCURRENCY_THREADMANAGER_H_ 1 + +#include +#include +#include + +namespace apache { namespace thrift { namespace concurrency { + +class Runnable; +class ThreadFactory; + +/** + * ThreadManager class + * + * This class manages a pool of threads. It uses a ThreadFactory to create + * threads. It never actually creates or destroys worker threads, rather + * It maintains statistics on number of idle threads, number of active threads, + * task backlog, and average wait and service times and informs the PoolPolicy + * object bound to instances of this manager of interesting transitions. It is + * then up the PoolPolicy object to decide if the thread pool size needs to be + * adjusted and call this object addWorker and removeWorker methods to make + * changes. + * + * This design allows different policy implementations to used this code to + * handle basic worker thread management and worker task execution and focus on + * policy issues. The simplest policy, StaticPolicy, does nothing other than + * create a fixed number of threads. + */ +class ThreadManager { + + protected: + ThreadManager() {} + + public: + class Task; + typedef std::tr1::function)> ExpireCallback; + typedef std::tr1::function InitCallback; + + virtual ~ThreadManager() {} + + /** + * Starts the thread manager. Verifies all attributes have been properly + * initialized, then allocates necessary resources to begin operation + */ + virtual void start() = 0; + + /** + * Stops the thread manager. Aborts all remaining unprocessed task, shuts + * down all created worker threads, and releases all allocated resources. + * This method blocks for all worker threads to complete, thus it can + * potentially block forever if a worker thread is running a task that + * won't terminate. + */ + virtual void stop() = 0; + + /** + * Joins the thread manager. This is the same as stop, except that it will + * wait until all the tasks have finished, rather than aborting the tasks. + */ + virtual void join() = 0; + + enum STATE { + UNINITIALIZED, + STARTING, + STARTED, + JOINING, + STOPPING, + STOPPED + }; + + virtual const STATE state() const = 0; + + virtual boost::shared_ptr threadFactory() const = 0; + + virtual void threadFactory(boost::shared_ptr value) = 0; + + virtual void addWorker(size_t value=1) = 0; + + virtual void removeWorker(size_t value=1) = 0; + + /** + * Gets the current number of idle worker threads + */ + virtual size_t idleWorkerCount() const = 0; + + /** + * Gets the current number of total worker threads + */ + virtual size_t workerCount() const = 0; + + /** + * Gets the current number of pending tasks + */ + virtual size_t pendingTaskCount() const = 0; + + /** + * Gets the current number of pending and executing tasks + */ + virtual size_t totalTaskCount() const = 0; + + /** + * Gets the maximum pending task count. 0 indicates no maximum + */ + virtual size_t pendingTaskCountMax() const = 0; + + /** + * Gets the number of tasks which have been expired without being run. + */ + virtual size_t expiredTaskCount() = 0; + + /** + * Adds a task to be executed at some time in the future by a worker thread. + * + * This method will block if pendingTaskCountMax() in not zero and + * pendingTaskCount() is greater than or equal to pendingTaskCountMax(). If + * this method is called in the context of a ThreadManager worker thread it + * will throw a TooManyPendingTasksException + * + * @param task The task to queue for execution + * + * @param timeout Time to wait in milliseconds to add a task when a + * pending-task-count is specified. Specific cases: + * timeout = 0 : Wait forever to queue task. + * timeout = -1 : Return immediately if pending task count exceeds specified + * max + * @param expiration when nonzero, the number of milliseconds the task is + * valid to be run; if exceeded, the task will be dropped off the queue and + * not run. + * + * @throws TooManyPendingTasksException Pending task count exceeds max + * pending task count + */ + virtual void add(boost::shared_ptrtask, + int64_t timeout=0LL, + int64_t expiration=0LL) = 0; + + /** + * Removes a pending task + */ + virtual void remove(boost::shared_ptr task) = 0; + + /** + * Remove the next pending task which would be run. + * + * @return the task removed. + */ + virtual boost::shared_ptr removeNextPending() = 0; + + /** + * Set a callback to be called when a task is expired and not run. + * + * @param expireCallback a function called with the shared_ptr for + * the expired task. + */ + virtual void setExpireCallback(ExpireCallback expireCallback) = 0; + + /** + * Set a callback to be called when a worker thread is created. + */ + virtual void setThreadInitCallback(InitCallback initCallback) = 0; + + static boost::shared_ptr newThreadManager(); + + /** + * Creates a simple thread manager the uses count number of worker threads + * and has a pendingTaskCountMax maximum pending tasks. The default, 0, + * specified no limit on pending tasks + */ + static boost::shared_ptr + newSimpleThreadManager(size_t count = 4, + size_t pendingTaskCountMax = 0, + bool enableTaskStats = false); + + /** + * Get an internal statistics. + * + * @param waitTimeUs - average time (us) task spent in a queue + * @param runTimeUs - average time (us) task spent running + * @param maxItems - max items collected for stats + */ + virtual void getStats(int64_t& waitTimeUs, int64_t& runTimeUs, + int64_t maxItems) { + waitTimeUs = 0; + runTimeUs = 0; + } + + class Task; + + class Worker; + + class Impl; +}; + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_THREADMANAGER_H_ diff --git a/thrift/lib/cpp/concurrency/TimerManager.h b/thrift/lib/cpp/concurrency/TimerManager.h new file mode 100644 index 00000000..b90a7187 --- /dev/null +++ b/thrift/lib/cpp/concurrency/TimerManager.h @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_CONCURRENCY_TIMERMANAGER_H_ +#define _THRIFT_CONCURRENCY_TIMERMANAGER_H_ 1 + +#include "thrift/lib/cpp/concurrency/Exception.h" +#include "thrift/lib/cpp/concurrency/Monitor.h" +#include "thrift/lib/cpp/concurrency/Thread.h" + +#include +#include +#include + +namespace apache { namespace thrift { namespace concurrency { + +/** + * Timer Manager + * + * This class dispatches timer tasks when they fall due. + * + * @version $Id:$ + */ +class TimerManager { + + public: + + TimerManager(); + + virtual ~TimerManager(); + + virtual boost::shared_ptr threadFactory() const; + + virtual void threadFactory(boost::shared_ptr value); + + /** + * Starts the timer manager service + * + * @throws IllegalArgumentException Missing thread factory attribute + */ + virtual void start(); + + /** + * Stops the timer manager service + */ + virtual void stop(); + + virtual size_t taskCount() const ; + + /** + * Adds a task to be executed at some time in the future by a worker thread. + * + * @param task The task to execute + * @param timeout Time in milliseconds to delay before executing task + */ + virtual void add(boost::shared_ptr task, int64_t timeout); + + /** + * Adds a task to be executed at some time in the future by a worker thread. + * + * @param task The task to execute + * @param timeout Absolute time in the future to execute task. + */ + virtual void add(boost::shared_ptr task, const struct timespec& timeout); + + /** + * Removes a pending task + * + * @throws NoSuchTaskException Specified task doesn't exist. It was either + * processed already or this call was made for a + * task that was never added to this timer + * + * @throws UncancellableTaskException Specified task is already being + * executed or has completed execution. + */ + virtual void remove(boost::shared_ptr task); + + enum STATE { + UNINITIALIZED, + STARTING, + STARTED, + STOPPING, + STOPPED + }; + + virtual const STATE state() const; + + private: + boost::shared_ptr threadFactory_; + class Task; + friend class Task; + std::multimap > taskMap_; + size_t taskCount_; + Monitor monitor_; + STATE state_; + class Dispatcher; + friend class Dispatcher; + boost::shared_ptr dispatcher_; + boost::shared_ptr dispatcherThread_; + typedef std::multimap >::iterator task_iterator; + typedef std::pair task_range; +}; + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_TIMERMANAGER_H_ diff --git a/thrift/lib/cpp/concurrency/Util.h b/thrift/lib/cpp/concurrency/Util.h new file mode 100644 index 00000000..58fc9cd6 --- /dev/null +++ b/thrift/lib/cpp/concurrency/Util.h @@ -0,0 +1,167 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_CONCURRENCY_UTIL_H_ +#define _THRIFT_CONCURRENCY_UTIL_H_ 1 + +#include +#include +#include +#include +#include + +namespace apache { namespace thrift { namespace concurrency { + +/** + * Utility methods + * + * This class contains basic utility methods for converting time formats, + * and other common platform-dependent concurrency operations. + * It should not be included in API headers for other concurrency library + * headers, since it will, by definition, pull in all sorts of horrid + * platform dependent crap. Rather it should be included directly in + * concurrency library implementation source. + * + * @version $Id:$ + */ +class Util { + public: + + static const int64_t NS_PER_S = 1000000000LL; + static const int64_t US_PER_S = 1000000LL; + static const int64_t MS_PER_S = 1000LL; + + static const int64_t NS_PER_MS = NS_PER_S / MS_PER_S; + static const int64_t NS_PER_US = NS_PER_S / US_PER_S; + static const int64_t US_PER_MS = US_PER_S / MS_PER_S; + + /** + * Converts millisecond timestamp into a timespec struct + * + * @param struct timespec& result + * @param time or duration in milliseconds + */ + static void toTimespec(struct timespec& result, int64_t value) { + result.tv_sec = value / MS_PER_S; // ms to s + result.tv_nsec = (value % MS_PER_S) * NS_PER_MS; // ms to ns + } + + static void toTimeval(struct timeval& result, int64_t value) { + result.tv_sec = value / MS_PER_S; // ms to s + result.tv_usec = (value % MS_PER_S) * US_PER_MS; // ms to us + } + + static const void toTicks(int64_t& result, int64_t secs, int64_t oldTicks, + int64_t oldTicksPerSec, int64_t newTicksPerSec) { + result = secs * newTicksPerSec; + result += oldTicks * newTicksPerSec / oldTicksPerSec; + + int64_t oldPerNew = oldTicksPerSec / newTicksPerSec; + if (oldPerNew && ((oldTicks % oldPerNew) >= (oldPerNew / 2))) { + ++result; + } + } + /** + * Converts struct timespec to arbitrary-sized ticks since epoch + */ + static const void toTicks(int64_t& result, + const struct timespec& value, + int64_t ticksPerSec) { + return toTicks(result, value.tv_sec, value.tv_nsec, NS_PER_S, ticksPerSec); + } + + /** + * Converts struct timeval to arbitrary-sized ticks since epoch + */ + static const void toTicks(int64_t& result, + const struct timeval& value, + int64_t ticksPerSec) { + return toTicks(result, value.tv_sec, value.tv_usec, US_PER_S, ticksPerSec); + } + + /** + * Converts struct timespec to milliseconds + */ + static const void toMilliseconds(int64_t& result, + const struct timespec& value) { + return toTicks(result, value, MS_PER_S); + } + + /** + * Converts struct timeval to milliseconds + */ + static const void toMilliseconds(int64_t& result, + const struct timeval& value) { + return toTicks(result, value, MS_PER_S); + } + + /** + * Converts struct timespec to microseconds + */ + static const void toUsec(int64_t& result, const struct timespec& value) { + return toTicks(result, value, US_PER_S); + } + + /** + * Converts struct timeval to microseconds + */ + static const void toUsec(int64_t& result, const struct timeval& value) { + return toTicks(result, value, US_PER_S); + } + + /** + * Get current time as a number of arbitrary-size ticks from epoch + */ + static const int64_t currentTimeTicks(int64_t ticksPerSec); + + /** + * Get current time as milliseconds from epoch + */ + static const int64_t currentTime() { return currentTimeTicks(MS_PER_S); } + + /** + * Get current time as micros from epoch + */ + static const int64_t currentTimeUsec() { return currentTimeTicks(US_PER_S); } + + /** + * Get monotonic time as a number of arbitrary-size ticks from some + * unspecified starting point. + * + * This may fall back to the current time (potentially non-monotonic) on + * systems that do not support monotonic time. + */ + static const int64_t monotonicTimeTicks(int64_t ticksPerSec); + + /** + * Get monotonic time as milliseconds. + */ + static const int64_t monotonicTime() { return monotonicTimeTicks(MS_PER_S); } + + /** + * Get current time as micros from epoch + */ + static const int64_t monotonicTimeUsec() { + return monotonicTimeTicks(US_PER_S); + } +}; + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_UTIL_H_ diff --git a/thrift/lib/cpp/concurrency/test/ThreadFactoryTests.h b/thrift/lib/cpp/concurrency/test/ThreadFactoryTests.h new file mode 100644 index 00000000..9f6f75e8 --- /dev/null +++ b/thrift/lib/cpp/concurrency/test/ThreadFactoryTests.h @@ -0,0 +1,354 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "thrift/lib/cpp/config.h" +#include "thrift/lib/cpp/concurrency/Thread.h" +#include "thrift/lib/cpp/concurrency/PosixThreadFactory.h" +#include "thrift/lib/cpp/concurrency/Monitor.h" +#include "thrift/lib/cpp/concurrency/Util.h" + +#include +#include +#include +#include + +namespace apache { namespace thrift { namespace concurrency { namespace test { + +using boost::shared_ptr; +using namespace apache::thrift::concurrency; + +/** + * ThreadManagerTests class + * + * @version $Id:$ + */ +class ThreadFactoryTests { + +public: + + static const double ERROR; + + class Task: public Runnable { + + public: + + Task() {} + + void run() { + std::cout << "\t\t\tHello World" << std::endl; + } + }; + + /** + * Hello world test + */ + bool helloWorldTest() { + + PosixThreadFactory threadFactory = PosixThreadFactory(); + + shared_ptr task = shared_ptr(new ThreadFactoryTests::Task()); + + shared_ptr thread = threadFactory.newThread(task); + + thread->start(); + + thread->join(); + + std::cout << "\t\t\tSuccess!" << std::endl; + + return true; + } + + /** + * Reap N threads + */ + class ReapNTask: public Runnable { + + public: + + ReapNTask(Monitor& monitor, int& activeCount) : + _monitor(monitor), + _count(activeCount) {} + + void run() { + Synchronized s(_monitor); + + _count--; + + //std::cout << "\t\t\tthread count: " << _count << std::endl; + + if (_count == 0) { + _monitor.notify(); + } + } + + Monitor& _monitor; + + int& _count; + }; + + bool reapNThreads(int loop=1, int count=10) { + + PosixThreadFactory threadFactory = PosixThreadFactory(); + + Monitor* monitor = new Monitor(); + + for(int lix = 0; lix < loop; lix++) { + + int* activeCount = new int(count); + + std::set > threads; + + int tix; + + for (tix = 0; tix < count; tix++) { + try { + threads.insert(threadFactory.newThread(shared_ptr(new ReapNTask(*monitor, *activeCount)))); + } catch(SystemResourceException& e) { + std::cout << "\t\t\tfailed to create " << lix * count + tix << " thread " << e.what() << std::endl; + throw e; + } + } + + tix = 0; + for (std::set >::const_iterator thread = threads.begin(); thread != threads.end(); tix++, ++thread) { + + try { + (*thread)->start(); + } catch(SystemResourceException& e) { + std::cout << "\t\t\tfailed to start " << lix * count + tix << " thread " << e.what() << std::endl; + throw e; + } + } + + { + Synchronized s(*monitor); + while (*activeCount > 0) { + monitor->wait(1000); + } + } + + std::cout << "\t\t\treaped " << lix * count << " threads" << std::endl; + } + + std::cout << "\t\t\tSuccess!" << std::endl; + + return true; + } + + class SynchStartTask: public Runnable { + + public: + + enum STATE { + UNINITIALIZED, + STARTING, + STARTED, + STOPPING, + STOPPED + }; + + SynchStartTask(Monitor& monitor, volatile STATE& state) : + _monitor(monitor), + _state(state) {} + + void run() { + { + Synchronized s(_monitor); + if (_state == SynchStartTask::STARTING) { + _state = SynchStartTask::STARTED; + _monitor.notify(); + } + } + + { + Synchronized s(_monitor); + while (_state == SynchStartTask::STARTED) { + _monitor.wait(); + } + + if (_state == SynchStartTask::STOPPING) { + _state = SynchStartTask::STOPPED; + _monitor.notifyAll(); + } + } + } + + private: + Monitor& _monitor; + volatile STATE& _state; + }; + + bool synchStartTest() { + + Monitor monitor; + + SynchStartTask::STATE state = SynchStartTask::UNINITIALIZED; + + shared_ptr task = shared_ptr(new SynchStartTask(monitor, state)); + + PosixThreadFactory threadFactory = PosixThreadFactory(); + + shared_ptr thread = threadFactory.newThread(task); + + if (state == SynchStartTask::UNINITIALIZED) { + + state = SynchStartTask::STARTING; + + thread->start(); + } + + { + Synchronized s(monitor); + while (state == SynchStartTask::STARTING) { + monitor.wait(); + } + } + + assert(state != SynchStartTask::STARTING); + + { + Synchronized s(monitor); + + try { + monitor.wait(100); + } catch(TimedOutException& e) { + } + + if (state == SynchStartTask::STARTED) { + + state = SynchStartTask::STOPPING; + + monitor.notify(); + } + + while (state == SynchStartTask::STOPPING) { + monitor.wait(); + } + } + + assert(state == SynchStartTask::STOPPED); + + bool success = true; + + std::cout << "\t\t\t" << (success ? "Success" : "Failure") << "!" << std::endl; + + return true; + } + + /** See how accurate monitor timeout is. */ + + bool monitorTimeoutTest(size_t count=1000, int64_t timeout=10) { + + Monitor monitor; + + int64_t startTime = Util::currentTime(); + + for (size_t ix = 0; ix < count; ix++) { + { + Synchronized s(monitor); + try { + monitor.wait(timeout); + } catch(TimedOutException& e) { + } + } + } + + int64_t endTime = Util::currentTime(); + + double error = ((endTime - startTime) - (count * timeout)) / (double)(count * timeout); + + if (error < 0.0) { + + error *= 1.0; + } + + bool success = error < ThreadFactoryTests::ERROR; + + std::cout << "\t\t\t" << (success ? "Success" : "Failure") << "! expected time: " << count * timeout << "ms elapsed time: "<< endTime - startTime << "ms error%: " << error * 100.0 << std::endl; + + return success; + } + + + class FloodTask : public Runnable { + public: + + FloodTask(const size_t id) :_id(id) {} + ~FloodTask(){ + if(_id % 1000 == 0) { + std::cout << "\t\tthread " << _id << " done" << std::endl; + } + } + + void run(){ + if(_id % 1000 == 0) { + std::cout << "\t\tthread " << _id << " started" << std::endl; + } + + usleep(1); + } + const size_t _id; + }; + + void foo(PosixThreadFactory *tf) { + } + + bool floodNTest(size_t loop=1, size_t count=100000) { + + bool success = false; + + for(size_t lix = 0; lix < loop; lix++) { + + PosixThreadFactory threadFactory = PosixThreadFactory(); + threadFactory.setDetached(true); + + for(size_t tix = 0; tix < count; tix++) { + + try { + + shared_ptr task(new FloodTask(lix * count + tix )); + + shared_ptr thread = threadFactory.newThread(task); + + thread->start(); + + usleep(1); + + } catch (TException& e) { + + std::cout << "\t\t\tfailed to start " << lix * count + tix << " thread " << e.what() << std::endl; + + return success; + } + } + + std::cout << "\t\t\tflooded " << (lix + 1) * count << " threads" << std::endl; + + success = true; + } + + return success; + } +}; + +const double ThreadFactoryTests::ERROR = .20; + +}}}} // apache::thrift::concurrency::test + diff --git a/thrift/lib/cpp/concurrency/test/TimerManagerTests.h b/thrift/lib/cpp/concurrency/test/TimerManagerTests.h new file mode 100644 index 00000000..964afbca --- /dev/null +++ b/thrift/lib/cpp/concurrency/test/TimerManagerTests.h @@ -0,0 +1,142 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "thrift/lib/cpp/concurrency/TimerManager.h" +#include "thrift/lib/cpp/concurrency/PosixThreadFactory.h" +#include "thrift/lib/cpp/concurrency/Monitor.h" +#include "thrift/lib/cpp/concurrency/Util.h" + +#include +#include + +namespace apache { namespace thrift { namespace concurrency { namespace test { + +using namespace apache::thrift::concurrency; + +/** + * ThreadManagerTests class + * + * @version $Id:$ + */ +class TimerManagerTests { + + public: + + static const double ERROR; + + class Task: public Runnable { + public: + + Task(Monitor& monitor, int64_t timeout) : + _timeout(timeout), + _startTime(Util::currentTime()), + _monitor(monitor), + _success(false), + _done(false) {} + + ~Task() { std::cerr << this << std::endl; } + + void run() { + + _endTime = Util::currentTime(); + + // Figure out error percentage + + int64_t delta = _endTime - _startTime; + + + delta = delta > _timeout ? delta - _timeout : _timeout - delta; + + float error = delta / _timeout; + + if(error < ERROR) { + _success = true; + } + + _done = true; + + std::cout << "\t\t\tTimerManagerTests::Task[" << this << "] done" << std::endl; //debug + + {Synchronized s(_monitor); + _monitor.notifyAll(); + } + } + + int64_t _timeout; + int64_t _startTime; + int64_t _endTime; + Monitor& _monitor; + bool _success; + bool _done; + }; + + /** + * This test creates two tasks and waits for the first to expire within 10% + * of the expected expiration time. It then verifies that the timer manager + * properly clean up itself and the remaining orphaned timeout task when the + * manager goes out of scope and its destructor is called. + */ + bool test00(int64_t timeout=1000LL) { + + shared_ptr orphanTask = shared_ptr(new TimerManagerTests::Task(_monitor, 10 * timeout)); + + { + + TimerManager timerManager; + + timerManager.threadFactory(shared_ptr(new PosixThreadFactory())); + + timerManager.start(); + + assert(timerManager.state() == TimerManager::STARTED); + + shared_ptr task = shared_ptr(new TimerManagerTests::Task(_monitor, timeout)); + + { + Synchronized s(_monitor); + + timerManager.add(orphanTask, 10 * timeout); + + timerManager.add(task, timeout); + + _monitor.wait(); + } + + assert(task->_done); + + + std::cout << "\t\t\t" << (task->_success ? "Success" : "Failure") << "!" << std::endl; + } + + // timerManager.stop(); This is where it happens via destructor + + assert(!orphanTask->_done); + + return true; + } + + friend class TestTask; + + Monitor _monitor; +}; + +const double TimerManagerTests::ERROR = .20; + +}}}} // apache::thrift::concurrency + diff --git a/thrift/lib/cpp/config.h b/thrift/lib/cpp/config.h new file mode 100644 index 00000000..78652427 --- /dev/null +++ b/thrift/lib/cpp/config.h @@ -0,0 +1,316 @@ +/* config.h. Generated by configure. */ +/* + * Generated by simpkins on 2009-11-18, + * on an x86_64 CentOS 5.2 system. + */ +/* config.hin. Generated from configure.ac by autoheader. */ + +/* Define if the AI_ADDRCONFIG symbol is unavailable */ +/* #undef AI_ADDRCONFIG */ + +/* Possible value for SIGNED_RIGHT_SHIFT_IS */ +#define ARITHMETIC_RIGHT_SHIFT 1 + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +/* #undef CRAY_STACKSEG_END */ + +/* Define to 1 if using `alloca.c'. */ +/* #undef C_ALLOCA */ + +/* Define to 1 if you have `alloca', as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* define if the Boost library is available */ +#define HAVE_BOOST + +/* Define to 1 if you have the `bzero' function. */ +#define HAVE_BZERO 1 + +/* Define to 1 if you have the `clock_gettime' function. */ +#define HAVE_CLOCK_GETTIME 1 + +/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you + don't. */ +#define HAVE_DECL_STRERROR_R 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +/* #undef HAVE_DOPRNT */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ENDIAN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the `gethostbyname' function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* define if libevent is available */ +#define HAVE_LIBEVENT + +/* Define to 1 if you have the header file. */ +#define HAVE_LIBINTL_H 1 + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#define HAVE_LIBPTHREAD 1 + +/* Define to 1 if you have the `rt' library (-lrt). */ +#define HAVE_LIBRT 1 + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#define HAVE_MALLOC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the `mkdir' function. */ +#define HAVE_MKDIR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PTHREAD_H 1 + +/* Define to 1 if the system has the type `ptrdiff_t'. */ +#define HAVE_PTRDIFF_T 1 + +/* Define to 1 if your system has a GNU libc compatible `realloc' function, + and to 0 otherwise. */ +#define HAVE_REALLOC 1 + +/* Define to 1 if you have the `realpath' function. */ +#define HAVE_REALPATH 1 + +/* Define to 1 if you have the `sched_get_priority_max' function. */ +#define HAVE_SCHED_GET_PRIORITY_MAX 1 + +/* Define to 1 if you have the `sched_get_priority_min' function. */ +#define HAVE_SCHED_GET_PRIORITY_MIN 1 + +/* Define to 1 if you have the `select' function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the `sqrt' function. */ +#define HAVE_SQRT 1 + +/* Define to 1 if `stat' has the bug that it succeeds when given the + zero-length file name argument. */ +/* #undef HAVE_STAT_EMPTY_STRING_BUG */ + +/* Define to 1 if stdbool.h conforms to C99. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDDEF_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the `strerror_r' function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the `strftime' function. */ +#define HAVE_STRFTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the `strtol' function. */ +#define HAVE_STRTOL 1 + +/* Define to 1 if you have the `strtoul' function. */ +#define HAVE_STRTOUL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vprintf' function. */ +#define HAVE_VPRINTF 1 + +/* define if zlib is available */ +#define HAVE_ZLIB + +/* Define to 1 if the system has the type `_Bool'. */ +/* #undef HAVE__BOOL */ + +/* Possible value for SIGNED_RIGHT_SHIFT_IS */ +#define LOGICAL_RIGHT_SHIFT 2 + +/* Define to 1 if `lstat' dereferences a symlink specified with a trailing + slash. */ +#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 + +/* Name of package */ +#define PACKAGE "thrift" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "thrift" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "thrift 20080411" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "thrift" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "20080411" + +/* Define to the type of arg 1 for `select'. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for `select'. */ +#define SELECT_TYPE_ARG234 (fd_set *) + +/* Define to the type of arg 5 for `select'. */ +#define SELECT_TYPE_ARG5 (struct timeval *) + +/* Indicates the effect of the right shift operator on negative signed + integers */ +#define SIGNED_RIGHT_SHIFT_IS 1 + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +/* #undef STACK_DIRECTION */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if strerror_r returns char *. */ +#define STRERROR_R_CHAR_P 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to 1 if your declares `struct tm'. */ +/* #undef TM_IN_SYS_TIME */ + +/* Possible value for SIGNED_RIGHT_SHIFT_IS */ +#define UNKNOWN_RIGHT_SHIFT 3 + +/* Version number of package */ +#define VERSION "20080411" + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#define YYTEXT_POINTER 1 + +/* Calls Google Perftools ProfilerRegisterThread() on pthread creation + + Set define to 0. It is exposing a linux 6.12 posix bug when an + application receives a SIGKILL, which causes the machine to crash. + */ +#ifndef GOOGLE_PERFTOOLS_REGISTER_THREAD +# define GOOGLE_PERFTOOLS_REGISTER_THREAD 0 +#endif + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to rpl_malloc if the replacement function should be used. */ +/* #undef malloc */ + +/* Define to `int' if does not define. */ +/* #undef mode_t */ + +/* Define to `long' if does not define. */ +/* #undef off_t */ + +/* Define to rpl_realloc if the replacement function should be used. */ +/* #undef realloc */ + +/* Define to `unsigned' if does not define. */ +/* #undef size_t */ + +/* Define to empty if the keyword `volatile' does not work. Warning: valid + code using `volatile' can become incorrect without. Disable with care. */ +/* #undef volatile */ diff --git a/thrift/lib/cpp/processor/PeekProcessor.h b/thrift/lib/cpp/processor/PeekProcessor.h new file mode 100644 index 00000000..9058252e --- /dev/null +++ b/thrift/lib/cpp/processor/PeekProcessor.h @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef PEEKPROCESSOR_H +#define PEEKPROCESSOR_H + +#include +#include "thrift/lib/cpp/TProcessor.h" +#include "thrift/lib/cpp/transport/TTransport.h" +#include "thrift/lib/cpp/transport/TTransportUtils.h" +#include "thrift/lib/cpp/transport/TBufferTransports.h" +#include + +namespace apache { namespace thrift { namespace processor { + +namespace server { +class TConnectionContext; +} + +/* + * Class for peeking at the raw data that is being processed by another processor + * and gives the derived class a chance to change behavior accordingly + * + */ +class PeekProcessor : public apache::thrift::TProcessor { + + public: + PeekProcessor(); + virtual ~PeekProcessor(); + + // Input here: actualProcessor - the underlying processor + // protocolFactory - the protocol factory used to wrap the memory buffer + // transportFactory - this TPipedTransportFactory is used to wrap the source transport + // via a call to getPipedTransport + void initialize(boost::shared_ptr actualProcessor, + boost::shared_ptr protocolFactory, + boost::shared_ptr transportFactory); + + boost::shared_ptr getPipedTransport(boost::shared_ptr in); + + void setTargetTransport(boost::shared_ptr targetTransport); + + virtual bool process(boost::shared_ptr in, + boost::shared_ptr out, + TConnectionContext* connectionContext); + + // The following three functions can be overloaded by child classes to + // achieve desired peeking behavior + virtual void peekName(const std::string& fname); + virtual void peekBuffer(uint8_t* buffer, uint32_t size); + virtual void peek(boost::shared_ptr in, + apache::thrift::protocol::TType ftype, + int16_t fid); + virtual void peekEnd(); + + private: + boost::shared_ptr actualProcessor_; + boost::shared_ptr pipedProtocol_; + boost::shared_ptr transportFactory_; + boost::shared_ptr memoryBuffer_; + boost::shared_ptr targetTransport_; +}; + +}}} // apache::thrift::processor + +#endif diff --git a/thrift/lib/cpp/processor/StatsProcessor.h b/thrift/lib/cpp/processor/StatsProcessor.h new file mode 100644 index 00000000..6197adf6 --- /dev/null +++ b/thrift/lib/cpp/processor/StatsProcessor.h @@ -0,0 +1,266 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef STATSPROCESSOR_H +#define STATSPROCESSOR_H + +#include +#include "thrift/lib/cpp/transport/TTransport.h" +#include "thrift/lib/cpp/protocol/TProtocol.h" +#include "thrift/lib/cpp/TProcessor.h" + +namespace apache { namespace thrift { namespace processor { + +/* + * Class for keeping track of function call statistics and printing them if desired + * + */ +class StatsProcessor : public apache::thrift::TProcessor { +public: + StatsProcessor(bool print, bool frequency) + : print_(print), + frequency_(frequency) + {} + virtual ~StatsProcessor() {}; + + virtual bool process(boost::shared_ptr piprot, + boost::shared_ptr poprot, + void* serverContext) { + + piprot_ = piprot; + + std::string fname; + apache::thrift::protocol::TMessageType mtype; + int32_t seqid; + + piprot_->readMessageBegin(fname, mtype, seqid); + if (mtype != apache::thrift::protocol::T_CALL) { + if (print_) { + printf("Unknown message type\n"); + } + throw apache::thrift::TLibraryException("Unexpected message type"); + } + if (print_) { + printf("%s (", fname.c_str()); + } + if (frequency_) { + if (frequency_map_.find(fname) != frequency_map_.end()) { + frequency_map_[fname]++; + } else { + frequency_map_[fname] = 1; + } + } + + apache::thrift::protocol::TType ftype; + int16_t fid; + + while (true) { + piprot_->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + + printAndPassToBuffer(ftype); + if (print_) { + printf(", "); + } + } + + if (print_) { + printf("\b\b)\n"); + } + return true; + } + + const std::map& get_frequency_map() { + return frequency_map_; + } + +protected: + void printAndPassToBuffer(apache::thrift::protocol::TType ftype) { + switch (ftype) { + case apache::thrift::protocol::T_BOOL: + { + bool boolv; + piprot_->readBool(boolv); + if (print_) { + printf("%d", boolv); + } + } + break; + case apache::thrift::protocol::T_BYTE: + { + int8_t bytev; + piprot_->readByte(bytev); + if (print_) { + printf("%d", bytev); + } + } + break; + case apache::thrift::protocol::T_I16: + { + int16_t i16; + piprot_->readI16(i16); + if (print_) { + printf("%d", i16); + } + } + break; + case apache::thrift::protocol::T_I32: + { + int32_t i32; + piprot_->readI32(i32); + if (print_) { + printf("%d", i32); + } + } + break; + case apache::thrift::protocol::T_I64: + { + int64_t i64; + piprot_->readI64(i64); + if (print_) { + printf("%ld", i64); + } + } + break; + case apache::thrift::protocol::T_DOUBLE: + { + double dub; + piprot_->readDouble(dub); + if (print_) { + printf("%f", dub); + } + } + break; + case apache::thrift::protocol::T_STRING: + { + std::string str; + piprot_->readString(str); + if (print_) { + printf("%s", str.c_str()); + } + } + break; + case apache::thrift::protocol::T_STRUCT: + { + std::string name; + int16_t fid; + apache::thrift::protocol::TType ftype; + piprot_->readStructBegin(name); + if (print_) { + printf("<"); + } + while (true) { + piprot_->readFieldBegin(name, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + printAndPassToBuffer(ftype); + if (print_) { + printf(","); + } + piprot_->readFieldEnd(); + } + piprot_->readStructEnd(); + if (print_) { + printf("\b>"); + } + } + break; + case apache::thrift::protocol::T_MAP: + { + apache::thrift::protocol::TType keyType; + apache::thrift::protocol::TType valType; + uint32_t i, size; + piprot_->readMapBegin(keyType, valType, size); + if (print_) { + printf("{"); + } + for (i = 0; i < size; i++) { + printAndPassToBuffer(keyType); + if (print_) { + printf("=>"); + } + printAndPassToBuffer(valType); + if (print_) { + printf(","); + } + } + piprot_->readMapEnd(); + if (print_) { + printf("\b}"); + } + } + break; + case apache::thrift::protocol::T_SET: + { + apache::thrift::protocol::TType elemType; + uint32_t i, size; + piprot_->readSetBegin(elemType, size); + if (print_) { + printf("{"); + } + for (i = 0; i < size; i++) { + printAndPassToBuffer(elemType); + if (print_) { + printf(","); + } + } + piprot_->readSetEnd(); + if (print_) { + printf("\b}"); + } + } + break; + case apache::thrift::protocol::T_LIST: + { + apache::thrift::protocol::TType elemType; + uint32_t i, size; + piprot_->readListBegin(elemType, size); + if (print_) { + printf("["); + } + for (i = 0; i < size; i++) { + printAndPassToBuffer(elemType); + if (print_) { + printf(","); + } + } + piprot_->readListEnd(); + if (print_) { + printf("\b]"); + } + } + break; + default: + break; + } + } + + boost::shared_ptr piprot_; + std::map frequency_map_; + + bool print_; + bool frequency_; +}; + +}}} // apache::thrift::processor + +#endif diff --git a/thrift/lib/cpp/processor/test/EventLog.h b/thrift/lib/cpp/processor/test/EventLog.h new file mode 100644 index 00000000..50d0d871 --- /dev/null +++ b/thrift/lib/cpp/processor/test/EventLog.h @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef _THRIFT_TEST_EVENTLOG_H_ +#define _THRIFT_TEST_EVENTLOG_H_ 1 + +#include "thrift/lib/cpp/concurrency/Monitor.h" + +namespace apache { namespace thrift { namespace test { + +// Initially I made EventType an enum, but using char* results +// in much more readable error messages when there is a mismatch. +// It also lets users of EventLog easily define their own new types. +// Comparing the literal pointer values should be safe, barring any strange +// linking setup that results in duplicate symbols. +typedef const char* EventType; + +struct Event { + Event(EventType type, uint32_t connectionId, uint32_t callId, + const std::string& message) : + type(type), + connectionId(connectionId), + callId(callId), + message(message) {} + + EventType type; + uint32_t connectionId; + uint32_t callId; + std::string message; +}; + +class EventLog { + public: + static EventType ET_LOG_END; + static EventType ET_CONN_CREATED; + static EventType ET_CONN_DESTROYED; + static EventType ET_CALL_STARTED; + static EventType ET_CALL_FINISHED; + static EventType ET_PROCESS; + static EventType ET_PRE_READ; + static EventType ET_POST_READ; + static EventType ET_PRE_WRITE; + static EventType ET_POST_WRITE; + static EventType ET_ASYNC_COMPLETE; + static EventType ET_HANDLER_ERROR; + + static EventType ET_CALL_INCREMENT_GENERATION; + static EventType ET_CALL_GET_GENERATION; + static EventType ET_CALL_ADD_STRING; + static EventType ET_CALL_GET_STRINGS; + static EventType ET_CALL_GET_DATA_WAIT; + static EventType ET_CALL_ONEWAY_WAIT; + static EventType ET_CALL_UNEXPECTED_EXCEPTION_WAIT; + static EventType ET_CALL_EXCEPTION_WAIT; + static EventType ET_WAIT_RETURN; + static EventType ET_CALL_SET_VALUE; + static EventType ET_CALL_GET_VALUE; + + EventLog(); + + void append(EventType type, uint32_t connectionId, uint32_t callId, + const std::string& message = ""); + + Event waitForEvent(int64_t timeout = 500); + Event waitForConnEvent(uint32_t connId, int64_t timeout = 500); + + protected: + typedef std::list EventList; + + concurrency::Monitor monitor_; + EventList events_; + uint32_t id_; + + static uint32_t nextId_; +}; + +}}} // apache::thrift::test + +#endif // _THRIFT_TEST_EVENTLOG_H_ diff --git a/thrift/lib/cpp/processor/test/Handlers.h b/thrift/lib/cpp/processor/test/Handlers.h new file mode 100644 index 00000000..4dc0e68b --- /dev/null +++ b/thrift/lib/cpp/processor/test/Handlers.h @@ -0,0 +1,311 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef _THRIFT_PROCESSOR_TEST_HANDLERS_H_ +#define _THRIFT_PROCESSOR_TEST_HANDLERS_H_ 1 + +#include "thrift/lib/cpp/processor/test/EventLog.h" +#include "thrift/lib/cpp/processor/test/gen-cpp/ChildService.h" + +#include "thrift/lib/cpp/server/TConnectionContext.h" + +namespace apache { namespace thrift { namespace test { + +class ParentHandler : virtual public ParentServiceIf { + public: + ParentHandler(const boost::shared_ptr& log) : + triggerMonitor(&mutex_), + generation_(0), + wait_(false), + log_(log) { } + + int32_t incrementGeneration() { + concurrency::Guard g(mutex_); + log_->append(EventLog::ET_CALL_INCREMENT_GENERATION, 0, 0); + return ++generation_; + } + + int32_t getGeneration() { + concurrency::Guard g(mutex_); + log_->append(EventLog::ET_CALL_GET_GENERATION, 0, 0); + return generation_; + } + + void addString(const std::string& s) { + concurrency::Guard g(mutex_); + log_->append(EventLog::ET_CALL_ADD_STRING, 0, 0); + strings_.push_back(s); + } + + void getStrings(std::vector& _return) { + concurrency::Guard g(mutex_); + log_->append(EventLog::ET_CALL_GET_STRINGS, 0, 0); + _return = strings_; + } + + void getDataWait(std::string& _return, int32_t length) { + concurrency::Guard g(mutex_); + log_->append(EventLog::ET_CALL_GET_DATA_WAIT, 0, 0); + + blockUntilTriggered(); + + _return.append(length, 'a'); + } + + void onewayWait() { + concurrency::Guard g(mutex_); + log_->append(EventLog::ET_CALL_ONEWAY_WAIT, 0, 0); + + blockUntilTriggered(); + } + + void exceptionWait(const std::string& message) { + concurrency::Guard g(mutex_); + log_->append(EventLog::ET_CALL_EXCEPTION_WAIT, 0, 0); + + blockUntilTriggered(); + + MyError e; + e.message = message; + throw e; + } + + void unexpectedExceptionWait(const std::string& message) { + concurrency::Guard g(mutex_); + log_->append(EventLog::ET_CALL_UNEXPECTED_EXCEPTION_WAIT, 0, 0); + + blockUntilTriggered(); + + MyError e; + e.message = message; + throw e; + } + + /** + * After prepareTriggeredCall() is invoked, calls to any of the *Wait() + * functions won't return until triggerPendingCalls() is invoked + * + * This has to be a separate function invoked by the main test thread + * in order to to avoid race conditions. + */ + void prepareTriggeredCall() { + concurrency::Guard g(mutex_); + wait_ = true; + } + + /** + * Wake up all calls waiting in blockUntilTriggered() + */ + void triggerPendingCalls() { + concurrency::Guard g(mutex_); + wait_ = false; + triggerMonitor.notifyAll(); + } + + protected: + /** + * blockUntilTriggered() won't return until triggerPendingCalls() is invoked + * in another thread. + * + * This should only be called when already holding mutex_. + */ + void blockUntilTriggered() { + while (wait_) { + triggerMonitor.waitForever(); + } + + // Log an event when we return + log_->append(EventLog::ET_WAIT_RETURN, 0, 0); + } + + concurrency::Mutex mutex_; + concurrency::Monitor triggerMonitor; + int32_t generation_; + bool wait_; + std::vector strings_; + boost::shared_ptr log_; +}; + +class ChildHandler : public ParentHandler, virtual public ChildServiceIf { + public: + ChildHandler(const boost::shared_ptr& log) : + ParentHandler(log), + value_(0) {} + + int32_t setValue(int32_t value) { + concurrency::Guard g(mutex_); + log_->append(EventLog::ET_CALL_SET_VALUE, 0, 0); + + int32_t oldValue = value_; + value_ = value; + return oldValue; + } + + int32_t getValue() { + concurrency::Guard g(mutex_); + log_->append(EventLog::ET_CALL_GET_VALUE, 0, 0); + + return value_; + } + + protected: + int32_t value_; +}; + +struct ConnContext { + public: + ConnContext(server::TConnectionContext* ctx, uint32_t id) : + ctx(ctx), + id(id) {} + + server::TConnectionContext* ctx; + uint32_t id; +}; + +struct CallContext { + public: + CallContext(ConnContext *context, uint32_t id, const std::string& name) : + connContext(context), + name(name), + id(id) {} + + ConnContext *connContext; + std::string name; + uint32_t id; +}; + +class ServerEventHandler : public server::TServerEventHandler { + public: + ServerEventHandler(const boost::shared_ptr& log) : + nextId_(1), + log_(log) {} + + virtual void preServe(const transport::TSocketAddress*) {} + + virtual void newConnection(server::TConnectionContext* ctx) { + ConnContext* context = new ConnContext(ctx, nextId_); + ++nextId_; + ctx->setUserData(context); + log_->append(EventLog::ET_CONN_CREATED, context->id, 0); + } + + virtual void connectionDestroyed(server::TConnectionContext* ctx) { + ConnContext* context = static_cast(ctx->getUserData()); + + if (ctx != context->ctx) { + abort(); + } + + log_->append(EventLog::ET_CONN_DESTROYED, context->id, 0); + + delete context; + } + + protected: + uint32_t nextId_; + boost::shared_ptr log_; +}; + +class ProcessorEventHandler : public TProcessorEventHandler { + public: + ProcessorEventHandler(const boost::shared_ptr& log) : + nextId_(1), + log_(log) {} + + void* getContext(const char* fnName, TConnectionContext* serverContext) { + ConnContext* connContext = + reinterpret_cast(serverContext->getUserData()); + + CallContext* context = new CallContext(connContext, nextId_, fnName); + ++nextId_; + + log_->append(EventLog::ET_CALL_STARTED, connContext->id, context->id, + fnName); + return context; + } + + void freeContext(void* ctx, const char* fnName) { + CallContext* context = reinterpret_cast(ctx); + checkName(context, fnName); + log_->append(EventLog::ET_CALL_FINISHED, context->connContext->id, + context->id, fnName); + delete context; + } + + void preRead(void* ctx, const char* fnName) { + CallContext* context = reinterpret_cast(ctx); + checkName(context, fnName); + log_->append(EventLog::ET_PRE_READ, context->connContext->id, context->id, + fnName); + } + + void postRead(void* ctx, const char* fnName, uint32_t bytes) { + CallContext* context = reinterpret_cast(ctx); + checkName(context, fnName); + log_->append(EventLog::ET_POST_READ, context->connContext->id, context->id, + fnName); + } + + void preWrite(void* ctx, const char* fnName) { + CallContext* context = reinterpret_cast(ctx); + checkName(context, fnName); + log_->append(EventLog::ET_PRE_WRITE, context->connContext->id, context->id, + fnName); + } + + void postWrite(void* ctx, const char* fnName, uint32_t bytes) { + CallContext* context = reinterpret_cast(ctx); + checkName(context, fnName); + log_->append(EventLog::ET_POST_WRITE, context->connContext->id, + context->id, fnName); + } + + void asyncComplete(void* ctx, const char* fnName) { + CallContext* context = reinterpret_cast(ctx); + checkName(context, fnName); + log_->append(EventLog::ET_ASYNC_COMPLETE, context->connContext->id, + context->id, fnName); + } + + void handlerError(void* ctx, const char* fnName) { + CallContext* context = reinterpret_cast(ctx); + checkName(context, fnName); + log_->append(EventLog::ET_HANDLER_ERROR, context->connContext->id, + context->id, fnName); + } + + protected: + void checkName(const CallContext* context, const char* fnName) { + // Note: we can't use BOOST_CHECK_EQUAL here, since the handler runs in a + // different thread from the test functions. Just abort if the names are + // different + if (context->name != fnName) { + fprintf(stderr, "call context name mismatch: \"%s\" != \"%s\"\n", + context->name.c_str(), fnName); + fflush(stderr); + abort(); + } + } + + uint32_t nextId_; + boost::shared_ptr log_; +}; + +}}} // apache::thrift::test + +#endif // _THRIFT_PROCESSOR_TEST_HANDLERS_H_ diff --git a/thrift/lib/cpp/processor/test/ServerThread.h b/thrift/lib/cpp/processor/test/ServerThread.h new file mode 100644 index 00000000..c5fcb39c --- /dev/null +++ b/thrift/lib/cpp/processor/test/ServerThread.h @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef _THRIFT_TEST_SERVERTHREAD_H_ +#define _THRIFT_TEST_SERVERTHREAD_H_ 1 + +#include "thrift/lib/cpp/TProcessor.h" +#include "thrift/lib/cpp/protocol/TProtocol.h" +#include "thrift/lib/cpp/server/TServer.h" +#include "thrift/lib/cpp/transport/TTransport.h" + +#include "thrift/lib/cpp/processor/test/EventLog.h" + +namespace apache { namespace thrift { namespace test { + +/** + * A helper class to tell ServerThread how to create the server + */ +class ServerState { + public: + virtual ~ServerState() {} + + /** + * Create a server to listen on the specified port. + * + * If the server returned fails to bind to the specified port when serve() is + * called on it, createServer() may be called again on a different port. + */ + virtual boost::shared_ptr createServer(uint16_t port) = 0; + + /** + * Get the TServerEventHandler to set on the server. + * + * This is only called after the server successfully binds and is about to + * start serving traffic. It is invoked from the server thread, rather than + * the main thread. + */ + virtual boost::shared_ptr + getServerEventHandler() { + return boost::shared_ptr(); + } + + /** + * This method is called in the server thread after server binding succeeds. + * + * Subclasses may override this method if they wish to record the final + * port that was used for the server. + */ + virtual void bindSuccessful(uint16_t port) { + } +}; + +/** + * ServerThread starts a thrift server running in a separate thread. + */ +class ServerThread { + public: + ServerThread(const boost::shared_ptr& state, bool autoStart) : + helper_(new Helper(this)), + port_(0), + running_(false), + serving_(false), + error_(false), + serverState_(state) { + if (autoStart) { + start(); + } + } + + void start(); + void stop(); + + uint16_t getPort() const { + return port_; + } + + ~ServerThread() { + if (running_) { + try { + stop(); + } catch (...) { + GlobalOutput.printf("error shutting down server"); + } + } + } + + protected: + // Annoying. thrift forces us to use shared_ptr, so we have to use + // a helper class that we can allocate on the heap and give to thrift. + // It would be simpler if we could just make Runnable and TServerEventHandler + // private base classes of ServerThread. + class Helper : public concurrency::Runnable, + public server::TServerEventHandler { + public: + Helper(ServerThread* serverThread) + : serverThread_(serverThread) {} + + void run() { + serverThread_->run(); + } + + void preServe(const transport::TSocketAddress* address) { + serverThread_->preServe(address); + } + + private: + ServerThread* serverThread_; + }; + + void run(); + void preServe(const transport::TSocketAddress* address); + + boost::shared_ptr helper_; + + uint16_t port_; + bool running_; + bool serving_; + bool error_; + concurrency::Monitor serverMonitor_; + + boost::shared_ptr serverState_; + boost::shared_ptr server_; + boost::shared_ptr thread_; +}; + +}}} // apache::thrift::test + +#endif // _THRIFT_TEST_SERVERTHREAD_H_ diff --git a/thrift/lib/cpp/processor/test/proc.thrift b/thrift/lib/cpp/processor/test/proc.thrift new file mode 100644 index 00000000..ac3c5f95 --- /dev/null +++ b/thrift/lib/cpp/processor/test/proc.thrift @@ -0,0 +1,22 @@ +namespace cpp apache.thrift.test + +exception MyError { + 1: string message +} + +service ParentService { + i32 incrementGeneration() + i32 getGeneration() + void addString(1: string s) + list getStrings() + + binary getDataWait(1: i32 length) + oneway void onewayWait() + void exceptionWait(1: string message) throws (2: MyError error) + void unexpectedExceptionWait(1: string message) +} + +service ChildService extends ParentService { + i32 setValue(1: i32 value) + i32 getValue() +} diff --git a/thrift/lib/cpp/protocol/TBase64Utils.h b/thrift/lib/cpp/protocol/TBase64Utils.h new file mode 100644 index 00000000..3def7335 --- /dev/null +++ b/thrift/lib/cpp/protocol/TBase64Utils.h @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_PROTOCOL_TBASE64UTILS_H_ +#define _THRIFT_PROTOCOL_TBASE64UTILS_H_ + +#include +#include + +namespace apache { namespace thrift { namespace protocol { + +// in must be at least len bytes +// len must be 1, 2, or 3 +// buf must be a buffer of at least 4 bytes and may not overlap in +// the data is not padded with '='; the caller can do this if desired +void base64_encode(const uint8_t *in, uint32_t len, uint8_t *buf); + +// buf must be a buffer of at least 4 bytes and contain base64 encoded values +// buf will be changed to contain output bytes +// len is number of bytes to consume from input (must be 2, 3, or 4) +// no '=' padding should be included in the input +void base64_decode(uint8_t *buf, uint32_t len); + +}}} // apache::thrift::protocol + +#endif // #define _THRIFT_PROTOCOL_TBASE64UTILS_H_ diff --git a/thrift/lib/cpp/protocol/TBinaryProtocol.h b/thrift/lib/cpp/protocol/TBinaryProtocol.h new file mode 100644 index 00000000..9a98d26c --- /dev/null +++ b/thrift/lib/cpp/protocol/TBinaryProtocol.h @@ -0,0 +1,302 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ +#define THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ 1 + +#include "thrift/lib/cpp/protocol/TProtocol.h" +#include "thrift/lib/cpp/protocol/TVirtualProtocol.h" + +#include + +namespace apache { namespace thrift { namespace protocol { + +/** + * The default binary protocol for thrift. Writes all data in a very basic + * binary format, essentially just spitting out the raw bytes. + * + */ +template +class TBinaryProtocolT + : public TVirtualProtocol< TBinaryProtocolT > { + + public: + static const int32_t VERSION_MASK = 0xffff0000; + static const int32_t VERSION_1 = 0x80010000; + // VERSION_2 (0x80020000) is taken by TDenseProtocol. + + TBinaryProtocolT(const boost::shared_ptr& trans) : + TVirtualProtocol< TBinaryProtocolT >(trans), + trans_(trans.get()), + string_limit_(0), + container_limit_(0), + strict_read_(false), + strict_write_(true), + string_buf_(NULL), + string_buf_size_(0) {} + + TBinaryProtocolT(const boost::shared_ptr& trans, + int32_t string_limit, + int32_t container_limit, + bool strict_read, + bool strict_write) : + TVirtualProtocol< TBinaryProtocolT >(trans), + trans_(trans.get()), + string_limit_(string_limit), + container_limit_(container_limit), + strict_read_(strict_read), + strict_write_(strict_write), + string_buf_(NULL), + string_buf_size_(0) {} + + /** + * Construct a TBinaryProtocolT using a raw pointer to the transport. + * + * The caller is responsible for ensuring that the transport remains valid + * for the lifetime of the protocol. + */ + TBinaryProtocolT(Transport_* trans) : + TVirtualProtocol< TBinaryProtocolT >(trans), + trans_(trans), + string_limit_(0), + container_limit_(0), + strict_read_(false), + strict_write_(true), + string_buf_(NULL), + string_buf_size_(0) {} + + ~TBinaryProtocolT() { + if (string_buf_ != NULL) { + std::free(string_buf_); + string_buf_size_ = 0; + } + } + + void setStringSizeLimit(int32_t string_limit) { + string_limit_ = string_limit; + } + + void setContainerSizeLimit(int32_t container_limit) { + container_limit_ = container_limit; + } + + void setStrict(bool strict_read, bool strict_write) { + strict_read_ = strict_read; + strict_write_ = strict_write; + } + + /** + * Writing functions. + */ + + /*ol*/ uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid); + + /*ol*/ uint32_t writeMessageEnd(); + + + inline uint32_t writeStructBegin(const char* name); + + inline uint32_t writeStructEnd(); + + inline uint32_t writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId); + + inline uint32_t writeFieldEnd(); + + inline uint32_t writeFieldStop(); + + inline uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size); + + inline uint32_t writeMapEnd(); + + inline uint32_t writeListBegin(const TType elemType, const uint32_t size); + + inline uint32_t writeListEnd(); + + inline uint32_t writeSetBegin(const TType elemType, const uint32_t size); + + inline uint32_t writeSetEnd(); + + inline uint32_t writeBool(const bool value); + + inline uint32_t writeByte(const int8_t byte); + + inline uint32_t writeI16(const int16_t i16); + + inline uint32_t writeI32(const int32_t i32); + + inline uint32_t writeI64(const int64_t i64); + + inline uint32_t writeDouble(const double dub); + + template + inline uint32_t writeString(const StrType& str); + + inline uint32_t writeBinary(const std::string& str); + + /** + * Reading functions + */ + + + /*ol*/ uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid); + + /*ol*/ uint32_t readMessageEnd(); + + inline uint32_t readStructBegin(std::string& name); + + inline uint32_t readStructEnd(); + + inline uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId); + + inline uint32_t readFieldEnd(); + + inline uint32_t readMapBegin(TType& keyType, + TType& valType, + uint32_t& size); + + inline uint32_t readMapEnd(); + + inline uint32_t readListBegin(TType& elemType, uint32_t& size); + + inline uint32_t readListEnd(); + + inline uint32_t readSetBegin(TType& elemType, uint32_t& size); + + inline uint32_t readSetEnd(); + + inline uint32_t readBool(bool& value); + // Provide the default readBool() implementation for std::vector + using TVirtualProtocol< TBinaryProtocolT >::readBool; + + inline uint32_t readByte(int8_t& byte); + + inline uint32_t readI16(int16_t& i16); + + inline uint32_t readI32(int32_t& i32); + + inline uint32_t readI64(int64_t& i64); + + inline uint32_t readDouble(double& dub); + + template + inline uint32_t readString(StrType& str); + + inline uint32_t readBinary(std::string& str); + + protected: + template + uint32_t readStringBody(StrType& str, int32_t sz); + + Transport_* trans_; + + int32_t string_limit_; + int32_t container_limit_; + + // Enforce presence of version identifier + bool strict_read_; + bool strict_write_; + + // Buffer for reading strings, save for the lifetime of the protocol to + // avoid memory churn allocating memory on every string read + uint8_t* string_buf_; + int32_t string_buf_size_; + +}; + +typedef TBinaryProtocolT TBinaryProtocol; + + +class TBinaryProtocolFactoryBase : public TProtocolFactory {}; + +/** + * Constructs binary protocol handlers + */ +template +class TBinaryProtocolFactoryT : public TBinaryProtocolFactoryBase { + public: + TBinaryProtocolFactoryT() : + string_limit_(0), + container_limit_(0), + strict_read_(false), + strict_write_(true) {} + + TBinaryProtocolFactoryT(int32_t string_limit, int32_t container_limit, + bool strict_read, bool strict_write) : + string_limit_(string_limit), + container_limit_(container_limit), + strict_read_(strict_read), + strict_write_(strict_write) {} + + virtual ~TBinaryProtocolFactoryT() {} + + void setStringSizeLimit(int32_t string_limit) { + string_limit_ = string_limit; + } + + void setContainerSizeLimit(int32_t container_limit) { + container_limit_ = container_limit; + } + + void setStrict(bool strict_read, bool strict_write) { + strict_read_ = strict_read; + strict_write_ = strict_write; + } + + boost::shared_ptr getProtocol( + boost::shared_ptr trans) { + boost::shared_ptr specific_trans = + boost::dynamic_pointer_cast(trans); + TProtocol* prot; + if (specific_trans) { + prot = new TBinaryProtocolT(specific_trans, string_limit_, + container_limit_, strict_read_, + strict_write_); + } else { + prot = new TBinaryProtocol(trans, string_limit_, container_limit_, + strict_read_, strict_write_); + } + + return boost::shared_ptr(prot); + } + + private: + int32_t string_limit_; + int32_t container_limit_; + bool strict_read_; + bool strict_write_; + +}; + +typedef TBinaryProtocolFactoryT TBinaryProtocolFactory; + +}}} // apache::thrift::protocol + +#include "TBinaryProtocol.tcc" + +#endif // #ifndef THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ diff --git a/thrift/lib/cpp/protocol/TBinaryProtocol.tcc b/thrift/lib/cpp/protocol/TBinaryProtocol.tcc new file mode 100644 index 00000000..9d14361c --- /dev/null +++ b/thrift/lib/cpp/protocol/TBinaryProtocol.tcc @@ -0,0 +1,441 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_ +#define _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_ 1 + +#include "thrift/lib/cpp/protocol/TBinaryProtocol.h" + +#include +#include + + +namespace apache { namespace thrift { namespace protocol { + +template +uint32_t TBinaryProtocolT::writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid) { + if (this->strict_write_) { + int32_t version = (VERSION_1) | ((int32_t)messageType); + uint32_t wsize = 0; + wsize += writeI32(version); + wsize += writeString(name); + wsize += writeI32(seqid); + return wsize; + } else { + uint32_t wsize = 0; + wsize += writeString(name); + wsize += writeByte((int8_t)messageType); + wsize += writeI32(seqid); + return wsize; + } +} + +template +uint32_t TBinaryProtocolT::writeMessageEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::writeStructBegin(const char* name) { + return 0; +} + +template +uint32_t TBinaryProtocolT::writeStructEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId) { + uint32_t wsize = 0; + wsize += writeByte((int8_t)fieldType); + wsize += writeI16(fieldId); + return wsize; +} + +template +uint32_t TBinaryProtocolT::writeFieldEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::writeFieldStop() { + return + writeByte((int8_t)T_STOP); +} + +template +uint32_t TBinaryProtocolT::writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size) { + uint32_t wsize = 0; + wsize += writeByte((int8_t)keyType); + wsize += writeByte((int8_t)valType); + wsize += writeI32((int32_t)size); + return wsize; +} + +template +uint32_t TBinaryProtocolT::writeMapEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::writeListBegin(const TType elemType, + const uint32_t size) { + uint32_t wsize = 0; + wsize += writeByte((int8_t) elemType); + wsize += writeI32((int32_t)size); + return wsize; +} + +template +uint32_t TBinaryProtocolT::writeListEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::writeSetBegin(const TType elemType, + const uint32_t size) { + uint32_t wsize = 0; + wsize += writeByte((int8_t)elemType); + wsize += writeI32((int32_t)size); + return wsize; +} + +template +uint32_t TBinaryProtocolT::writeSetEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::writeBool(const bool value) { + uint8_t tmp = value ? 1 : 0; + this->trans_->write(&tmp, 1); + return 1; +} + +template +uint32_t TBinaryProtocolT::writeByte(const int8_t byte) { + this->trans_->write((uint8_t*)&byte, 1); + return 1; +} + +template +uint32_t TBinaryProtocolT::writeI16(const int16_t i16) { + int16_t net = (int16_t)htons(i16); + this->trans_->write((uint8_t*)&net, 2); + return 2; +} + +template +uint32_t TBinaryProtocolT::writeI32(const int32_t i32) { + int32_t net = (int32_t)htonl(i32); + this->trans_->write((uint8_t*)&net, 4); + return 4; +} + +template +uint32_t TBinaryProtocolT::writeI64(const int64_t i64) { + int64_t net = (int64_t)htonll(i64); + this->trans_->write((uint8_t*)&net, 8); + return 8; +} + +template +uint32_t TBinaryProtocolT::writeDouble(const double dub) { + BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); + BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + + uint64_t bits = bitwise_cast(dub); + bits = htonll(bits); + this->trans_->write((uint8_t*)&bits, 8); + return 8; +} + + +template +template +uint32_t TBinaryProtocolT::writeString(const StrType& str) { + uint32_t size = str.size(); + uint32_t result = writeI32((int32_t)size); + if (size > 0) { + this->trans_->write((uint8_t*)str.data(), size); + } + return result + size; +} + +template +uint32_t TBinaryProtocolT::writeBinary(const std::string& str) { + return TBinaryProtocolT::writeString(str); +} + +/** + * Reading functions + */ + +template +uint32_t TBinaryProtocolT::readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid) { + uint32_t result = 0; + int32_t sz; + result += readI32(sz); + + if (sz < 0) { + // Check for correct version number + int32_t version = sz & VERSION_MASK; + if (version != VERSION_1) { + throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier"); + } + messageType = (TMessageType)(sz & 0x000000ff); + result += readString(name); + result += readI32(seqid); + } else { + if (this->strict_read_) { + throw TProtocolException(TProtocolException::BAD_VERSION, "No version identifier... old protocol client in strict mode?"); + } else { + // Handle pre-versioned input + int8_t type; + result += readStringBody(name, sz); + result += readByte(type); + messageType = (TMessageType)type; + result += readI32(seqid); + } + } + return result; +} + +template +uint32_t TBinaryProtocolT::readMessageEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::readStructBegin(std::string& name) { + name = ""; + return 0; +} + +template +uint32_t TBinaryProtocolT::readStructEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId) { + uint32_t result = 0; + int8_t type; + result += readByte(type); + fieldType = (TType)type; + if (fieldType == T_STOP) { + fieldId = 0; + return result; + } + result += readI16(fieldId); + return result; +} + +template +uint32_t TBinaryProtocolT::readFieldEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::readMapBegin(TType& keyType, + TType& valType, + uint32_t& size) { + int8_t k, v; + uint32_t result = 0; + int32_t sizei; + result += readByte(k); + keyType = (TType)k; + result += readByte(v); + valType = (TType)v; + result += readI32(sizei); + if (sizei < 0) { + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } else if (this->container_limit_ && sizei > this->container_limit_) { + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + size = (uint32_t)sizei; + return result; +} + +template +uint32_t TBinaryProtocolT::readMapEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::readListBegin(TType& elemType, + uint32_t& size) { + int8_t e; + uint32_t result = 0; + int32_t sizei; + result += readByte(e); + elemType = (TType)e; + result += readI32(sizei); + if (sizei < 0) { + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } else if (this->container_limit_ && sizei > this->container_limit_) { + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + size = (uint32_t)sizei; + return result; +} + +template +uint32_t TBinaryProtocolT::readListEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::readSetBegin(TType& elemType, + uint32_t& size) { + int8_t e; + uint32_t result = 0; + int32_t sizei; + result += readByte(e); + elemType = (TType)e; + result += readI32(sizei); + if (sizei < 0) { + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } else if (this->container_limit_ && sizei > this->container_limit_) { + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + size = (uint32_t)sizei; + return result; +} + +template +uint32_t TBinaryProtocolT::readSetEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::readBool(bool& value) { + uint8_t b[1]; + this->trans_->readAll(b, 1); + value = *(int8_t*)b != 0; + return 1; +} + +template +uint32_t TBinaryProtocolT::readByte(int8_t& byte) { + uint8_t b[1]; + this->trans_->readAll(b, 1); + byte = *(int8_t*)b; + return 1; +} + +template +uint32_t TBinaryProtocolT::readI16(int16_t& i16) { + uint8_t b[2]; + this->trans_->readAll(b, 2); + i16 = *bitwise_cast(&b); + i16 = (int16_t)ntohs(i16); + return 2; +} + +template +uint32_t TBinaryProtocolT::readI32(int32_t& i32) { + uint8_t b[4]; + this->trans_->readAll(b, 4); + i32 = *bitwise_cast(&b); + i32 = (int32_t)ntohl(i32); + return 4; +} + +template +uint32_t TBinaryProtocolT::readI64(int64_t& i64) { + uint8_t b[8]; + this->trans_->readAll(b, 8); + i64 = *bitwise_cast(&b); + i64 = (int64_t)ntohll(i64); + return 8; +} + +template +uint32_t TBinaryProtocolT::readDouble(double& dub) { + BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); + BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + + uint64_t bits; + uint8_t b[8]; + this->trans_->readAll(b, 8); + bits = *bitwise_cast(&b); + bits = ntohll(bits); + dub = bitwise_cast(bits); + return 8; +} + +template +template +uint32_t TBinaryProtocolT::readString(StrType& str) { + uint32_t result; + int32_t size; + result = readI32(size); + return result + readStringBody(str, size); +} + +template +uint32_t TBinaryProtocolT::readBinary(std::string& str) { + return TBinaryProtocolT::readString(str); +} + +template +template +uint32_t TBinaryProtocolT::readStringBody(StrType& str, + int32_t size) { + uint32_t result = 0; + + // Catch error cases + if (size < 0) { + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } + if (this->string_limit_ > 0 && size > this->string_limit_) { + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + + // Catch empty string case + if (size == 0) { + str.clear(); + return result; + } + + // Try to borrow first + const uint8_t* borrow_buf; + uint32_t got = size; + if ((borrow_buf = this->trans_->borrow(NULL, &got))) { + str.assign((const char*)borrow_buf, size); + this->trans_->consume(size); + return size; + } + + // Use the heap here to prevent stack overflow for v. large strings + if (size > this->string_buf_size_ || this->string_buf_ == NULL) { + void* new_string_buf = std::realloc(this->string_buf_, (uint32_t)size); + if (new_string_buf == NULL) { + throw std::bad_alloc(); + } + this->string_buf_ = (uint8_t*)new_string_buf; + this->string_buf_size_ = size; + } + this->trans_->readAll(this->string_buf_, size); + str.assign((char*)this->string_buf_, size); + return (uint32_t)size; +} + +}}} // apache::thrift::protocol + +#endif // #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_ diff --git a/thrift/lib/cpp/protocol/TCompactProtocol.h b/thrift/lib/cpp/protocol/TCompactProtocol.h new file mode 100644 index 00000000..ebef2727 --- /dev/null +++ b/thrift/lib/cpp/protocol/TCompactProtocol.h @@ -0,0 +1,313 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_PROTOCOL_TCOMPACTPROTOCOL_H_ +#define THRIFT_PROTOCOL_TCOMPACTPROTOCOL_H_ 1 + +#include "thrift/lib/cpp/protocol/TVirtualProtocol.h" + +#include +#include + +namespace apache { namespace thrift { namespace protocol { + +/** + * C++ Implementation of the Compact Protocol as described in THRIFT-110 + */ +template +class TCompactProtocolT + : public TVirtualProtocol< TCompactProtocolT > { + public: + static const int8_t VERSION_N = 2; + static const int8_t VERSION_LOW = 1; + static const int8_t VERSION_DOUBLE_BE = 2; + static const int8_t PROTOCOL_ID = static_cast(0x82); + static const int8_t VERSION_MASK = 0x1f; // 0001 1111 + + protected: + // Normally we can define static const data members of integral + // type here. However there appears to be a gcc issue when the + // high bit is set (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49896) + // unless we cast to a value that fits in an int8_t (0x82 and 0xE0 are + // uint8_t) + + static const int8_t TYPE_MASK = static_cast(0xE0); + static const int32_t TYPE_SHIFT_AMOUNT = 5; + + Transport_* trans_; + + /** + * (Writing) If we encounter a boolean field begin, save the TField here + * so it can have the value incorporated. + */ + struct { + const char* name; + TType fieldType; + int16_t fieldId; + } booleanField_; + + /** + * (Reading) If we read a field header, and it's a boolean field, save + * the boolean value here so that readBool can use it. + */ + struct { + bool hasBoolValue; + bool boolValue; + } boolValue_; + + /** + * Used to keep track of the last field for the current and previous structs, + * so we can do the delta stuff. + */ + + std::stack lastField_; + int16_t lastFieldId_; + int8_t version_; + + public: + explicit TCompactProtocolT(boost::shared_ptr trans) : + TVirtualProtocol< TCompactProtocolT >(trans), + trans_(trans.get()), + lastFieldId_(0), + version_(VERSION_N), + string_limit_(0), + string_buf_(NULL), + string_buf_size_(0), + container_limit_(0) { + booleanField_.name = NULL; + boolValue_.hasBoolValue = false; + } + + TCompactProtocolT(boost::shared_ptr trans, + int32_t string_limit, + int32_t container_limit) : + TVirtualProtocol< TCompactProtocolT >(trans), + trans_(trans.get()), + lastFieldId_(0), + version_(VERSION_N), + string_limit_(string_limit), + string_buf_(NULL), + string_buf_size_(0), + container_limit_(container_limit) { + booleanField_.name = NULL; + boolValue_.hasBoolValue = false; + } + + virtual ~TCompactProtocolT() { + if (string_buf_) { + free(string_buf_); + } + } + + /** Set this if you need backwards compatibility with an old version */ + void setVersion(const int8_t version) { + version_ = version; + } + + /** + * Writing functions + */ + + virtual uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid); + + uint32_t writeStructBegin(const char* name); + + uint32_t writeStructEnd(); + + uint32_t writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId); + + uint32_t writeFieldStop(); + + uint32_t writeListBegin(const TType elemType, + const uint32_t size); + + uint32_t writeSetBegin(const TType elemType, + const uint32_t size); + + virtual uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size); + + uint32_t writeBool(const bool value); + + uint32_t writeByte(const int8_t byte); + + uint32_t writeI16(const int16_t i16); + + uint32_t writeI32(const int32_t i32); + + uint32_t writeI64(const int64_t i64); + + uint32_t writeDouble(const double dub); + + uint32_t writeString(const char* str); + + template + uint32_t writeString(const String_& str); + + template + uint32_t writeBinary(const String_& str); + + /** + * These methods are called by structs, but don't actually have any wired + * output or purpose + */ + virtual uint32_t writeMessageEnd() { return 0; } + uint32_t writeMapEnd() { return 0; } + uint32_t writeListEnd() { return 0; } + uint32_t writeSetEnd() { return 0; } + uint32_t writeFieldEnd() { return 0; } + + protected: + int32_t writeFieldBeginInternal(const char* name, + const TType fieldType, + const int16_t fieldId, + int8_t typeOverride); + uint32_t writeCollectionBegin(int8_t elemType, int32_t size); + uint32_t writeVarint32(uint32_t n); + uint32_t writeVarint64(uint64_t n); + uint64_t i64ToZigzag(const int64_t l); + uint32_t i32ToZigzag(const int32_t n); + inline int8_t getCompactType(int8_t ttype); + + public: + uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid); + + uint32_t readStructBegin(std::string& name); + + uint32_t readStructEnd(); + + uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId); + + uint32_t readMapBegin(TType& keyType, + TType& valType, + uint32_t& size); + + uint32_t readListBegin(TType& elemType, + uint32_t& size); + + uint32_t readSetBegin(TType& elemType, + uint32_t& size); + + uint32_t readBool(bool& value); + // Provide the default readBool() implementation for std::vector + using TVirtualProtocol< TCompactProtocolT >::readBool; + + uint32_t readByte(int8_t& byte); + + uint32_t readI16(int16_t& i16); + + uint32_t readI32(int32_t& i32); + + uint32_t readI64(int64_t& i64); + + uint32_t readDouble(double& dub); + + template + uint32_t readString(String_& str); + + template + uint32_t readBinary(String_& str); + + /* + *These methods are here for the struct to call, but don't have any wire + * encoding. + */ + uint32_t readMessageEnd() { return 0; } + uint32_t readFieldEnd() { return 0; } + uint32_t readMapEnd() { return 0; } + uint32_t readListEnd() { return 0; } + uint32_t readSetEnd() { return 0; } + + protected: + uint32_t readVarint32(int32_t& i32); + uint32_t readVarint64(int64_t& i64); + int32_t zigzagToI32(uint32_t n); + int64_t zigzagToI64(uint64_t n); + TType getTType(int8_t type); + + // Buffer for reading strings, save for the lifetime of the protocol to + // avoid memory churn allocating memory on every string read + int32_t string_limit_; + uint8_t* string_buf_; + int32_t string_buf_size_; + int32_t container_limit_; +}; + +typedef TCompactProtocolT TCompactProtocol; + +/** + * Constructs compact protocol handlers + */ +template +class TCompactProtocolFactoryT : public TProtocolFactory { + public: + TCompactProtocolFactoryT() : + string_limit_(0), + container_limit_(0) {} + + TCompactProtocolFactoryT(int32_t string_limit, int32_t container_limit) : + string_limit_(string_limit), + container_limit_(container_limit) {} + + virtual ~TCompactProtocolFactoryT() {} + + void setStringSizeLimit(int32_t string_limit) { + string_limit_ = string_limit; + } + + void setContainerSizeLimit(int32_t container_limit) { + container_limit_ = container_limit; + } + + boost::shared_ptr getProtocol(boost::shared_ptr trans) { + boost::shared_ptr specific_trans = + boost::dynamic_pointer_cast(trans); + TProtocol* prot; + if (specific_trans) { + prot = new TCompactProtocolT(specific_trans, string_limit_, + container_limit_); + } else { + prot = new TCompactProtocol(trans, string_limit_, container_limit_); + } + + return boost::shared_ptr(prot); + } + + private: + int32_t string_limit_; + int32_t container_limit_; + +}; + +typedef TCompactProtocolFactoryT TCompactProtocolFactory; + +}}} // apache::thrift::protocol + +#include "TCompactProtocol.tcc" + +#endif diff --git a/thrift/lib/cpp/protocol/TCompactProtocol.tcc b/thrift/lib/cpp/protocol/TCompactProtocol.tcc new file mode 100644 index 00000000..3551d69e --- /dev/null +++ b/thrift/lib/cpp/protocol/TCompactProtocol.tcc @@ -0,0 +1,820 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_PROTOCOL_TCOMPACTPROTOCOL_TCC_ +#define THRIFT_PROTOCOL_TCOMPACTPROTOCOL_TCC_ 1 + +#include "thrift/lib/cpp/thrift_config.h" +#include "folly/Likely.h" +#include + +/* + * TCompactProtocol::i*ToZigzag depend on the fact that the right shift + * operator on a signed integer is an arithmetic (sign-extending) shift. + * If this is not the case, the current implementation will not work. + * If anyone encounters this error, we can try to figure out the best + * way to implement an arithmetic right shift on their platform. + */ +#if !defined(SIGNED_RIGHT_SHIFT_IS) || !defined(ARITHMETIC_RIGHT_SHIFT) +# error "Unable to determine the behavior of a signed right shift" +#endif +#if SIGNED_RIGHT_SHIFT_IS != ARITHMETIC_RIGHT_SHIFT +# error "TCompactProtocol currently only works if a signed right shift is arithmetic" +#endif + +namespace apache { namespace thrift { namespace protocol { + +namespace detail { namespace compact { + +enum Types { + CT_STOP = 0x00, + CT_BOOLEAN_TRUE = 0x01, + CT_BOOLEAN_FALSE = 0x02, + CT_BYTE = 0x03, + CT_I16 = 0x04, + CT_I32 = 0x05, + CT_I64 = 0x06, + CT_DOUBLE = 0x07, + CT_BINARY = 0x08, + CT_LIST = 0x09, + CT_SET = 0x0A, + CT_MAP = 0x0B, + CT_STRUCT = 0x0C, +}; + +const int8_t TTypeToCType[16] = { + CT_STOP, // T_STOP + 0, // unused + CT_BOOLEAN_TRUE, // T_BOOL + CT_BYTE, // T_BYTE + CT_DOUBLE, // T_DOUBLE + 0, // unused + CT_I16, // T_I16 + 0, // unused + CT_I32, // T_I32 + 0, // unused + CT_I64, // T_I64 + CT_BINARY, // T_STRING + CT_STRUCT, // T_STRUCT + CT_MAP, // T_MAP + CT_SET, // T_SET + CT_LIST, // T_LIST +}; + +}} // end detail::compact namespace + +template +uint32_t TCompactProtocolT::writeMessageBegin( + const std::string& name, + const TMessageType messageType, + const int32_t seqid) { + uint32_t wsize = 0; + wsize += writeByte(PROTOCOL_ID); + wsize += writeByte((version_ & VERSION_MASK) | (((int32_t)messageType << TYPE_SHIFT_AMOUNT) & TYPE_MASK)); + wsize += writeVarint32(seqid); + wsize += writeString(name); + return wsize; +} + +/** + * Write a field header containing the field id and field type. If the + * difference between the current field id and the last one is small (< 15), + * then the field id will be encoded in the 4 MSB as a delta. Otherwise, the + * field id will follow the type header as a zigzag varint. + */ +template +uint32_t TCompactProtocolT::writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId) { + if (fieldType == T_BOOL) { + booleanField_.name = name; + booleanField_.fieldType = fieldType; + booleanField_.fieldId = fieldId; + } else { + return writeFieldBeginInternal(name, fieldType, fieldId, -1); + } + return 0; +} + +/** + * Write the STOP symbol so we know there are no more fields in this struct. + */ +template +uint32_t TCompactProtocolT::writeFieldStop() { + return writeByte(T_STOP); +} + +/** + * Write a struct begin. This doesn't actually put anything on the wire. We + * use it as an opportunity to put special placeholder markers on the field + * stack so we can get the field id deltas correct. + */ +template +uint32_t TCompactProtocolT::writeStructBegin(const char* name) { + lastField_.push(lastFieldId_); + lastFieldId_ = 0; + return 0; +} + +/** + * Write a struct end. This doesn't actually put anything on the wire. We use + * this as an opportunity to pop the last field from the current struct off + * of the field stack. + */ +template +uint32_t TCompactProtocolT::writeStructEnd() { + lastFieldId_ = lastField_.top(); + lastField_.pop(); + return 0; +} + +/** + * Write a List header. + */ +template +uint32_t TCompactProtocolT::writeListBegin(const TType elemType, + const uint32_t size) { + return writeCollectionBegin(elemType, size); +} + +/** + * Write a set header. + */ +template +uint32_t TCompactProtocolT::writeSetBegin(const TType elemType, + const uint32_t size) { + return writeCollectionBegin(elemType, size); +} + +/** + * Write a map header. If the map is empty, omit the key and value type + * headers, as we don't need any additional information to skip it. + */ +template +uint32_t TCompactProtocolT::writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size) { + uint32_t wsize = 0; + + if (size == 0) { + wsize += writeByte(0); + } else { + wsize += writeVarint32(size); + wsize += writeByte(getCompactType(keyType) << 4 | getCompactType(valType)); + } + return wsize; +} + +/** + * Write a boolean value. Potentially, this could be a boolean field, in + * which case the field header info isn't written yet. If so, decide what the + * right type header is for the value and then write the field header. + * Otherwise, write a single byte. + */ +template +uint32_t TCompactProtocolT::writeBool(const bool value) { + uint32_t wsize = 0; + + if (booleanField_.name != NULL) { + // we haven't written the field header yet + wsize += writeFieldBeginInternal(booleanField_.name, + booleanField_.fieldType, + booleanField_.fieldId, + value ? detail::compact::CT_BOOLEAN_TRUE : + detail::compact::CT_BOOLEAN_FALSE); + booleanField_.name = NULL; + } else { + // we're not part of a field, so just write the value + wsize += writeByte(value ? detail::compact::CT_BOOLEAN_TRUE : + detail::compact::CT_BOOLEAN_FALSE); + } + return wsize; +} + +template +uint32_t TCompactProtocolT::writeByte(const int8_t byte) { + trans_->write((uint8_t*)&byte, 1); + return 1; +} + +/** + * Write an i16 as a zigzag varint. + */ +template +uint32_t TCompactProtocolT::writeI16(const int16_t i16) { + return writeVarint32(i32ToZigzag(i16)); +} + +/** + * Write an i32 as a zigzag varint. + */ +template +uint32_t TCompactProtocolT::writeI32(const int32_t i32) { + return writeVarint32(i32ToZigzag(i32)); +} + +/** + * Write an i64 as a zigzag varint. + */ +template +uint32_t TCompactProtocolT::writeI64(const int64_t i64) { + return writeVarint64(i64ToZigzag(i64)); +} + +/** + * Write a double to the wire as 8 bytes. + */ +template +uint32_t TCompactProtocolT::writeDouble(const double dub) { + BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); + BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + + uint64_t bits = bitwise_cast(dub); + if (version_ >= VERSION_DOUBLE_BE) { + bits = htonll(bits); + } else { + bits = htolell(bits); + } + trans_->write((uint8_t*)&bits, 8); + return 8; +} + +/** + * Write a string to the wire with a varint size preceding. + */ +template +uint32_t TCompactProtocolT::writeString(const char* str) { + return writeString(std::string(str)); +} + +template +template +uint32_t TCompactProtocolT::writeString(const String_& str) { + return writeBinary(str); +} + +template +template +uint32_t TCompactProtocolT::writeBinary(const String_& str) { + uint32_t ssize = str.size(); + uint32_t wsize = writeVarint32(ssize) + ssize; + trans_->write((uint8_t*)str.data(), ssize); + return wsize; +} + +// +// Internal Writing methods +// + +/** + * The workhorse of writeFieldBegin. It has the option of doing a + * 'type override' of the type header. This is used specifically in the + * boolean field case. + */ +template +int32_t TCompactProtocolT::writeFieldBeginInternal( + const char* name, + const TType fieldType, + const int16_t fieldId, + int8_t typeOverride) { + uint32_t wsize = 0; + + // if there's a type override, use that. + int8_t typeToWrite = (typeOverride == -1 ? getCompactType(fieldType) : typeOverride); + + // check if we can use delta encoding for the field id + if (fieldId > lastFieldId_ && fieldId - lastFieldId_ <= 15) { + // write them together + wsize += writeByte((fieldId - lastFieldId_) << 4 | typeToWrite); + } else { + // write them separate + wsize += writeByte(typeToWrite); + wsize += writeI16(fieldId); + } + + lastFieldId_ = fieldId; + return wsize; +} + +/** + * Abstract method for writing the start of lists and sets. List and sets on + * the wire differ only by the type indicator. + */ +template +uint32_t TCompactProtocolT::writeCollectionBegin(int8_t elemType, + int32_t size) { + uint32_t wsize = 0; + if (size <= 14) { + wsize += writeByte(size << 4 | getCompactType(elemType)); + } else { + wsize += writeByte(0xf0 | getCompactType(elemType)); + wsize += writeVarint32(size); + } + return wsize; +} + +/** + * Write an i32 as a varint. Results in 1-5 bytes on the wire. + */ +template +uint32_t TCompactProtocolT::writeVarint32(uint32_t n) { + uint8_t buf[5]; + uint32_t wsize = 0; + + while (true) { + if ((n & ~0x7F) == 0) { + buf[wsize++] = (int8_t)n; + break; + } else { + buf[wsize++] = (int8_t)((n & 0x7F) | 0x80); + n >>= 7; + } + } + trans_->write(buf, wsize); + return wsize; +} + +/** + * Write an i64 as a varint. Results in 1-10 bytes on the wire. + */ +template +uint32_t TCompactProtocolT::writeVarint64(uint64_t n) { + uint8_t buf[10]; + uint32_t wsize = 0; + + while (true) { + if ((n & ~0x7FL) == 0) { + buf[wsize++] = (int8_t)n; + break; + } else { + buf[wsize++] = (int8_t)((n & 0x7F) | 0x80); + n >>= 7; + } + } + trans_->write(buf, wsize); + return wsize; +} + +/** + * Convert l into a zigzag long. This allows negative numbers to be + * represented compactly as a varint. + */ +template +uint64_t TCompactProtocolT::i64ToZigzag(const int64_t l) { + return (l << 1) ^ (l >> 63); +} + +/** + * Convert n into a zigzag int. This allows negative numbers to be + * represented compactly as a varint. + */ +template +uint32_t TCompactProtocolT::i32ToZigzag(const int32_t n) { + return (n << 1) ^ (n >> 31); +} + +/** + * Given a TType value, find the appropriate detail::compact::Types value + */ +template +int8_t TCompactProtocolT::getCompactType(int8_t ttype) { + return detail::compact::TTypeToCType[ttype]; +} + +// +// Reading Methods +// + +/** + * Read a message header. + */ +template +uint32_t TCompactProtocolT::readMessageBegin( + std::string& name, + TMessageType& messageType, + int32_t& seqid) { + uint32_t rsize = 0; + int8_t protocolId; + int8_t versionAndType; + + rsize += readByte(protocolId); + if (protocolId != PROTOCOL_ID) { + throw TProtocolException(TProtocolException::BAD_VERSION, "Bad protocol identifier"); + } + + rsize += readByte(versionAndType); + version_ = (int8_t)(versionAndType & VERSION_MASK); + if (!(version_ <= VERSION_N && version_ >= VERSION_LOW)) { + throw TProtocolException(TProtocolException::BAD_VERSION, "Bad protocol version"); + } + + messageType = (TMessageType)((versionAndType >> TYPE_SHIFT_AMOUNT) & 0x03); + rsize += readVarint32(seqid); + rsize += readString(name); + + return rsize; +} + +/** + * Read a struct begin. There's nothing on the wire for this, but it is our + * opportunity to push a new struct begin marker on the field stack. + */ +template +uint32_t TCompactProtocolT::readStructBegin(std::string& name) { + name = ""; + lastField_.push(lastFieldId_); + lastFieldId_ = 0; + return 0; +} + +/** + * Doesn't actually consume any wire data, just removes the last field for + * this struct from the field stack. + */ +template +uint32_t TCompactProtocolT::readStructEnd() { + lastFieldId_ = lastField_.top(); + lastField_.pop(); + return 0; +} + +/** + * Read a field header off the wire. + */ +template +uint32_t TCompactProtocolT::readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId) { + uint32_t rsize = 0; + int8_t byte; + int8_t type; + + rsize += readByte(byte); + type = (byte & 0x0f); + + // if it's a stop, then we can return immediately, as the struct is over. + if (type == T_STOP) { + fieldType = T_STOP; + fieldId = 0; + return rsize; + } + + // mask off the 4 MSB of the type header. it could contain a field id delta. + int16_t modifier = (int16_t)(((uint8_t)byte & 0xf0) >> 4); + if (modifier == 0) { + // not a delta, look ahead for the zigzag varint field id. + rsize += readI16(fieldId); + } else { + fieldId = (int16_t)(lastFieldId_ + modifier); + } + fieldType = getTType(type); + + // if this happens to be a boolean field, the value is encoded in the type + if (type == detail::compact::CT_BOOLEAN_TRUE || + type == detail::compact::CT_BOOLEAN_FALSE) { + // save the boolean value in a special instance variable. + boolValue_.hasBoolValue = true; + boolValue_.boolValue = + (type == detail::compact::CT_BOOLEAN_TRUE ? true : false); + } + + // push the new field onto the field stack so we can keep the deltas going. + lastFieldId_ = fieldId; + return rsize; +} + +/** + * Read a map header off the wire. If the size is zero, skip reading the key + * and value type. This means that 0-length maps will yield TMaps without the + * "correct" types. + */ +template +uint32_t TCompactProtocolT::readMapBegin(TType& keyType, + TType& valType, + uint32_t& size) { + uint32_t rsize = 0; + int8_t kvType = 0; + int32_t msize = 0; + + rsize += readVarint32(msize); + if (msize != 0) + rsize += readByte(kvType); + + if (msize < 0) { + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } else if (container_limit_ && msize > container_limit_) { + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + + keyType = getTType((int8_t)((uint8_t)kvType >> 4)); + valType = getTType((int8_t)((uint8_t)kvType & 0xf)); + size = (uint32_t)msize; + + return rsize; +} + +/** + * Read a list header off the wire. If the list size is 0-14, the size will + * be packed into the element type header. If it's a longer list, the 4 MSB + * of the element type header will be 0xF, and a varint will follow with the + * true size. + */ +template +uint32_t TCompactProtocolT::readListBegin(TType& elemType, + uint32_t& size) { + int8_t size_and_type; + uint32_t rsize = 0; + int32_t lsize; + + rsize += readByte(size_and_type); + + lsize = ((uint8_t)size_and_type >> 4) & 0x0f; + if (lsize == 15) { + rsize += readVarint32(lsize); + } + + if (lsize < 0) { + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } else if (container_limit_ && lsize > container_limit_) { + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + + elemType = getTType((int8_t)(size_and_type & 0x0f)); + size = (uint32_t)lsize; + + return rsize; +} + +/** + * Read a set header off the wire. If the set size is 0-14, the size will + * be packed into the element type header. If it's a longer set, the 4 MSB + * of the element type header will be 0xF, and a varint will follow with the + * true size. + */ +template +uint32_t TCompactProtocolT::readSetBegin(TType& elemType, + uint32_t& size) { + return readListBegin(elemType, size); +} + +/** + * Read a boolean off the wire. If this is a boolean field, the value should + * already have been read during readFieldBegin, so we'll just consume the + * pre-stored value. Otherwise, read a byte. + */ +template +uint32_t TCompactProtocolT::readBool(bool& value) { + if (boolValue_.hasBoolValue == true) { + value = boolValue_.boolValue; + boolValue_.hasBoolValue = false; + return 0; + } else { + int8_t val; + readByte(val); + value = (val == detail::compact::CT_BOOLEAN_TRUE); + return 1; + } +} + +/** + * Read a single byte off the wire. Nothing interesting here. + */ +template +uint32_t TCompactProtocolT::readByte(int8_t& byte) { + uint8_t b[1]; + trans_->readAll(b, 1); + byte = *(int8_t*)b; + return 1; +} + +/** + * Read an i16 from the wire as a zigzag varint. + */ +template +uint32_t TCompactProtocolT::readI16(int16_t& i16) { + int32_t value; + uint32_t rsize = readVarint32(value); + i16 = (int16_t)zigzagToI32(value); + return rsize; +} + +/** + * Read an i32 from the wire as a zigzag varint. + */ +template +uint32_t TCompactProtocolT::readI32(int32_t& i32) { + int32_t value; + uint32_t rsize = readVarint32(value); + i32 = zigzagToI32(value); + return rsize; +} + +/** + * Read an i64 from the wire as a zigzag varint. + */ +template +uint32_t TCompactProtocolT::readI64(int64_t& i64) { + int64_t value; + uint32_t rsize = readVarint64(value); + i64 = zigzagToI64(value); + return rsize; +} + +/** + * No magic here - just read a double off the wire. + */ +template +uint32_t TCompactProtocolT::readDouble(double& dub) { + BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); + BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + + union { + uint64_t bits; + uint8_t b[8]; + } u; + trans_->readAll(u.b, 8); + if (version_ >= VERSION_DOUBLE_BE) { + u.bits = ntohll(u.bits); + } else { + u.bits = letohll(u.bits); + } + dub = bitwise_cast(u.bits); + return 8; +} + +template +template +uint32_t TCompactProtocolT::readString(String_& str) { + return readBinary(str); +} + +/** + * Read a byte[] from the wire. + */ +template +template +uint32_t TCompactProtocolT::readBinary(String_& str) { + int32_t rsize = 0; + int32_t size; + + rsize += readVarint32(size); + // Catch empty string case + if (size == 0) { + str = ""; + return rsize; + } + + // Catch error cases + if (size < 0) { + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } + if (string_limit_ > 0 && size > string_limit_) { + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + + // Use the heap here to prevent stack overflow for v. large strings + if (size > string_buf_size_ || string_buf_ == NULL) { + void* new_string_buf = std::realloc(string_buf_, (uint32_t)size); + if (new_string_buf == NULL) { + throw std::bad_alloc(); + } + string_buf_ = (uint8_t*)new_string_buf; + string_buf_size_ = size; + } + trans_->readAll(string_buf_, size); + str.assign((char*)string_buf_, size); + + return rsize + (uint32_t)size; +} + +/** + * Read an i32 from the wire as a varint. The MSB of each byte is set + * if there is another byte to follow. This can read up to 5 bytes. + */ +template +uint32_t TCompactProtocolT::readVarint32(int32_t& i32) { + int64_t val; + uint32_t rsize = readVarint64(val); + i32 = (int32_t)val; + return rsize; +} + +/** + * Read an i64 from the wire as a proper varint. The MSB of each byte is set + * if there is another byte to follow. This can read up to 10 bytes. + */ +template +uint32_t TCompactProtocolT::readVarint64(int64_t& i64) { + uint32_t rsize = 0; + uint64_t val = 0; + int shift = 0; + uint8_t buf[10]; // 64 bits / (7 bits/byte) = 10 bytes. + uint32_t buf_size = sizeof(buf); + const uint8_t* borrowed = trans_->borrow(buf, &buf_size); + + // Fast path. + if (borrowed != NULL) { + while (true) { + uint8_t byte = borrowed[rsize]; + rsize++; + val |= (uint64_t)(byte & 0x7f) << shift; + shift += 7; + if (!(byte & 0x80)) { + i64 = val; + trans_->consume(rsize); + return rsize; + } + // Have to check for invalid data so we don't crash. + if (UNLIKELY(rsize == sizeof(buf))) { + throw TProtocolException(TProtocolException::INVALID_DATA, "Variable-length int over 10 bytes."); + } + } + } + + // Slow path. + else { + while (true) { + uint8_t byte; + rsize += trans_->readAll(&byte, 1); + val |= (uint64_t)(byte & 0x7f) << shift; + shift += 7; + if (!(byte & 0x80)) { + i64 = val; + return rsize; + } + // Might as well check for invalid data on the slow path too. + if (UNLIKELY(rsize >= sizeof(buf))) { + throw TProtocolException(TProtocolException::INVALID_DATA, "Variable-length int over 10 bytes."); + } + } + } +} + +/** + * Convert from zigzag int to int. + */ +template +int32_t TCompactProtocolT::zigzagToI32(uint32_t n) { + return (n >> 1) ^ -(n & 1); +} + +/** + * Convert from zigzag long to long. + */ +template +int64_t TCompactProtocolT::zigzagToI64(uint64_t n) { + return (n >> 1) ^ -(n & 1); +} + +template +TType TCompactProtocolT::getTType(int8_t type) { + switch (type) { + case T_STOP: + return T_STOP; + case detail::compact::CT_BOOLEAN_FALSE: + case detail::compact::CT_BOOLEAN_TRUE: + return T_BOOL; + case detail::compact::CT_BYTE: + return T_BYTE; + case detail::compact::CT_I16: + return T_I16; + case detail::compact::CT_I32: + return T_I32; + case detail::compact::CT_I64: + return T_I64; + case detail::compact::CT_DOUBLE: + return T_DOUBLE; + case detail::compact::CT_BINARY: + return T_STRING; + case detail::compact::CT_LIST: + return T_LIST; + case detail::compact::CT_SET: + return T_SET; + case detail::compact::CT_MAP: + return T_MAP; + case detail::compact::CT_STRUCT: + return T_STRUCT; + default: + throw TLibraryException("don't know what type: " + type); + } + return T_STOP; +} + +}}} // apache::thrift::protocol + +#endif // THRIFT_PROTOCOL_TCOMPACTPROTOCOL_TCC_ diff --git a/thrift/lib/cpp/protocol/TDebugProtocol.h b/thrift/lib/cpp/protocol/TDebugProtocol.h new file mode 100644 index 00000000..236f9b86 --- /dev/null +++ b/thrift/lib/cpp/protocol/TDebugProtocol.h @@ -0,0 +1,360 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_PROTOCOL_TDEBUGPROTOCOL_H +#define THRIFT_PROTOCOL_TDEBUGPROTOCOL_H + +#include "thrift/lib/cpp/protocol/TVirtualProtocol.h" + +#include + +namespace apache { namespace thrift { namespace protocol { + +/* + +!!! EXPERIMENTAL CODE !!! + +This protocol is very much a work in progress. +It doesn't handle many cases properly. +It throws exceptions in many cases. +It probably segfaults in many cases. +Bug reports and feature requests are welcome. +Complaints are not. :R + +*/ + + +/** + * Protocol that prints the payload in a nice human-readable format. + * Reading from this protocol is not supported. + * + */ +class TDebugProtocol : public TVirtualProtocol { + private: + enum write_state_t + { UNINIT + , STRUCT + , LIST + , SET + , MAP_KEY + , MAP_VALUE + }; + + public: + TDebugProtocol(boost::shared_ptr trans) + : TVirtualProtocol(trans) + , trans_(trans.get()) + , string_limit_(DEFAULT_STRING_LIMIT) + , string_prefix_size_(DEFAULT_STRING_PREFIX_SIZE) + { + write_state_.push_back(UNINIT); + } + + static const int32_t DEFAULT_STRING_LIMIT = 256; + static const int32_t DEFAULT_STRING_PREFIX_SIZE = 16; + + void setStringSizeLimit(int32_t string_limit) { + string_limit_ = string_limit; + } + + void setStringPrefixSize(int32_t string_prefix_size) { + string_prefix_size_ = string_prefix_size; + } + + + uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid); + + uint32_t writeMessageEnd(); + + + uint32_t writeStructBegin(const char* name); + + uint32_t writeStructEnd(); + + uint32_t writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId); + + uint32_t writeFieldEnd(); + + uint32_t writeFieldStop(); + + uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size); + + uint32_t writeMapEnd(); + + uint32_t writeListBegin(const TType elemType, + const uint32_t size); + + uint32_t writeListEnd(); + + uint32_t writeSetBegin(const TType elemType, + const uint32_t size); + + uint32_t writeSetEnd(); + + uint32_t writeBool(const bool value); + + uint32_t writeByte(const int8_t byte); + + uint32_t writeI16(const int16_t i16); + + uint32_t writeI32(const int32_t i32); + + uint32_t writeI64(const int64_t i64); + + uint32_t writeDouble(const double dub); + + uint32_t writeString(const std::string& str); + + template + uint32_t writeString(const StrType& str) { + return writeString(std::string(str.data(), str.size())); + } + + uint32_t writeBinary(const std::string& str); + + + private: + void indentUp(); + void indentDown(); + uint32_t writePlain(const std::string& str); + uint32_t writeIndented(const std::string& str); + uint32_t startItem(); + uint32_t endItem(); + uint32_t writeItem(const std::string& str); + + static std::string fieldTypeName(TType type); + + TTransport* trans_; + + int32_t string_limit_; + int32_t string_prefix_size_; + + std::string indent_str_; + static const int indent_inc = 2; + + std::vector write_state_; + std::vector list_idx_; +}; + +/** + * Constructs debug protocol handlers + */ +class TDebugProtocolFactory : public TProtocolFactory { + public: + TDebugProtocolFactory() {} + virtual ~TDebugProtocolFactory() {} + + boost::shared_ptr getProtocol(boost::shared_ptr trans) { + return boost::shared_ptr(new TDebugProtocol(trans)); + } + +}; + +}}} // apache::thrift::protocol + + +// TODO(dreiss): Move (part of) ThriftDebugString into a .cpp file and remove this. +#include "thrift/lib/cpp/transport/TBufferTransports.h" + +namespace apache { namespace thrift { + +template +struct ThriftTypeTraits { + static const apache::thrift::protocol::TType fieldType_ = + apache::thrift::protocol::TType(99); +}; + +template<> +struct ThriftTypeTraits { + static const apache::thrift::protocol::TType fieldType_ = + apache::thrift::protocol::T_BOOL; +}; + +template<> +struct ThriftTypeTraits { + static const apache::thrift::protocol::TType fieldType_ = + apache::thrift::protocol::T_I08; +}; + +template<> +struct ThriftTypeTraits { + static const apache::thrift::protocol::TType fieldType_ = + apache::thrift::protocol::T_I16; +}; + +template<> +struct ThriftTypeTraits { + static const apache::thrift::protocol::TType fieldType_ = + apache::thrift::protocol::T_I32; +}; + +template<> +struct ThriftTypeTraits { + static const apache::thrift::protocol::TType fieldType_ = + apache::thrift::protocol::T_I64; +}; + +template<> +struct ThriftTypeTraits { + static const apache::thrift::protocol::TType fieldType_ = + apache::thrift::protocol::T_DOUBLE; +}; + +template<> +struct ThriftTypeTraits { + static const apache::thrift::protocol::TType fieldType_ = + apache::thrift::protocol::T_STRING; +}; + +class TDebugProtocolEx : public apache::thrift::protocol::TDebugProtocol { +public: + TDebugProtocolEx( + boost::shared_ptr trans + ) + : TDebugProtocol(trans) { + } + + template + void write(const T& t) { + t.write(this); + } + + template + void write(const std::vector& c) { + writeListBegin(ThriftTypeTraits::fieldType_, c.size()); + typeof(c.begin()) it = c.begin(); + for (; it != c.end(); it++) { + write(*it); + } + writeListEnd(); + } + + template + void write(const std::map& c) { + writeMapBegin( + ThriftTypeTraits::fieldType_, + ThriftTypeTraits::fieldType_, + c.size() + ); + typeof(c.begin()) it = c.begin(); + for (; it != c.end(); it++) { + write(it->first); + write(it->second); + } + writeMapEnd(); + } + + template + void write(const std::multimap& c) { + writeMapBegin( + ThriftTypeTraits::fieldType_, + ThriftTypeTraits::fieldType_, + c.size() + ); + typeof(c.begin()) it = c.begin(); + for (; it != c.end(); it++) { + write(it->first); + write(it->second); + } + writeMapEnd(); + } + + + template + void write(const std::set& c) { + writeSetBegin( + ThriftTypeTraits::fieldType_, + c.size() + ); + typeof(c.begin()) it = c.begin(); + for (; it != c.end(); it++) { + write(*it); + } + writeSetEnd(); + } + + void write(const bool value) { + writeBool(value); + } + + void write(const int8_t byte) { + writeByte(byte); + } + + void write(const int16_t i16) { + writeI16(i16); + } + + void write(const int32_t i32) { + writeI32(i32); + } + + void write(const int64_t i64) { + writeI64(i64); + } + + void write(const double dub) { + writeDouble(dub); + } + + void write(const std::string& str) { + writeString(str); + } + + template + void write(const std::pair& p) { + writeStructBegin("pair"); + writeFieldBegin("first", ThriftTypeTraits::fieldType_, 1); + write(p.first); + writeFieldEnd(); + writeFieldBegin("second", ThriftTypeTraits::fieldType_, 2); + write(p.second); + writeFieldEnd(); + writeStructEnd(); + } +}; + +template +std::string ThriftDebugString(const T& ts) { + using namespace apache::thrift::transport; + using namespace apache::thrift::protocol; + TMemoryBuffer* buffer = new TMemoryBuffer; + boost::shared_ptr trans(buffer); + TDebugProtocolEx protocol(trans); + + protocol.write(ts); + + uint8_t* buf; + uint32_t size; + buffer->getBuffer(&buf, &size); + return std::string((char*)buf, (unsigned int)size); +} + +}} // apache::thrift + + +#endif // #ifndef _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_ + + diff --git a/thrift/lib/cpp/protocol/THeaderProtocol.h b/thrift/lib/cpp/protocol/THeaderProtocol.h new file mode 100644 index 00000000..1ab4656e --- /dev/null +++ b/thrift/lib/cpp/protocol/THeaderProtocol.h @@ -0,0 +1,376 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_PROTOCOL_THEADERPROTOCOL_H_ +#define THRIFT_PROTOCOL_THEADERPROTOCOL_H_ 1 + +#include "thrift/lib/cpp/protocol/TProtocol.h" +#include "thrift/lib/cpp/protocol/TProtocolTypes.h" +#include "thrift/lib/cpp/protocol/TVirtualProtocol.h" +#include "thrift/lib/cpp/transport/THeaderTransport.h" +#include "thrift/lib/cpp/util/shared_ptr_util.h" + +#include + +#include + +using apache::thrift::transport::THeaderTransport; +using apache::thrift::transport::TTransportPair; + +namespace apache { namespace thrift { namespace protocol { + +/** + * The header protocol for thrift. Reads unframed, framed, header format, + * and http + * + */ +class THeaderProtocol + : public TVirtualProtocol { + public: + explicit THeaderProtocol(const boost::shared_ptr& trans, + std::bitset* clientTypes = NULL, + uint16_t protoId = T_COMPACT_PROTOCOL) : + TVirtualProtocol(getTransportWrapper(trans, + clientTypes)) + , trans_(boost::dynamic_pointer_cast( + this->getTransport())) + , protoId_(protoId) + { + trans_->setProtocolId(protoId); + resetProtocol(); + } + + THeaderProtocol(const boost::shared_ptr& inTrans, + const boost::shared_ptr& outTrans, + std::bitset* clientTypes = NULL, + uint16_t protoId = T_COMPACT_PROTOCOL) : + TVirtualProtocol(getInOutTransportWrapper(inTrans, + outTrans, + clientTypes)) + , trans_(boost::dynamic_pointer_cast( + this->getTransport())) + , protoId_(protoId) + { + trans_->setProtocolId(protoId); + resetProtocol(); + } + + /** + * Construct a THeaderProtocol using a raw pointer to the transport. + * + * The caller is responsible for ensuring that the transport remains valid + * for the lifetime of the protocol. + */ + THeaderProtocol(TTransport* trans, + std::bitset* clientTypes, + uint16_t protoId = T_COMPACT_PROTOCOL) : + TVirtualProtocol( + getTransportWrapper( + boost::shared_ptr(trans, + NoopPtrDestructor()), + clientTypes)) + , trans_(boost::dynamic_pointer_cast( + this->getTransport())) + , protoId_(protoId) + { + trans_->setProtocolId(protoId); + resetProtocol(); + } + + ~THeaderProtocol() {} + + /** + * Functions to work with headers by calling into THeaderTransport + */ + void setProtocolId(uint16_t protoId) { + trans_->setProtocolId(protoId); + resetProtocol(); + } + + void resetProtocol(); + + typedef THeaderTransport::StringToStringMap StringToStringMap; + + // these work with write headers + void setHeader(const std::string& key, const std::string& value) { + trans_->setHeader(key, value); + } + + void setPersistentHeader(const std::string& key, const std::string& value) { + trans_->setPersistentHeader(key, value); + } + + void clearHeaders() { + trans_->clearHeaders(); + } + + void clearPersistentHeaders() { + trans_->clearPersistentHeaders(); + } + + StringToStringMap& getWriteHeaders() { + return trans_->getWriteHeaders(); + } + + StringToStringMap& getPersistentWriteHeaders() { + return trans_->getPersistentWriteHeaders(); + } + + // these work with read headers + const StringToStringMap& getHeaders() const { + return trans_->getHeaders(); + } + + void setTransform(uint16_t trans) { + trans_->setTransform(trans); + } + + std::string getPeerIdentity() const { + return trans_->getPeerIdentity(); + } + void setIdentity(const std::string& identity) { + trans_->setIdentity(identity); + } + + void setHmac(THeaderTransport::MacCallback macCb, + THeaderTransport::VerifyMacCallback verifyCb) { + trans_->setHmac(macCb, verifyCb); + } + + /** + * Writing functions. + */ + + /*ol*/ uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqId); + + /*ol*/ uint32_t writeMessageEnd(); + + + uint32_t writeStructBegin(const char* name); + + uint32_t writeStructEnd(); + + uint32_t writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId); + + uint32_t writeFieldEnd(); + + uint32_t writeFieldStop(); + + uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size); + + uint32_t writeMapEnd(); + + uint32_t writeListBegin(const TType elemType, const uint32_t size); + + uint32_t writeListEnd(); + + uint32_t writeSetBegin(const TType elemType, const uint32_t size); + + uint32_t writeSetEnd(); + + uint32_t writeBool(const bool value); + + uint32_t writeByte(const int8_t byte); + + uint32_t writeI16(const int16_t i16); + + uint32_t writeI32(const int32_t i32); + + uint32_t writeI64(const int64_t i64); + + uint32_t writeDouble(const double dub); + + template + uint32_t writeString(const StrType& str) { + return proto_->writeString(str); + } + + uint32_t writeBinary(const std::string& str); + + /** + * Reading functions + */ + + + /*ol*/ uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqId); + + /*ol*/ uint32_t readMessageEnd(); + + uint32_t readStructBegin(std::string& name); + + uint32_t readStructEnd(); + + uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId); + + uint32_t readFieldEnd(); + + uint32_t readMapBegin(TType& keyType, + TType& valType, + uint32_t& size); + + uint32_t readMapEnd(); + + uint32_t readListBegin(TType& elemType, uint32_t& size); + + uint32_t readListEnd(); + + uint32_t readSetBegin(TType& elemType, uint32_t& size); + + uint32_t readSetEnd(); + + uint32_t readBool(bool& value); + // Provide the default readBool() implementation for std::vector + using TVirtualProtocol< THeaderProtocol >::readBool; + + uint32_t readByte(int8_t& byte); + + uint32_t readI16(int16_t& i16); + + uint32_t readI32(int32_t& i32); + + uint32_t readI64(int64_t& i64); + + uint32_t readDouble(double& dub); + + template + uint32_t readString(StrType& str) { + return proto_->readString(str); + } + + uint32_t readBinary(std::string& binary); + + protected: + template + uint32_t readStringBody(StrType& str, int32_t sz); + + boost::shared_ptr getTransportWrapper( + const boost::shared_ptr& trans, + std::bitset* clientTypes) { + if (dynamic_cast(trans.get()) != NULL) { + return trans; + } else { + return boost::shared_ptr( + new THeaderTransport(trans, clientTypes)); + } + } + + boost::shared_ptr getInOutTransportWrapper( + const boost::shared_ptr& inTrans, + const boost::shared_ptr& outTrans, + std::bitset* clientTypes) { + assert(dynamic_cast(inTrans.get()) == NULL + && dynamic_cast(outTrans.get()) == NULL); + + return boost::shared_ptr( + new THeaderTransport(inTrans, outTrans, clientTypes) + ); + } + + boost::shared_ptr trans_; + + boost::shared_ptr proto_; + uint32_t protoId_; +}; + +/** + * Constructs header protocol handlers + */ +class THeaderProtocolFactory : public TDuplexProtocolFactory { + public: + explicit THeaderProtocolFactory(uint16_t protoId = T_COMPACT_PROTOCOL, + bool disableIdentity = false) { + protoId_ = protoId; + setIdentity_ = disableIdentity; + } + + virtual ~THeaderProtocolFactory() {} + + void setClientTypes(std::bitset& clientTypes) { + for (int i = 0; i < CLIENT_TYPES_LEN; i++) { + this->clientTypes[i] = clientTypes[i]; + } + } + + void setIdentity(const std::string& identity) { + identity_ = identity; + setIdentity_ = true; + } + + void setTransform(uint16_t trans) { + trans_.push_back(trans); + } + + virtual TProtocolPair getProtocol( + boost::shared_ptr trans) { + THeaderProtocol* prot = new THeaderProtocol(trans, &clientTypes, protoId_); + + if(setIdentity_) { + prot->setIdentity(identity_); + } + + for (auto& t : trans_) { + prot->setTransform(t); + } + + boost::shared_ptr pprot(prot); + return TProtocolPair(pprot, pprot); + } + + virtual TProtocolPair getProtocol(TTransportPair transports) { + THeaderProtocol* prot = new THeaderProtocol(transports.first, + transports.second, + &clientTypes, + protoId_); + + if(setIdentity_) { + prot->setIdentity(identity_); + } + + for (auto& t : trans_) { + prot->setTransform(t); + } + + boost::shared_ptr pprot(prot); + return TProtocolPair(pprot, pprot); + } + + // No implementation of getInputProtocolFactory/getOutputProtocolFactory + // Using base class implementation which return NULL. + + private: + std::bitset clientTypes; + uint16_t protoId_; + bool setIdentity_; + std::vector trans_; + std::string identity_; +}; + +}}} // apache::thrift::protocol + +#endif // #ifndef THRIFT_PROTOCOL_THEADERPROTOCOL_H_ diff --git a/thrift/lib/cpp/protocol/TJSONProtocol.h b/thrift/lib/cpp/protocol/TJSONProtocol.h new file mode 100644 index 00000000..71ca8e87 --- /dev/null +++ b/thrift/lib/cpp/protocol/TJSONProtocol.h @@ -0,0 +1,348 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_PROTOCOL_TJSONPROTOCOL_H_ +#define THRIFT_PROTOCOL_TJSONPROTOCOL_H_ 1 + +#include "TVirtualProtocol.h" + +#include + +namespace apache { namespace thrift { namespace protocol { + +// Forward declaration +class TJSONContext; + +/** + * JSON protocol for Thrift. + * + * Implements a protocol which uses JSON as the wire-format. + * + * Thrift types are represented as described below: + * + * 1. Every Thrift integer type is represented as a JSON number. + * + * 2. Thrift doubles are represented as JSON numbers. Some special values are + * represented as strings: + * a. "NaN" for not-a-number values + * b. "Infinity" for positive infinity + * c. "-Infinity" for negative infinity + * + * 3. Thrift string values are emitted as JSON strings, with appropriate + * escaping. + * + * 4. Thrift binary values are encoded into Base64 and emitted as JSON strings. + * The readBinary() method is written such that it will properly skip if + * called on a Thrift string (although it will decode garbage data). + * + * 5. Thrift structs are represented as JSON objects, with the field ID as the + * key, and the field value represented as a JSON object with a single + * key-value pair. The key is a short string identifier for that type, + * followed by the value. The valid type identifiers are: "tf" for bool, + * "i8" for byte, "i16" for 16-bit integer, "i32" for 32-bit integer, "i64" + * for 64-bit integer, "dbl" for double-precision floating point, "str" for + * string (including binary), "rec" for struct ("records"), "map" for map, + * "lst" for list, "set" for set. + * + * 6. Thrift lists and sets are represented as JSON arrays, with the first + * element of the JSON array being the string identifier for the Thrift + * element type and the second element of the JSON array being the count of + * the Thrift elements. The Thrift elements then follow. + * + * 7. Thrift maps are represented as JSON arrays, with the first two elements + * of the JSON array being the string identifiers for the Thrift key type + * and value type, followed by the count of the Thrift pairs, followed by a + * JSON object containing the key-value pairs. Note that JSON keys can only + * be strings, which means that the key type of the Thrift map should be + * restricted to numeric or string types -- in the case of numerics, they + * are serialized as strings. + * + * 8. Thrift messages are represented as JSON arrays, with the protocol + * version #, the message name, the message type, and the sequence ID as + * the first 4 elements. + * + * More discussion of the double handling is probably warranted. The aim of + * the current implementation is to match as closely as possible the behavior + * of Java's Double.toString(), which has no precision loss. Implementors in + * other languages should strive to achieve that where possible. I have not + * yet verified whether boost:lexical_cast, which is doing that work for me in + * C++, loses any precision, but I am leaving this as a future improvement. I + * may try to provide a C component for this, so that other languages could + * bind to the same underlying implementation for maximum consistency. + * + * Note further that JavaScript itself is not capable of representing + * floating point infinities -- presumably when we have a JavaScript Thrift + * client, this would mean that infinities get converted to not-a-number in + * transmission. I don't know of any work-around for this issue. + * + */ +class TJSONProtocol : public TVirtualProtocol { + public: + + TJSONProtocol(boost::shared_ptr ptrans); + + ~TJSONProtocol(); + + private: + + void pushContext(boost::shared_ptr c); + + void popContext(); + + protected: + + uint32_t writeJSONEscapeChar(uint8_t ch); + + uint32_t writeJSONChar(uint8_t ch); + + uint32_t writeJSONString(const std::string &str); + + uint32_t writeJSONBase64(const std::string &str); + + template + uint32_t writeJSONInteger(NumberType num); + + uint32_t writeJSONBool(bool value); + + uint32_t writeJSONDouble(double num); + + uint32_t writeJSONObjectStart() ; + + uint32_t writeJSONObjectEnd(); + + uint32_t writeJSONArrayStart(); + + uint32_t writeJSONArrayEnd(); + + uint32_t readJSONSyntaxChar(uint8_t ch); + + uint32_t readJSONEscapeChar(uint8_t *out); + + uint32_t readJSONString(std::string &str, bool skipContext = false); + + uint32_t readJSONBase64(std::string &str); + + uint32_t readJSONNumericChars(std::string &str); + + template + uint32_t readJSONInteger(NumberType &num); + + uint32_t readJSONDouble(double &num); + + uint32_t readJSONObjectStart(); + + uint32_t readJSONObjectEnd(); + + uint32_t readJSONArrayStart(); + + uint32_t readJSONArrayEnd(); + + public: + + /** + * Writing functions. + */ + + uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid); + + uint32_t writeMessageEnd(); + + uint32_t writeStructBegin(const char* name); + + uint32_t writeStructEnd(); + + uint32_t writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId); + + uint32_t writeFieldEnd(); + + uint32_t writeFieldStop(); + + uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size); + + uint32_t writeMapEnd(); + + uint32_t writeListBegin(const TType elemType, + const uint32_t size); + + uint32_t writeListEnd(); + + uint32_t writeSetBegin(const TType elemType, + const uint32_t size); + + uint32_t writeSetEnd(); + + uint32_t writeBool(const bool value); + + uint32_t writeByte(const int8_t byte); + + uint32_t writeI16(const int16_t i16); + + uint32_t writeI32(const int32_t i32); + + uint32_t writeI64(const int64_t i64); + + uint32_t writeDouble(const double dub); + + uint32_t writeString(const std::string& str); + + uint32_t writeBinary(const std::string& str); + + /** + * Reading functions + */ + + uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid); + + uint32_t readMessageEnd(); + + uint32_t readStructBegin(std::string& name); + + uint32_t readStructEnd(); + + uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId); + + uint32_t readFieldEnd(); + + uint32_t readMapBegin(TType& keyType, + TType& valType, + uint32_t& size); + + uint32_t readMapEnd(); + + uint32_t readListBegin(TType& elemType, + uint32_t& size); + + uint32_t readListEnd(); + + uint32_t readSetBegin(TType& elemType, + uint32_t& size); + + uint32_t readSetEnd(); + + uint32_t readBool(bool& value); + + // Provide the default readBool() implementation for std::vector + using TVirtualProtocol::readBool; + + uint32_t readByte(int8_t& byte); + + uint32_t readI16(int16_t& i16); + + uint32_t readI32(int32_t& i32); + + uint32_t readI64(int64_t& i64); + + uint32_t readDouble(double& dub); + + uint32_t readString(std::string& str); + + uint32_t readBinary(std::string& str); + + class LookaheadReader { + + public: + + LookaheadReader(TTransport &trans) : + trans_(&trans), + hasData_(false) { + } + + uint8_t read() { + if (hasData_) { + hasData_ = false; + } + else { + trans_->readAll(&data_, 1); + } + return data_; + } + + uint8_t peek() { + if (!hasData_) { + trans_->readAll(&data_, 1); + } + hasData_ = true; + return data_; + } + + private: + TTransport *trans_; + bool hasData_; + uint8_t data_; + }; + + private: + TTransport* trans_; + + std::stack > contexts_; + boost::shared_ptr context_; + LookaheadReader reader_; +}; + +/** + * Constructs input and output protocol objects given transports. + */ +class TJSONProtocolFactory : public TProtocolFactory { + public: + TJSONProtocolFactory() {} + + virtual ~TJSONProtocolFactory() {} + + boost::shared_ptr getProtocol(boost::shared_ptr trans) { + return boost::shared_ptr(new TJSONProtocol(trans)); + } +}; + +}}} // apache::thrift::protocol + + +// TODO(dreiss): Move part of ThriftJSONString into a .cpp file and remove this. +#include "thrift/lib/cpp/transport/TBufferTransports.h" + +/*namespace apache { namespace thrift { + +template + std::string ThriftJSONString(const ThriftStruct& ts) { + using namespace apache::thrift::transport; + using namespace apache::thrift::protocol; + TMemoryBuffer* buffer = new TMemoryBuffer; + boost::shared_ptr trans(buffer); + TJSONProtocol protocol(trans); + + ts.write(&protocol); + + uint8_t* buf; + uint32_t size; + buffer->getBuffer(&buf, &size); + return std::string((char*)buf, (unsigned int)size); +} + +}} // apache::thrift +*/ +#endif // #define THRIFT_PROTOCOL_TJSONPROTOCOL_H_ 1 diff --git a/thrift/lib/cpp/protocol/TNeutroniumProtocol.h b/thrift/lib/cpp/protocol/TNeutroniumProtocol.h new file mode 100644 index 00000000..dfeae1e4 --- /dev/null +++ b/thrift/lib/cpp/protocol/TNeutroniumProtocol.h @@ -0,0 +1,287 @@ +/** + * Copyright 2012 Facebook + * @author Tudor Bosman (tudorb@fb.com) + */ + +#ifndef THRIFT_LIB_CPP_PROTOCOL_TNEUTRONIUMPROTOCOL_H_ +#define THRIFT_LIB_CPP_PROTOCOL_TNEUTRONIUMPROTOCOL_H_ + +#include "thrift/lib/cpp/protocol/TProtocol.h" +#include "thrift/lib/cpp/protocol/TVirtualProtocol.h" +#include "thrift/lib/cpp/protocol/neutronium/Encoder.h" +#include "thrift/lib/cpp/protocol/neutronium/Decoder.h" + +namespace apache { namespace thrift { namespace protocol { + +class TNeutroniumProtocol + : public TVirtualProtocol { + + public: + TNeutroniumProtocol(const neutronium::Schema* schema, + neutronium::InternTable* internTable, + folly::IOBuf* buf) + : TVirtualProtocol(nullptr), + enc_(schema, internTable, buf), + dec_(schema, internTable, buf) { + } + + void setRootType(int64_t rootType) { + enc_.setRootType(rootType); + dec_.setRootType(rootType); + } + + uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid) { + LOG(FATAL) << "Message encoding / decoding not implemented"; + } + + uint32_t writeMessageEnd() { + LOG(FATAL) << "Message encoding / decoding not implemented"; + } + + uint32_t writeStructBegin(const char* name) { + enc_.writeStructBegin(name); + return 0; + } + + uint32_t writeStructEnd() { + enc_.writeStructEnd(); + return enc_.bytesWritten(); + } + + uint32_t writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId) { + enc_.writeFieldBegin(name, fieldType, fieldId); + return 0; + } + + uint32_t writeFieldEnd() { + enc_.writeFieldEnd(); + return 0; + } + + uint32_t writeFieldStop() { + enc_.writeFieldStop(); + return 0; + } + + uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size) { + enc_.writeMapBegin(keyType, valType, size); + return 0; + } + + uint32_t writeMapEnd() { + enc_.writeMapEnd(); + return 0; + } + + uint32_t writeListBegin(const TType elemType, const uint32_t size) { + enc_.writeListBegin(elemType, size); + return 0; + } + + uint32_t writeListEnd() { + enc_.writeListEnd(); + return 0; + } + + uint32_t writeSetBegin(const TType elemType, const uint32_t size) { + enc_.writeSetBegin(elemType, size); + return 0; + } + + uint32_t writeSetEnd() { + enc_.writeSetEnd(); + return 0; + } + + uint32_t writeBool(const bool value) { + enc_.writeBool(value); + return 0; + } + + uint32_t writeByte(const int8_t byte) { + enc_.writeByte(byte); + return 0; + } + + uint32_t writeI16(const int16_t i16) { + enc_.writeI16(i16); + return 0; + } + + uint32_t writeI32(const int32_t i32) { + enc_.writeI32(i32); + return 0; + } + + uint32_t writeI64(const int64_t i64) { + enc_.writeI64(i64); + return 0; + } + + uint32_t writeDouble(const double dub) { + enc_.writeDouble(dub); + return 0; + } + + template + uint32_t writeString(const StrType& str) { + enc_.writeString(str); + return 0; + } + + uint32_t writeBinary(const std::string& str) { + enc_.writeBinary(str); + return 0; + } + + + /** + * Reading functions + */ + + + uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid) { + LOG(FATAL) << "Message encoding / decoding not implemented"; + } + + uint32_t readMessageEnd() { + LOG(FATAL) << "Message encoding / decoding not implemented"; + } + + uint32_t readStructBegin(std::string& name) { + dec_.readStructBegin(); + return 0; + } + + uint32_t readStructEnd() { + dec_.readStructEnd(); + return dec_.bytesRead(); + } + + uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId) { + dec_.readFieldBegin(fieldType, fieldId); + return 0; + } + + uint32_t readFieldEnd() { + dec_.readFieldEnd(); + return 0; + } + + uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size) { + dec_.readMapBegin(keyType, valType, size); + return 0; + } + + uint32_t readMapEnd() { + dec_.readMapEnd(); + return 0; + } + + uint32_t readListBegin(TType& elemType, uint32_t& size) { + dec_.readListBegin(elemType, size); + return 0; + } + + uint32_t readListEnd() { + dec_.readListEnd(); + return 0; + } + + uint32_t readSetBegin(TType& elemType, uint32_t& size) { + dec_.readSetBegin(elemType, size); + return 0; + } + + uint32_t readSetEnd() { + dec_.readSetEnd(); + return 0; + } + + uint32_t readBool(bool& value) { + dec_.readBool(value); + return 0; + } + // Provide the default readBool() implementation for std::vector + using TVirtualProtocol::readBool; + + uint32_t readByte(int8_t& byte) { + dec_.readByte(byte); + return 0; + } + + uint32_t readI16(int16_t& i16) { + dec_.readI16(i16); + return 0; + } + + uint32_t readI32(int32_t& i32) { + dec_.readI32(i32); + return 0; + } + + uint32_t readI64(int64_t& i64) { + dec_.readI64(i64); + return 0; + } + + uint32_t readDouble(double& dub) { + dec_.readDouble(dub); + return 0; + } + + template + uint32_t readString(StrType& str) { + dec_.readString(str); + return 0; + } + + uint32_t readBinary(std::string& str) { + dec_.readBinary(str); + return 0; + } + + private: + neutronium::Encoder enc_; + neutronium::Decoder dec_; +}; + +class Neutronium { + public: + explicit Neutronium(const neutronium::Schema* schema, + neutronium::InternTable* internTable, + folly::IOBuf* buf) + : proto_(schema, internTable, buf) { + } + + template + uint32_t serialize(const T& obj) { + proto_.setRootType(T::_reflection_id); + return obj.write(&proto_); + } + + template + uint32_t deserialize(T& obj) { + proto_.setRootType(T::_reflection_id); + return obj.read(&proto_); + } + + private: + TNeutroniumProtocol proto_; +}; + + +}}} // apache::thrift::protocol + +#endif /* THRIFT_LIB_CPP_PROTOCOL_TNEUTRONIUMPROTOCOL_H_ */ + diff --git a/thrift/lib/cpp/protocol/TPhpSerializeProtocol.h b/thrift/lib/cpp/protocol/TPhpSerializeProtocol.h new file mode 100644 index 00000000..d193d423 --- /dev/null +++ b/thrift/lib/cpp/protocol/TPhpSerializeProtocol.h @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_PROTOCOL_TPHPSERIALIZEPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TPHPSERIALIZEPROTOCOL_H_ 1 + +#include "thrift/lib/cpp/protocol/TVirtualProtocol.h" +#include "thrift/lib/cpp/transport/TBufferTransports.h" + +#include +#include + +namespace apache { namespace thrift { namespace protocol { + + +/** + * A Thrift protocol for serializing Thrift objects into PHP's + * "serialize" format. Should work properly for objects that + * PHP can properly express. Currently, it can silently corrupt + * data that PHP cannot properly express (lists or bools as map keys, + * very large integers on 32-bit systems, and possibly others). + */ + +class TPhpSerializeProtocol : public TVirtualProtocol { + public: + TPhpSerializeProtocol(boost::shared_ptr trans) + : TVirtualProtocol(trans) + , trans_(trans.get()) + {} + + uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid); + + uint32_t writeMessageEnd(); + + uint32_t writeStructBegin(const char* name); + + uint32_t writeStructEnd(); + + uint32_t writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId); + + uint32_t writeFieldEnd(); + + uint32_t writeFieldStop(); + + uint32_t writeListBegin(const TType elemType, + const uint32_t size); + + uint32_t writeListEnd(); + + uint32_t writeSetBegin(const TType elemType, + const uint32_t size); + + uint32_t writeSetEnd(); + + uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size); + + uint32_t writeMapEnd(); + + uint32_t writeBool(const bool value); + + uint32_t writeByte(const int8_t byte); + + uint32_t writeI16(const int16_t i16); + + uint32_t writeI32(const int32_t i32); + + uint32_t writeI64(const int64_t i64); + + uint32_t writeDouble(const double dub); + + uint32_t writeString(const std::string& str); + + uint32_t writeBinary(const std::string& str); + + protected: + uint32_t doWriteInt(const int64_t i64); + uint32_t doWriteInt(const std::string& val); + uint32_t doWriteString(const std::string& str, bool is_class); + uint32_t doWriteListBegin(uint32_t size, bool is_map); + uint32_t listKey(); + uint32_t write3(const char* v1, const char* v2, const char* v3); + uint32_t write(const char* buf, uint32_t len); + + std::stack listPosStack_; + std::stack structSizeStack_; + std::stack< boost::shared_ptr > structBufferStack_; + + TTransport* trans_; +}; + +}}} // apache::thrift::protocol + +#endif diff --git a/thrift/lib/cpp/protocol/TProtocol.h b/thrift/lib/cpp/protocol/TProtocol.h new file mode 100644 index 00000000..f35fa09a --- /dev/null +++ b/thrift/lib/cpp/protocol/TProtocol.h @@ -0,0 +1,753 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_PROTOCOL_TPROTOCOL_H_ +#define THRIFT_PROTOCOL_TPROTOCOL_H_ 1 + +#include "thrift/lib/cpp/transport/TTransport.h" +#include "thrift/lib/cpp/protocol/TProtocolException.h" +#include "thrift/lib/cpp/util/BitwiseCast.h" +#include "thrift/lib/cpp/util/shared_ptr_util.h" + +#include + +#include +#include +#include +#include +#include + +namespace apache { namespace thrift { namespace protocol { + +using apache::thrift::transport::TTransport; + +#ifdef THRIFT_HAVE_ENDIAN_H +#include +#endif + +#ifndef __BYTE_ORDER +# if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) +# define __BYTE_ORDER BYTE_ORDER +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __BIG_ENDIAN BIG_ENDIAN +# else +# error "Cannot determine endianness" +# endif +#endif + +#if __BYTE_ORDER == __BIG_ENDIAN +# if !defined(htonll) && !defined(ntohll) +# define ntohll(n) (n) +# define htonll(n) (n) +# endif /* !defined(htonll) && !defined(ntohll) */ +# if defined(__GNUC__) && defined(__GLIBC__) +# include +# define htolell(n) bswap_64(n) +# define letohll(n) bswap_64(n) +# else /* GNUC & GLIBC */ +# define bswap_64(n) \ + ( (((n) & 0xff00000000000000ull) >> 56) \ + | (((n) & 0x00ff000000000000ull) >> 40) \ + | (((n) & 0x0000ff0000000000ull) >> 24) \ + | (((n) & 0x000000ff00000000ull) >> 8) \ + | (((n) & 0x00000000ff000000ull) << 8) \ + | (((n) & 0x0000000000ff0000ull) << 24) \ + | (((n) & 0x000000000000ff00ull) << 40) \ + | (((n) & 0x00000000000000ffull) << 56) ) +# define htolell(n) bswap_64(n) +# define letohll(n) bswap_64(n) +# endif /* GNUC & GLIBC */ +#elif __BYTE_ORDER == __LITTLE_ENDIAN +# define htolell(n) (n) +# define letohll(n) (n) +# if !defined(htonll) && !defined(ntohll) +# if defined(__GNUC__) && defined(__GLIBC__) +# include +# define ntohll(n) bswap_64(n) +# define htonll(n) bswap_64(n) +# else /* GNUC & GLIBC */ +# define ntohll(n) ( (((unsigned long long)ntohl(n)) << 32) + ntohl(n >> 32) ) +# define htonll(n) ( (((unsigned long long)htonl(n)) << 32) + htonl(n >> 32) ) +# endif /* GNUC & GLIBC */ +# endif /* !defined(htonll) && !defined(ntohll) */ +#else /* __BYTE_ORDER */ +# error "Can't define htonll or ntohll!" +#endif + +/** + * Enumerated definition of the types that the Thrift protocol supports. + * Take special note of the T_END type which is used specifically to mark + * the end of a sequence of fields. + */ +enum TType { + T_STOP = 0, + T_VOID = 1, + T_BOOL = 2, + T_BYTE = 3, + T_I08 = 3, + T_I16 = 6, + T_I32 = 8, + T_U64 = 9, + T_I64 = 10, + T_DOUBLE = 4, + T_STRING = 11, + T_UTF7 = 11, + T_STRUCT = 12, + T_MAP = 13, + T_SET = 14, + T_LIST = 15, + T_UTF8 = 16, + T_UTF16 = 17 +}; + +/** + * Enumerated definition of the message types that the Thrift protocol + * supports. + */ +enum TMessageType { + T_CALL = 1, + T_REPLY = 2, + T_EXCEPTION = 3, + T_ONEWAY = 4 +}; + + +/** + * Helper template for implementing TProtocol::skip(). + * + * Templatized to avoid having to make virtual function calls. + */ +template +uint32_t skip(Protocol_& prot, TType type) { + switch (type) { + case T_BOOL: + { + bool boolv; + return prot.readBool(boolv); + } + case T_BYTE: + { + int8_t bytev = 0; + return prot.readByte(bytev); + } + case T_I16: + { + int16_t i16; + return prot.readI16(i16); + } + case T_I32: + { + int32_t i32; + return prot.readI32(i32); + } + case T_I64: + { + int64_t i64; + return prot.readI64(i64); + } + case T_DOUBLE: + { + double dub; + return prot.readDouble(dub); + } + case T_STRING: + { + std::string str; + return prot.readBinary(str); + } + case T_STRUCT: + { + uint32_t result = 0; + std::string name; + int16_t fid; + TType ftype; + result += prot.readStructBegin(name); + while (true) { + result += prot.readFieldBegin(name, ftype, fid); + if (ftype == T_STOP) { + break; + } + result += skip(prot, ftype); + result += prot.readFieldEnd(); + } + result += prot.readStructEnd(); + return result; + } + case T_MAP: + { + uint32_t result = 0; + TType keyType; + TType valType; + uint32_t i, size; + result += prot.readMapBegin(keyType, valType, size); + for (i = 0; i < size; i++) { + result += skip(prot, keyType); + result += skip(prot, valType); + } + result += prot.readMapEnd(); + return result; + } + case T_SET: + { + uint32_t result = 0; + TType elemType; + uint32_t i, size; + result += prot.readSetBegin(elemType, size); + for (i = 0; i < size; i++) { + result += skip(prot, elemType); + } + result += prot.readSetEnd(); + return result; + } + case T_LIST: + { + uint32_t result = 0; + TType elemType; + uint32_t i, size; + result += prot.readListBegin(elemType, size); + for (i = 0; i < size; i++) { + result += skip(prot, elemType); + } + result += prot.readListEnd(); + return result; + } + default: + return 0; + } +} + +/** + * Abstract class for a thrift protocol driver. These are all the methods that + * a protocol must implement. Essentially, there must be some way of reading + * and writing all the base types, plus a mechanism for writing out structs + * with indexed fields. + * + * TProtocol objects should not be shared across multiple encoding contexts, + * as they may need to maintain internal state in some protocols (i.e. XML). + * Note that is is acceptable for the TProtocol module to do its own internal + * buffered reads/writes to the underlying TTransport where appropriate (i.e. + * when parsing an input XML stream, reading should be batched rather than + * looking ahead character by character for a close tag). + * + */ +class TProtocol { + public: + virtual ~TProtocol() {} + + virtual void setVersion_virt(const int8_t version) = 0; + + void setVersion(const int8_t version) { + T_VIRTUAL_CALL(); + return setVersion_virt(version); + } + + /** + * Writing functions. + */ + + virtual uint32_t writeMessageBegin_virt(const std::string& name, + const TMessageType messageType, + const int32_t seqid) = 0; + + virtual uint32_t writeMessageEnd_virt() = 0; + + + virtual uint32_t writeStructBegin_virt(const char* name) = 0; + + virtual uint32_t writeStructEnd_virt() = 0; + + virtual uint32_t writeFieldBegin_virt(const char* name, + const TType fieldType, + const int16_t fieldId) = 0; + + virtual uint32_t writeFieldEnd_virt() = 0; + + virtual uint32_t writeFieldStop_virt() = 0; + + virtual uint32_t writeMapBegin_virt(const TType keyType, + const TType valType, + const uint32_t size) = 0; + + virtual uint32_t writeMapEnd_virt() = 0; + + virtual uint32_t writeListBegin_virt(const TType elemType, + const uint32_t size) = 0; + + virtual uint32_t writeListEnd_virt() = 0; + + virtual uint32_t writeSetBegin_virt(const TType elemType, + const uint32_t size) = 0; + + virtual uint32_t writeSetEnd_virt() = 0; + + virtual uint32_t writeBool_virt(const bool value) = 0; + + virtual uint32_t writeByte_virt(const int8_t byte) = 0; + + virtual uint32_t writeI16_virt(const int16_t i16) = 0; + + virtual uint32_t writeI32_virt(const int32_t i32) = 0; + + virtual uint32_t writeI64_virt(const int64_t i64) = 0; + + virtual uint32_t writeDouble_virt(const double dub) = 0; + + virtual uint32_t writeString_virt(const std::string& str) = 0; + + virtual uint32_t writeBinary_virt(const std::string& str) = 0; + + uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid) { + T_VIRTUAL_CALL(); + return writeMessageBegin_virt(name, messageType, seqid); + } + + uint32_t writeMessageEnd() { + T_VIRTUAL_CALL(); + return writeMessageEnd_virt(); + } + + + uint32_t writeStructBegin(const char* name) { + T_VIRTUAL_CALL(); + return writeStructBegin_virt(name); + } + + uint32_t writeStructEnd() { + T_VIRTUAL_CALL(); + return writeStructEnd_virt(); + } + + uint32_t writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId) { + T_VIRTUAL_CALL(); + return writeFieldBegin_virt(name, fieldType, fieldId); + } + + uint32_t writeFieldEnd() { + T_VIRTUAL_CALL(); + return writeFieldEnd_virt(); + } + + uint32_t writeFieldStop() { + T_VIRTUAL_CALL(); + return writeFieldStop_virt(); + } + + uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size) { + T_VIRTUAL_CALL(); + return writeMapBegin_virt(keyType, valType, size); + } + + uint32_t writeMapEnd() { + T_VIRTUAL_CALL(); + return writeMapEnd_virt(); + } + + uint32_t writeListBegin(const TType elemType, const uint32_t size) { + T_VIRTUAL_CALL(); + return writeListBegin_virt(elemType, size); + } + + uint32_t writeListEnd() { + T_VIRTUAL_CALL(); + return writeListEnd_virt(); + } + + uint32_t writeSetBegin(const TType elemType, const uint32_t size) { + T_VIRTUAL_CALL(); + return writeSetBegin_virt(elemType, size); + } + + uint32_t writeSetEnd() { + T_VIRTUAL_CALL(); + return writeSetEnd_virt(); + } + + uint32_t writeBool(const bool value) { + T_VIRTUAL_CALL(); + return writeBool_virt(value); + } + + uint32_t writeByte(const int8_t byte) { + T_VIRTUAL_CALL(); + return writeByte_virt(byte); + } + + uint32_t writeI16(const int16_t i16) { + T_VIRTUAL_CALL(); + return writeI16_virt(i16); + } + + uint32_t writeI32(const int32_t i32) { + T_VIRTUAL_CALL(); + return writeI32_virt(i32); + } + + uint32_t writeI64(const int64_t i64) { + T_VIRTUAL_CALL(); + return writeI64_virt(i64); + } + + uint32_t writeDouble(const double dub) { + T_VIRTUAL_CALL(); + return writeDouble_virt(dub); + } + + uint32_t writeString(const std::string& str) { + T_VIRTUAL_CALL(); + return writeString_virt(str); + } + + uint32_t writeBinary(const std::string& str) { + T_VIRTUAL_CALL(); + return writeBinary_virt(str); + } + + /** + * Reading functions + */ + + virtual uint32_t readMessageBegin_virt(std::string& name, + TMessageType& messageType, + int32_t& seqid) = 0; + + virtual uint32_t readMessageEnd_virt() = 0; + + virtual uint32_t readStructBegin_virt(std::string& name) = 0; + + virtual uint32_t readStructEnd_virt() = 0; + + virtual uint32_t readFieldBegin_virt(std::string& name, + TType& fieldType, + int16_t& fieldId) = 0; + + virtual uint32_t readFieldEnd_virt() = 0; + + virtual uint32_t readMapBegin_virt(TType& keyType, + TType& valType, + uint32_t& size) = 0; + + virtual uint32_t readMapEnd_virt() = 0; + + virtual uint32_t readListBegin_virt(TType& elemType, + uint32_t& size) = 0; + + virtual uint32_t readListEnd_virt() = 0; + + virtual uint32_t readSetBegin_virt(TType& elemType, + uint32_t& size) = 0; + + virtual uint32_t readSetEnd_virt() = 0; + + virtual uint32_t readBool_virt(bool& value) = 0; + + virtual uint32_t readBool_virt(std::vector::reference value) = 0; + + virtual uint32_t readByte_virt(int8_t& byte) = 0; + + virtual uint32_t readI16_virt(int16_t& i16) = 0; + + virtual uint32_t readI32_virt(int32_t& i32) = 0; + + virtual uint32_t readI64_virt(int64_t& i64) = 0; + + virtual uint32_t readDouble_virt(double& dub) = 0; + + virtual uint32_t readString_virt(std::string& str) = 0; + + virtual uint32_t readBinary_virt(std::string& str) = 0; + + uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid) { + T_VIRTUAL_CALL(); + return readMessageBegin_virt(name, messageType, seqid); + } + + uint32_t readMessageEnd() { + T_VIRTUAL_CALL(); + return readMessageEnd_virt(); + } + + uint32_t readStructBegin(std::string& name) { + T_VIRTUAL_CALL(); + return readStructBegin_virt(name); + } + + uint32_t readStructEnd() { + T_VIRTUAL_CALL(); + return readStructEnd_virt(); + } + + uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId) { + T_VIRTUAL_CALL(); + return readFieldBegin_virt(name, fieldType, fieldId); + } + + uint32_t readFieldEnd() { + T_VIRTUAL_CALL(); + return readFieldEnd_virt(); + } + + uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size) { + T_VIRTUAL_CALL(); + return readMapBegin_virt(keyType, valType, size); + } + + uint32_t readMapEnd() { + T_VIRTUAL_CALL(); + return readMapEnd_virt(); + } + + uint32_t readListBegin(TType& elemType, uint32_t& size) { + T_VIRTUAL_CALL(); + return readListBegin_virt(elemType, size); + } + + uint32_t readListEnd() { + T_VIRTUAL_CALL(); + return readListEnd_virt(); + } + + uint32_t readSetBegin(TType& elemType, uint32_t& size) { + T_VIRTUAL_CALL(); + return readSetBegin_virt(elemType, size); + } + + uint32_t readSetEnd() { + T_VIRTUAL_CALL(); + return readSetEnd_virt(); + } + + uint32_t readBool(bool& value) { + T_VIRTUAL_CALL(); + return readBool_virt(value); + } + + uint32_t readByte(int8_t& byte) { + T_VIRTUAL_CALL(); + return readByte_virt(byte); + } + + uint32_t readI16(int16_t& i16) { + T_VIRTUAL_CALL(); + return readI16_virt(i16); + } + + uint32_t readI32(int32_t& i32) { + T_VIRTUAL_CALL(); + return readI32_virt(i32); + } + + uint32_t readI64(int64_t& i64) { + T_VIRTUAL_CALL(); + return readI64_virt(i64); + } + + uint32_t readDouble(double& dub) { + T_VIRTUAL_CALL(); + return readDouble_virt(dub); + } + + uint32_t readString(std::string& str) { + T_VIRTUAL_CALL(); + return readString_virt(str); + } + + uint32_t readBinary(std::string& str) { + T_VIRTUAL_CALL(); + return readBinary_virt(str); + } + + /* + * std::vector is specialized for bool, and its elements are individual bits + * rather than bools. We need to define a different version of readBool() + * to work with std::vector. + */ + uint32_t readBool(std::vector::reference value) { + T_VIRTUAL_CALL(); + return readBool_virt(value); + } + + /** + * Method to arbitrarily skip over data. + */ + uint32_t skip(TType type) { + T_VIRTUAL_CALL(); + return skip_virt(type); + } + virtual uint32_t skip_virt(TType type) { + return ::apache::thrift::protocol::skip(*this, type); + } + + inline boost::shared_ptr getTransport() { + return ptrans_; + } + + // TODO: remove these two calls, they are for backwards + // compatibility + inline boost::shared_ptr getInputTransport() { + return ptrans_; + } + inline boost::shared_ptr getOutputTransport() { + return ptrans_; + } + + protected: + explicit TProtocol(boost::shared_ptr ptrans): + ptrans_(ptrans) { + } + + /** + * Construct a TProtocol using a raw TTransport pointer. + * + * It is the callers responsibility to ensure that the TTransport remains + * valid for the lifetime of the TProtocol object. + */ + explicit TProtocol(TTransport* ptrans): + ptrans_(ptrans, NoopPtrDestructor()) { + } + + boost::shared_ptr ptrans_; + + private: + TProtocol() {} +}; + +/** + * Constructs protocol objects given transports. + */ +class TProtocolFactory { + public: + TProtocolFactory() {} + + virtual ~TProtocolFactory() {} + + virtual boost::shared_ptr getProtocol(boost::shared_ptr trans) = 0; +}; + +/** + * Constructs both input and output protocol objects with a given pair of + * input and output transports. + * + * TProtocolPair.first = Input Protocol + * TProtocolPair.second = Output Protocol + */ +typedef std::pair, + boost::shared_ptr > TProtocolPair; + +class TDuplexProtocolFactory { + public: + TDuplexProtocolFactory() {} + + virtual ~TDuplexProtocolFactory() {} + + virtual TProtocolPair getProtocol(transport::TTransportPair transports) = 0; + + virtual boost::shared_ptr getInputProtocolFactory() { + return boost::shared_ptr(); + } + + virtual boost::shared_ptr getOutputProtocolFactory() { + return boost::shared_ptr(); + } +}; + +/** + * Adapts a TProtocolFactory to a TDuplexProtocolFactory that returns + * a new protocol object for both input and output + */ +template +class TSingleProtocolFactory : public TDuplexProtocolFactory { + public: + TSingleProtocolFactory() { + factory_.reset(new Factory_()); + } + + explicit TSingleProtocolFactory(boost::shared_ptr factory) : + factory_(factory) {} + + virtual TProtocolPair getProtocol(transport::TTransportPair transports) { + return std::make_pair(factory_->getProtocol(transports.first), + factory_->getProtocol(transports.second)); + } + + virtual boost::shared_ptr getInputProtocolFactory() { + return factory_; + } + + virtual boost::shared_ptr getOutputProtocolFactory() { + return factory_; + } + + private: + + boost::shared_ptr factory_; +}; + +/** + * Use TDualProtocolFactory to construct input and output protocols from + * different factories. + */ +class TDualProtocolFactory : public TDuplexProtocolFactory { + public: + TDualProtocolFactory( + boost::shared_ptr inputFactory, + boost::shared_ptr outputFactory) : + inputFactory_(inputFactory), + outputFactory_(outputFactory) {} + + virtual TProtocolPair getProtocol(transport::TTransportPair transports) { + return std::make_pair(inputFactory_->getProtocol(transports.first), + outputFactory_->getProtocol(transports.second)); + } + + virtual boost::shared_ptr getInputProtocolFactory() { + return inputFactory_; + } + + virtual boost::shared_ptr getOutputProtocolFactory() { + return outputFactory_; + } + + private: + + boost::shared_ptr inputFactory_; + boost::shared_ptr outputFactory_; +}; + +/** + * Dummy protocol class. + * + * This class does nothing, and should never be instantiated. + * It is used only by the generator code. + */ +class TDummyProtocol : public TProtocol { +}; + +}}} // apache::thrift::protocol + +#endif // #define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1 diff --git a/thrift/lib/cpp/protocol/TProtocolException.h b/thrift/lib/cpp/protocol/TProtocolException.h new file mode 100644 index 00000000..e9f3856a --- /dev/null +++ b/thrift/lib/cpp/protocol/TProtocolException.h @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_ +#define _THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_ 1 + +#include + +namespace apache { namespace thrift { namespace protocol { + +/** + * Class to encapsulate all the possible types of protocol errors that may + * occur in various protocol systems. This provides a sort of generic + * wrapper around the shitty UNIX E_ error codes that lets a common code + * base of error handling to be used for various types of protocols, i.e. + * pipes etc. + * + */ +class TProtocolException : public apache::thrift::TLibraryException { + public: + + /** + * Error codes for the various types of exceptions. + */ + enum TProtocolExceptionType + { UNKNOWN = 0 + , INVALID_DATA = 1 + , NEGATIVE_SIZE = 2 + , SIZE_LIMIT = 3 + , BAD_VERSION = 4 + , NOT_IMPLEMENTED = 5 + }; + + TProtocolException() : + apache::thrift::TLibraryException(), + type_(UNKNOWN) {} + + TProtocolException(TProtocolExceptionType type) : + apache::thrift::TLibraryException(), + type_(type) {} + + TProtocolException(const std::string& message) : + apache::thrift::TLibraryException(message), + type_(UNKNOWN) {} + + TProtocolException(TProtocolExceptionType type, const std::string& message) : + apache::thrift::TLibraryException(message), + type_(type) {} + + virtual ~TProtocolException() throw() {} + + /** + * Returns an error code that provides information about the type of error + * that has occurred. + * + * @return Error code + */ + TProtocolExceptionType getType() { + return type_; + } + + virtual const char* what() const throw() { + if (message_.empty()) { + switch (type_) { + case UNKNOWN : return "TProtocolException: Unknown protocol exception"; + case INVALID_DATA : return "TProtocolException: Invalid data"; + case NEGATIVE_SIZE : return "TProtocolException: Negative size"; + case SIZE_LIMIT : return "TProtocolException: Exceeded size limit"; + case BAD_VERSION : return "TProtocolException: Invalid version"; + case NOT_IMPLEMENTED : return "TProtocolException: Not implemented"; + default : return "TProtocolException: (Invalid exception type)"; + } + } else { + return message_.c_str(); + } + } + + protected: + /** + * Error code + */ + TProtocolExceptionType type_; + +}; + +}}} // apache::thrift::protocol + +#endif // #ifndef _THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_ diff --git a/thrift/lib/cpp/protocol/TProtocolTap.h b/thrift/lib/cpp/protocol/TProtocolTap.h new file mode 100644 index 00000000..3772bff5 --- /dev/null +++ b/thrift/lib/cpp/protocol/TProtocolTap.h @@ -0,0 +1,188 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_PROTOCOL_TPROTOCOLTAP_H_ +#define _THRIFT_PROTOCOL_TPROTOCOLTAP_H_ 1 + +#include + +namespace apache { namespace thrift { namespace protocol { + +using apache::thrift::transport::TTransport; + +/** + * Puts a wiretap on a protocol object. Any reads to this class are passed + * through to an enclosed protocol object, but also mirrored as write to a + * second protocol object. + * + */ +class TProtocolTap : public TVirtualProtocol { + public: + TProtocolTap(boost::shared_ptr source, + boost::shared_ptr sink) + : TVirtualProtocol(source->getTransport()) + , source_(source) + , sink_(sink) + {} + + uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid) { + uint32_t rv = source_->readMessageBegin(name, messageType, seqid); + sink_->writeMessageBegin(name, messageType, seqid); + return rv; + } + + uint32_t readMessageEnd() { + uint32_t rv = source_->readMessageEnd(); + sink_->writeMessageEnd(); + return rv; + } + + uint32_t readStructBegin(std::string& name) { + uint32_t rv = source_->readStructBegin(name); + sink_->writeStructBegin(name.c_str()); + return rv; + } + + uint32_t readStructEnd() { + uint32_t rv = source_->readStructEnd(); + sink_->writeStructEnd(); + return rv; + } + + uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId) { + uint32_t rv = source_->readFieldBegin(name, fieldType, fieldId); + if (fieldType == T_STOP) { + sink_->writeFieldStop(); + } else { + sink_->writeFieldBegin(name.c_str(), fieldType, fieldId); + } + return rv; + } + + + uint32_t readFieldEnd() { + uint32_t rv = source_->readFieldEnd(); + sink_->writeFieldEnd(); + return rv; + } + + uint32_t readMapBegin(TType& keyType, + TType& valType, + uint32_t& size) { + uint32_t rv = source_->readMapBegin(keyType, valType, size); + sink_->writeMapBegin(keyType, valType, size); + return rv; + } + + + uint32_t readMapEnd() { + uint32_t rv = source_->readMapEnd(); + sink_->writeMapEnd(); + return rv; + } + + uint32_t readListBegin(TType& elemType, uint32_t& size) { + uint32_t rv = source_->readListBegin(elemType, size); + sink_->writeListBegin(elemType, size); + return rv; + } + + + uint32_t readListEnd() { + uint32_t rv = source_->readListEnd(); + sink_->writeListEnd(); + return rv; + } + + uint32_t readSetBegin(TType& elemType, uint32_t& size) { + uint32_t rv = source_->readSetBegin(elemType, size); + sink_->writeSetBegin(elemType, size); + return rv; + } + + + uint32_t readSetEnd() { + uint32_t rv = source_->readSetEnd(); + sink_->writeSetEnd(); + return rv; + } + + uint32_t readBool(bool& value) { + uint32_t rv = source_->readBool(value); + sink_->writeBool(value); + return rv; + } + + // Provide the default readBool() implementation for std::vector + using TVirtualProtocol::readBool; + + uint32_t readByte(int8_t& byte) { + uint32_t rv = source_->readByte(byte); + sink_->writeByte(byte); + return rv; + } + + uint32_t readI16(int16_t& i16) { + uint32_t rv = source_->readI16(i16); + sink_->writeI16(i16); + return rv; + } + + uint32_t readI32(int32_t& i32) { + uint32_t rv = source_->readI32(i32); + sink_->writeI32(i32); + return rv; + } + + uint32_t readI64(int64_t& i64) { + uint32_t rv = source_->readI64(i64); + sink_->writeI64(i64); + return rv; + } + + uint32_t readDouble(double& dub) { + uint32_t rv = source_->readDouble(dub); + sink_->writeDouble(dub); + return rv; + } + + uint32_t readString(std::string& str) { + uint32_t rv = source_->readString(str); + sink_->writeString(str); + return rv; + } + + uint32_t readBinary(std::string& str) { + uint32_t rv = source_->readBinary(str); + sink_->writeBinary(str); + return rv; + } + + private: + boost::shared_ptr source_; + boost::shared_ptr sink_; +}; + +}}} // apache::thrift::protocol + +#endif // #define _THRIFT_PROTOCOL_TPROTOCOLTAP_H_ 1 diff --git a/thrift/lib/cpp/protocol/TProtocolTypes.h b/thrift/lib/cpp/protocol/TProtocolTypes.h new file mode 100644 index 00000000..ca22b545 --- /dev/null +++ b/thrift/lib/cpp/protocol/TProtocolTypes.h @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_PROTOCOL_TPROTOCOLTYPES_H_ +#define THRIFT_PROTOCOL_TPROTOCOLTYPES_H_ 1 + +namespace apache { namespace thrift { namespace protocol { + +enum PROTOCOL_TYPES { + T_BINARY_PROTOCOL = 0, + T_JSON_PROTOCOL = 1, + T_COMPACT_PROTOCOL = 2, +}; + +}}} // apache::thrift::protocol + +#endif // #define _THRIFT_PROTOCOL_TPROTOCOLTYPES_H_ 1 + diff --git a/thrift/lib/cpp/protocol/TSimpleJSONProtocol.h b/thrift/lib/cpp/protocol/TSimpleJSONProtocol.h new file mode 100644 index 00000000..4183d3af --- /dev/null +++ b/thrift/lib/cpp/protocol/TSimpleJSONProtocol.h @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_PROTOCOL_TSIMPLEJSONPROTOCOL_H_ +#define THRIFT_PROTOCOL_TSIMPLEJSONPROTOCOL_H_ 1 + +#include "TJSONProtocol.h" + +namespace apache { namespace thrift { namespace protocol { + + +/* + * TsimpleJSONProtocol overrides parts of the regular JSON serialization to + * comply with the Simple JSON format. + * Namely, spitting only field names without verbose field type output + */ + +class TSimpleJSONProtocol : public TVirtualProtocol{ + + public: + + TSimpleJSONProtocol(boost::shared_ptr ptrans); + + ~TSimpleJSONProtocol(); + + + public: + + uint32_t writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId); + + + uint32_t writeFieldEnd(); + + uint32_t writeMapBegin(const TType keyType, const TType valType, + const uint32_t size); + + uint32_t writeMapEnd(); + + uint32_t writeListBegin(const TType elemType, const uint32_t size); + + uint32_t writeSetBegin(const TType elemType, const uint32_t size); + + uint32_t writeBool(const bool value); +}; + +/** + * Constructs input and output protocol objects given transports. + */ +class TSimpleJSONProtocolFactory : public TProtocolFactory { + public: + TSimpleJSONProtocolFactory() {} + + virtual ~TSimpleJSONProtocolFactory() {} + + boost::shared_ptr getProtocol( + boost::shared_ptr trans) { + return boost::shared_ptr(new TSimpleJSONProtocol(trans)); + } +}; + +}}} // apache::thrift::protocol + +#endif // #define THRIFT_PROTOCOL_TJSONPROTOCOL_H_ 1 diff --git a/thrift/lib/cpp/protocol/TVirtualProtocol.h b/thrift/lib/cpp/protocol/TVirtualProtocol.h new file mode 100644 index 00000000..97298f00 --- /dev/null +++ b/thrift/lib/cpp/protocol/TVirtualProtocol.h @@ -0,0 +1,523 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_PROTOCOL_TVIRTUALPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TVIRTUALPROTOCOL_H_ 1 + +#include "thrift/lib/cpp/protocol/TProtocol.h" + +namespace apache { namespace thrift { namespace protocol { + +/** + * Helper class that provides default implementations of TProtocol methods. + * + * This class provides default implementations of the non-virtual TProtocol + * methods. It exists primarily so TVirtualProtocol can derive from it. It + * prevents TVirtualProtocol methods from causing infinite recursion if the + * non-virtual methods are not overridden by the TVirtualProtocol subclass. + * + * You probably don't want to use this class directly. Use TVirtualProtocol + * instead. + */ +class TProtocolDefaults : public TProtocol { + public: + void setVersion(const int8_t version) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support setVersion (yet)"); + } + + uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readMessageEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readStructBegin(std::string& name) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readStructEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readFieldEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readMapEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readListBegin(TType& elemType, uint32_t& size) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readListEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readSetBegin(TType& elemType, uint32_t& size) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readSetEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readBool(bool& value) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readBool(std::vector::reference value) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readByte(int8_t& byte) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readI16(int16_t& i16) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readI32(int32_t& i32) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readI64(int64_t& i64) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readDouble(double& dub) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readString(std::string& str) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readBinary(std::string& str) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeMessageEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + + uint32_t writeStructBegin(const char* name) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeStructEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeFieldEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeFieldStop() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeMapEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeListBegin(const TType elemType, const uint32_t size) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeListEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeSetBegin(const TType elemType, const uint32_t size) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeSetEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeBool(const bool value) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeByte(const int8_t byte) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeI16(const int16_t i16) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeI32(const int32_t i32) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeI64(const int64_t i64) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeDouble(const double dub) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeString(const std::string& str) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeBinary(const std::string& str) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t skip(TType type) { + return ::apache::thrift::protocol::skip(*this, type); + } + + protected: + TProtocolDefaults(const boost::shared_ptr& ptrans) + : TProtocol(ptrans) + {} + + TProtocolDefaults(transport::TTransport* ptrans) + : TProtocol(ptrans) + {} +}; + +/** + * Concrete TProtocol classes should inherit from TVirtualProtocol + * so they don't have to manually override virtual methods. + * + * @author David Reiss + */ +template +class TVirtualProtocol : public Super_ { + public: + + virtual void setVersion_virt(const int8_t version) { + return static_cast(this)->setVersion(version); + } + /** + * Writing functions. + */ + + virtual uint32_t writeMessageBegin_virt(const std::string& name, + const TMessageType messageType, + const int32_t seqid) { + return static_cast(this)->writeMessageBegin(name, messageType, + seqid); + } + + virtual uint32_t writeMessageEnd_virt() { + return static_cast(this)->writeMessageEnd(); + } + + + virtual uint32_t writeStructBegin_virt(const char* name) { + return static_cast(this)->writeStructBegin(name); + } + + virtual uint32_t writeStructEnd_virt() { + return static_cast(this)->writeStructEnd(); + } + + virtual uint32_t writeFieldBegin_virt(const char* name, + const TType fieldType, + const int16_t fieldId) { + return static_cast(this)->writeFieldBegin(name, fieldType, + fieldId); + } + + virtual uint32_t writeFieldEnd_virt() { + return static_cast(this)->writeFieldEnd(); + } + + virtual uint32_t writeFieldStop_virt() { + return static_cast(this)->writeFieldStop(); + } + + virtual uint32_t writeMapBegin_virt(const TType keyType, + const TType valType, + const uint32_t size) { + return static_cast(this)->writeMapBegin(keyType, valType, size); + } + + virtual uint32_t writeMapEnd_virt() { + return static_cast(this)->writeMapEnd(); + } + + virtual uint32_t writeListBegin_virt(const TType elemType, + const uint32_t size) { + return static_cast(this)->writeListBegin(elemType, size); + } + + virtual uint32_t writeListEnd_virt() { + return static_cast(this)->writeListEnd(); + } + + virtual uint32_t writeSetBegin_virt(const TType elemType, + const uint32_t size) { + return static_cast(this)->writeSetBegin(elemType, size); + } + + virtual uint32_t writeSetEnd_virt() { + return static_cast(this)->writeSetEnd(); + } + + virtual uint32_t writeBool_virt(const bool value) { + return static_cast(this)->writeBool(value); + } + + virtual uint32_t writeByte_virt(const int8_t byte) { + return static_cast(this)->writeByte(byte); + } + + virtual uint32_t writeI16_virt(const int16_t i16) { + return static_cast(this)->writeI16(i16); + } + + virtual uint32_t writeI32_virt(const int32_t i32) { + return static_cast(this)->writeI32(i32); + } + + virtual uint32_t writeI64_virt(const int64_t i64) { + return static_cast(this)->writeI64(i64); + } + + virtual uint32_t writeDouble_virt(const double dub) { + return static_cast(this)->writeDouble(dub); + } + + virtual uint32_t writeString_virt(const std::string& str) { + return static_cast(this)->writeString(str); + } + + virtual uint32_t writeBinary_virt(const std::string& str) { + return static_cast(this)->writeBinary(str); + } + + /** + * Reading functions + */ + + virtual uint32_t readMessageBegin_virt(std::string& name, + TMessageType& messageType, + int32_t& seqid) { + return static_cast(this)->readMessageBegin(name, messageType, + seqid); + } + + virtual uint32_t readMessageEnd_virt() { + return static_cast(this)->readMessageEnd(); + } + + virtual uint32_t readStructBegin_virt(std::string& name) { + return static_cast(this)->readStructBegin(name); + } + + virtual uint32_t readStructEnd_virt() { + return static_cast(this)->readStructEnd(); + } + + virtual uint32_t readFieldBegin_virt(std::string& name, + TType& fieldType, + int16_t& fieldId) { + return static_cast(this)->readFieldBegin(name, fieldType, + fieldId); + } + + virtual uint32_t readFieldEnd_virt() { + return static_cast(this)->readFieldEnd(); + } + + virtual uint32_t readMapBegin_virt(TType& keyType, + TType& valType, + uint32_t& size) { + return static_cast(this)->readMapBegin(keyType, valType, size); + } + + virtual uint32_t readMapEnd_virt() { + return static_cast(this)->readMapEnd(); + } + + virtual uint32_t readListBegin_virt(TType& elemType, + uint32_t& size) { + return static_cast(this)->readListBegin(elemType, size); + } + + virtual uint32_t readListEnd_virt() { + return static_cast(this)->readListEnd(); + } + + virtual uint32_t readSetBegin_virt(TType& elemType, + uint32_t& size) { + return static_cast(this)->readSetBegin(elemType, size); + } + + virtual uint32_t readSetEnd_virt() { + return static_cast(this)->readSetEnd(); + } + + virtual uint32_t readBool_virt(bool& value) { + return static_cast(this)->readBool(value); + } + + virtual uint32_t readBool_virt(std::vector::reference value) { + return static_cast(this)->readBool(value); + } + + virtual uint32_t readByte_virt(int8_t& byte) { + return static_cast(this)->readByte(byte); + } + + virtual uint32_t readI16_virt(int16_t& i16) { + return static_cast(this)->readI16(i16); + } + + virtual uint32_t readI32_virt(int32_t& i32) { + return static_cast(this)->readI32(i32); + } + + virtual uint32_t readI64_virt(int64_t& i64) { + return static_cast(this)->readI64(i64); + } + + virtual uint32_t readDouble_virt(double& dub) { + return static_cast(this)->readDouble(dub); + } + + virtual uint32_t readString_virt(std::string& str) { + return static_cast(this)->readString(str); + } + + virtual uint32_t readBinary_virt(std::string& str) { + return static_cast(this)->readBinary(str); + } + + virtual uint32_t skip_virt(TType type) { + return static_cast(this)->skip(type); + } + + /* + * Provide a default skip() implementation that uses non-virtual read + * methods. + * + * Note: subclasses that use TVirtualProtocol to derive from another protocol + * implementation (i.e., not TProtocolDefaults) should beware that this may + * override any non-default skip() implementation provided by the parent + * transport class. They may need to explicitly redefine skip() to call the + * correct parent implementation, if desired. + */ + uint32_t skip(TType type) { + Protocol_* const prot = static_cast(this); + return ::apache::thrift::protocol::skip(*prot, type); + } + + /* + * Provide a default readBool() implementation for use with + * std::vector, that behaves the same as reading into a normal bool. + * + * Subclasses can override this if desired, but there normally shouldn't + * be a need to. + */ + uint32_t readBool(std::vector::reference value) { + bool b = false; + uint32_t ret = static_cast(this)->readBool(b); + value = b; + return ret; + } + using Super_::readBool; // so we don't hide readBool(bool&) + + protected: + TVirtualProtocol(const boost::shared_ptr& ptrans) + : Super_(ptrans) + {} + + TVirtualProtocol(transport::TTransport* ptrans) + : Super_(ptrans) + {} +}; + +}}} // apache::thrift::protocol + +#endif // #define _THRIFT_PROTOCOL_TVIRTUALPROTOCOL_H_ 1 diff --git a/thrift/lib/cpp/protocol/neutronium/Decoder-inl.h b/thrift/lib/cpp/protocol/neutronium/Decoder-inl.h new file mode 100644 index 00000000..e38451c6 --- /dev/null +++ b/thrift/lib/cpp/protocol/neutronium/Decoder-inl.h @@ -0,0 +1,438 @@ +/** + * Copyright 2012 Facebook + * @author Tudor Bosman (tudorb@fb.com) + */ + +#ifndef THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_DECODER_INL_H_ +#define THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_DECODER_INL_H_ + +#ifndef THRIFT_INCLUDE_DECODER_INL +#error This file may only be included from Decoder.h +#endif + +#include "folly/GroupVarint.h" +#include "folly/Conv.h" + +namespace apache { +namespace thrift { +namespace protocol { +namespace neutronium { + +inline const char* CH(const uint8_t* p) { + return reinterpret_cast(p); +} +inline char* CH(uint8_t* p) { + return reinterpret_cast(p); +} + +template +inline auto CH(P p) -> std::pair { + return std::make_pair(CH(p.first), p.second); +} + +inline folly::StringPiece SP(std::pair p) { + return folly::StringPiece(CH(p.first), p.second); +} + +inline void Decoder::setRootType(int64_t rootType) { + CHECK(stack_.empty()); + rootType_ = rootType; +} + +inline void Decoder::readStructBegin() { + push(reflection::TYPE_STRUCT, nextType(), 0); +} + +inline void Decoder::readStructEnd() { + DCHECK_EQ(top().state, IN_STRUCT); + // The last readFieldBegin returned T_STOP and so didn't change the state + // to IN_FIELD + pop(); +} + +inline int64_t Decoder::nextType() { + int64_t type; + if (!stack_.empty()) { + auto& s = top(); + s.nextValue(); + type = s.type.typeVal; + } else { + type = rootType_; + } + return type; +} + +inline void Decoder::readMapBegin(TType& keyType, TType& valType, + uint32_t& size) { + size = peekElementCount(); + push(reflection::TYPE_MAP, nextType(), size); + keyType = top().list.mapKeyType.ttype(); + valType = top().list.valueType.ttype(); + size = top().list.remaining; +} + +inline void Decoder::readMapEnd() { + DCHECK_EQ(top().state, IN_MAP_VALUE); + DCHECK_EQ(top().list.remaining, 0); + pop(); +} + +inline void Decoder::readListBegin(TType& elemType, uint32_t& size) { + size = peekElementCount(); + push(reflection::TYPE_LIST, nextType(), size); + elemType = top().list.valueType.ttype(); + size = top().list.remaining; +} + +inline void Decoder::readListEnd() { + DCHECK_EQ(top().state, IN_LIST_VALUE); + DCHECK_EQ(top().list.remaining, 0); + pop(); +} + +inline void Decoder::readSetBegin(TType& elemType, uint32_t& size) { + size = peekElementCount(); + push(reflection::TYPE_SET, nextType(), size); + elemType = top().list.valueType.ttype(); + size = top().list.remaining; +} + +inline void Decoder::readSetEnd() { + DCHECK_EQ(top().state, IN_SET_VALUE); + DCHECK_EQ(top().list.remaining, 0); + pop(); +} + +inline void Decoder::push(reflection::Type rtype, int64_t type, uint32_t size) { + if (rtype != reflection::getType(type)) { + throw TProtocolException(folly::to( + "Invalid type ", reflection::getType(type), " expected ", rtype)); + } + const DataType* dt = &(schema_->map().at(type)); + stack_.emplace_back(schema_, type, dt, size); + read(); +} + +inline Decoder::TypeInfo::TypeInfo(const Schema* schema, int64_t t) + : typeVal(t), + length(kVariableLength), + dataType(nullptr), + terminator('\0') { + if (!reflection::isBaseType(type())) { + dataType = &(schema->map().at(t)); + length = dataType->fixedSize; + } +} + +inline Decoder::TypeInfo::TypeInfo(int64_t t) + : typeVal(t), + length(kVariableLength), + dataType(nullptr), + terminator('\0') { + DCHECK(reflection::isBaseType(type())); +} + +template +inline void Decoder::DecoderState::setStateList(T& ts) { + if (UNLIKELY(++ts.index == ts.count)) { + throw TProtocolException("type mismatch"); + } +} + +inline void Decoder::DecoderState::nextList() { + switch (state) { + case IN_MAP_KEY: + state = IN_MAP_VALUE; + type = list.valueType; + break; // don't advance to next + case IN_MAP_VALUE: + state = IN_MAP_KEY; + type = list.mapKeyType; + DCHECK_NE(list.remaining, 0); + --list.remaining; + break; + case IN_LIST_VALUE: + case IN_SET_VALUE: + type = list.valueType; + DCHECK_NE(list.remaining, 0); + --list.remaining; + break; + default: + LOG(FATAL) << "Invalid state " << state; + } + // Advance to next element + + switch (type.typeVal) { + case reflection::TYPE_BOOL: + setStateList(bools); + break; + case reflection::TYPE_BYTE: + setStateList(bytes); + break; + case reflection::TYPE_I16: // fallthrough + case reflection::TYPE_I32: + setStateList(ints); + break; + case reflection::TYPE_I64: // fallthrough + case reflection::TYPE_DOUBLE: + setStateList(int64s); + break; + case reflection::TYPE_STRING: // fallthrough + default: + setStateList(strings); + } +} + +template +bool Decoder::DecoderState::setStateStruct( + TS& ts, + const TV& tv, + FieldState nextState) { + if (++ts.index == ts.count) { + str.fieldState = nextState; + return false; + } else { + auto& p = tv[ts.index]; + str.tag = p.first; + type = p.second; + return true; + } +} + +inline bool Decoder::DecoderState::nextStruct() { + switch (str.fieldState) { + case FS_START: + str.fieldState = FS_INT; + ints.index = -1; + // fallthrough + case FS_INT: + if (setStateStruct(ints, str.intTags, FS_INT64)) { + break; + } + // fallthrough + case FS_INT64: + if (setStateStruct(int64s, str.int64Tags, FS_BOOL)) { + break; + } + // fallthrough + case FS_BOOL: + if (setStateStruct(bools, str.boolTags, FS_STRICT_ENUM)) { + break; + } + case FS_STRICT_ENUM: + if (setStateStruct(strictEnums, str.strictEnumTags, FS_BYTE)) { + break; + } + // fallthrough + case FS_BYTE: + if (setStateStruct(bytes, str.byteTags, FS_INTERNED_STRING)) { + break; + } + // fallthrough + case FS_INTERNED_STRING: + if (setStateStruct(internedStrings, str.internedStringTags, FS_STRING)) { + break; + } + case FS_STRING: + if (setStateStruct(strings, str.stringTags, FS_END)) { + break; + } + // fallthrough + case FS_END: + return false; + } + + return true; +} + +inline bool Decoder::DecoderState::nextField() { + DCHECK_EQ(state, IN_STRUCT); + if (!nextStruct()) { + return false; + } + state = IN_FIELD; + setLength(); + return true; +} + +inline void Decoder::DecoderState::nextValue() { + DCHECK_NE(state, IN_STRUCT); + if (state != IN_FIELD) { + nextList(); + setLength(); + } +} + +inline void Decoder::DecoderState::setLength() { + if (type.type() == reflection::TYPE_STRING && + type.length == kVariableLength) { + // Variable size, read length + if (++vars.index == vars.count) { + throw TProtocolException("too many vars"); + } + type.length = vars.values[vars.index]; + } +} + +inline uint32_t Decoder::peekElementCount() { + uint32_t len; + cursor_.gather(folly::GroupVarint32::maxSize(1)); + folly::GroupVarint32Decoder decoder(SP(cursor_.peek())); + uint32_t count; + if (!decoder.next(&count)) { + throw TProtocolException("underflow"); + } + return count; +} + +inline void Decoder::readFieldBegin(TType& fieldType, int16_t& fieldId) { + auto& s = top(); + if (s.nextField()) { + fieldType = s.type.ttype(); + fieldId = s.str.tag; + } else { + fieldType = T_STOP; + fieldId = 0; + } +} + +inline void Decoder::readFieldEnd() { + auto& s = top(); + CHECK_EQ(s.state, IN_FIELD); + s.state = IN_STRUCT; +} + +inline void Decoder::readBool(bool& value) { + auto& s = top(); + s.nextValue(); + if (UNLIKELY(s.type.typeVal != reflection::TYPE_BOOL)) { + throw TProtocolException("invalid type"); + } + value = testBit(s.bools.values, s.boolStartBit + s.bools.index); +} + +inline void Decoder::readByte(int8_t& value) { + auto& s = top(); + s.nextValue(); + if (UNLIKELY(s.type.typeVal != reflection::TYPE_BYTE)) { + throw TProtocolException("invalid type"); + } + value = s.bytes.values[s.bytes.index]; +} + +inline void Decoder::readI16(int16_t& value) { + auto& s = top(); + s.nextValue(); + if (UNLIKELY(s.type.typeVal != reflection::TYPE_I16)) { + throw TProtocolException("invalid type"); + } + value = s.ints.values[s.ints.index]; +} + +inline void Decoder::readI32(int32_t& value) { + auto& s = top(); + s.nextValue(); + // Strict enums only occur in structs + // TODO(tudorb): Relax? + if (s.state == IN_FIELD && s.str.fieldState == DecoderState::FS_STRICT_ENUM) { + value = s.strictEnums.values[s.strictEnums.index]; + } else if (UNLIKELY(s.type.typeVal != reflection::TYPE_I32)) { + throw TProtocolException("invalid type"); + } else { + value = s.ints.values[s.ints.index]; + } +} + +inline void Decoder::readI64(int64_t& value) { + auto& s = top(); + s.nextValue(); + if (UNLIKELY(s.type.typeVal != reflection::TYPE_I64)) { + throw TProtocolException("invalid type"); + } + value = s.int64s.values[s.int64s.index]; +} + +inline void Decoder::readDouble(double& value) { + auto& s = top(); + s.nextValue(); + if (UNLIKELY(s.type.typeVal != reflection::TYPE_DOUBLE)) { + throw TProtocolException("invalid type"); + } + int64_t i64 = s.int64s.values[s.int64s.index]; + value = bitwise_cast(i64); +} + +inline bool Decoder::beginReadString() { + auto& s = top(); + s.nextValue(); + if (UNLIKELY(s.type.typeVal != reflection::TYPE_STRING)) { + throw TProtocolException("invalid type"); + } + // Interned strings only occur in structs, + // TODO(tudorb): Relax? + return (s.state == IN_FIELD && + s.str.fieldState == DecoderState::FS_INTERNED_STRING); +} + +template +inline void Decoder::readString(StrType& str) { + if (beginReadString()) { + // interned + auto& s = top(); + auto sp = s.internedStrings.values[s.internedStrings.index]; + str.assign(sp.data(), sp.size()); + } else { + // not interned + str.clear(); + int64_t len = top().type.length; + DCHECK(len >= 0 || len == kTerminated); + if (len == kTerminated) { + char terminator = top().type.terminator; + const uint8_t* term = nullptr; + while (!term) { + auto p = cursor_.peek(); + if (p.second == 0) throw TLibraryException("eof"); + term = static_cast( + memchr(p.first, terminator, p.second)); + size_t n = term ? term - p.first : p.second; + str.append(reinterpret_cast(p.first), n); + cursor_.skip(n); + top().bytesRead += n; + } + } else { + while (len) { + auto p = cursor_.peek(); + if (p.second == 0) throw TLibraryException("eof"); + auto n = std::min(len, static_cast(p.second)); + str.append(reinterpret_cast(p.first), n); + cursor_.skip(n); + top().bytesRead += n; + len -= n; + } + } + } +} + +inline Decoder::DecoderState& Decoder::top() { + DCHECK(!stack_.empty()); + return stack_.back(); +} + +inline void Decoder::pop() { + DCHECK(!stack_.empty()); + size_t bytesRead = stack_.back().bytesRead; + stack_.pop_back(); + if (stack_.empty()) { + bytesRead_ = bytesRead; + } else { + top().bytesRead += bytesRead; + } +} + +} // namespace neutronium +} // namespace protocol +} // namespace thrift +} // namespace apache + +#endif /* THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_DECODER_INL_H_ */ + diff --git a/thrift/lib/cpp/protocol/neutronium/Decoder.h b/thrift/lib/cpp/protocol/neutronium/Decoder.h new file mode 100644 index 00000000..de0edff6 --- /dev/null +++ b/thrift/lib/cpp/protocol/neutronium/Decoder.h @@ -0,0 +1,239 @@ +/** + * Copyright 2012 Facebook + * @author Tudor Bosman (tudorb@fb.com) + */ + +#ifndef THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_DECODER_H_ +#define THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_DECODER_H_ + +#include "thrift/lib/cpp/protocol/neutronium/Utils.h" +#include "thrift/lib/cpp/protocol/neutronium/InternTable.h" +#include "thrift/lib/cpp/protocol/neutronium/Schema.h" +#include "thrift/lib/cpp/protocol/TProtocol.h" +#include "folly/FBString.h" +#include "folly/Range.h" +#include "folly/small_vector.h" +#include "folly/experimental/io/Cursor.h" + +namespace apache { +namespace thrift { +namespace protocol { +namespace neutronium { + +class Decoder { + public: + explicit Decoder(const Schema* schema, const InternTable* internTable, + folly::IOBuf* buf); + void setRootType(int64_t type); + + void readStructBegin(); + void readStructEnd(); + + void readFieldBegin(TType& fieldType, int16_t& fieldId); + void readFieldEnd(); + + void readMapBegin(TType& keyType, TType& valType, uint32_t& size); + void readMapEnd(); + + void readListBegin(TType& elemType, uint32_t& size); + void readListEnd(); + + void readSetBegin(TType& elemType, uint32_t& size); + void readSetEnd(); + + void readBool(bool& value); + void readByte(int8_t& value); + void readI16(int16_t& value); + void readI32(int32_t& i32); + void readI64(int64_t& i64); + void readDouble(double& dub); + + template + void readString(StrType& str); + + void readBinary(std::string& str) { + readString(str); + } + + size_t bytesRead() const { + return bytesRead_; + } + + private: + bool beginReadString(); // returns true if interned + + const Schema* schema_; + const InternTable* internTable_; + folly::io::RWPrivateCursor cursor_; + int64_t rootType_; + + enum State { + IN_STRUCT, + IN_FIELD, + IN_MAP_KEY, + IN_MAP_VALUE, + IN_LIST_VALUE, + IN_SET_VALUE, + }; + + static const int64_t kVariableLength = -1; + static const int64_t kTerminated = -2; + + struct TypeInfo { + TypeInfo() + : typeVal(reflection::TYPE_VOID), + length(kVariableLength), + dataType(nullptr), + terminator('\0') { } + TypeInfo(const Schema* schema, int64_t t); + /* implicit */ TypeInfo(int64_t t); + reflection::Type type() const { + return reflection::getType(typeVal); + } + TType ttype() const { + return toTType(type()); + } + + int64_t typeVal; + int64_t length; + const DataType* dataType; + char terminator; + }; + + static const size_t kIntInline = 8; + static const size_t kInt64Inline = 8; + static const size_t kByteInline = 8; + static const size_t kFixedInt16Inline = 8; + static const size_t kFixedInt32Inline = 8; + static const size_t kFixedInt64Inline = 8; + static const size_t kBoolInline = 8; + static const size_t kStringInline = 8; + + struct DecoderState { + DecoderState(const Schema* schema, int64_t type, + const DataType* dataType, uint32_t size); + DecoderState(DecoderState&&) = default; + DecoderState& operator=(DecoderState&&) = default; + + enum FieldState { + FS_START, + FS_INT, + FS_INT64, + FS_BYTE, + FS_BOOL, + FS_STRICT_ENUM, + FS_INTERNED_STRING, + FS_STRING, + FS_END + }; + + const DataType* dataType; + State state; + + TypeInfo type; + + size_t bytesRead; + + struct TypeStateBase { + TypeStateBase() : count(0), index(-1) { } + size_t count; + ssize_t index; + }; + + template + struct TypeState : public TypeStateBase { + folly::small_vector values; + }; + + TypeState ints; // int16_t, int32_t + TypeState int64s; // int64_t, double + TypeState bytes; // int8_t + size_t boolStartBit; // offset of first bit from bools in bools.values + TypeState bools; // bool + TypeState strictEnums; + size_t totalStrictEnumBits; + TypeState vars; // variable-length + TypeState internedStrings; + TypeStateBase strings; // non-interned strings and user-defined types + + // TODO(tudorb): Make Struct and List into a union, but as these types are + // non-POD, the union would have a deleted copy/move constructor, + // copy/move assignment operator, and destructor, which meanns that + // DecoderState would have to have them user-defined in order to insert + // DecoderState in containers, bleh. + + typedef + folly::small_vector, 8> + TagVec; + + typedef + folly::small_vector, 8> + FullTagVec; + + struct Struct { + FieldState fieldState; + int16_t tag; + + TagVec intTags; + TagVec int64Tags; + TagVec byteTags; + TagVec boolTags; + FullTagVec strictEnumTags; + + FullTagVec stringTags; + FullTagVec internedStringTags; + + TagVec fixedInt16Tags; + TagVec fixedInt32Tags; + TagVec fixedInt64Tags; + } str; + struct List { + uint32_t remaining; + TypeInfo mapKeyType; + TypeInfo valueType; + } list; + + template + void setStateList(T& ts); + + template + bool setStateStruct(TS& ts, const TV& tv, FieldState nextState); + + bool nextField(); + void nextValue(); + void addType(TypeInfo& tinfo, + const StructField& field, int16_t tag, uint32_t count); + + private: + void setLength(); + void nextList(); + bool nextStruct(); + }; + + size_t bytesRead_; + static const size_t kStackInline = 8; + folly::small_vector stack_; + + void readBoolsAndStrictEnums(size_t skipBits); + void read(); + void push(reflection::Type expected, int64_t type, uint32_t size); + void pop(); + DecoderState& top(); + uint32_t peekElementCount(); + int64_t nextType(); + std::pair ensure(size_t n); +}; + + +} // namespace neutronium +} // namespace protocol +} // namespace thrift +} // namespace apache + +#define THRIFT_INCLUDE_DECODER_INL +#include "thrift/lib/cpp/protocol/neutronium/Decoder-inl.h" +#undef THRIFT_INCLUDE_DECODER_INL + + +#endif /* THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_DECODER_H_ */ + diff --git a/thrift/lib/cpp/protocol/neutronium/Encoder-inl.h b/thrift/lib/cpp/protocol/neutronium/Encoder-inl.h new file mode 100644 index 00000000..a70a8a9d --- /dev/null +++ b/thrift/lib/cpp/protocol/neutronium/Encoder-inl.h @@ -0,0 +1,357 @@ +/** + * Copyright 2012 Facebook + * @author Tudor Bosman (tudorb@fb.com) + */ + +#ifndef THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_ENCODER_INL_H_ +#define THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_ENCODER_INL_H_ + +#ifndef THRIFT_INCLUDE_ENCODER_INL +#error This file may only be included from Encoder.h +#endif + +#include "folly/Conv.h" + +namespace apache { +namespace thrift { +namespace protocol { +namespace neutronium { + +inline void Encoder::writeFieldBegin(const char* name, TType fieldType, + int16_t fieldId) { + auto& s = top(); + DCHECK(s.state == IN_STRUCT); + s.field = s.dataType->fields.at(fieldId); + s.tag = fieldId; + s.state = IN_FIELD; +} + +inline void Encoder::writeFieldEnd() { + auto& s = top(); + DCHECK(s.state == DONE_FIELD); + s.tag = 0; + s.field.clear(); + s.state = IN_STRUCT; +} + +inline void Encoder::writeFieldStop() { + auto& s = top(); + DCHECK(s.state == IN_STRUCT); + flush(); +} + +inline bool Encoder::EncoderState::inDataState() const { + return (state == IN_FIELD || + state == IN_MAP_KEY || + state == IN_MAP_VALUE || + state == IN_LIST_VALUE || + state == IN_SET_VALUE); +} + +inline bool Encoder::EncoderState::inFlushableState() const { + return (state == IN_STRUCT || + state == IN_MAP_KEY || + state == IN_LIST_VALUE || + state == IN_SET_VALUE); +} + +inline void Encoder::EncoderState::dataWritten() { + switch (state) { + case IN_FIELD: + state = DONE_FIELD; + break; + case IN_MAP_KEY: + state = IN_MAP_VALUE; + field.type = dataType->valueType; + break; + case IN_MAP_VALUE: + state = IN_MAP_KEY; + field.type = dataType->mapKeyType; + break; + case IN_LIST_VALUE: + break; + case IN_SET_VALUE: + break; + default: + LOG(FATAL) << "Invalid state " << state; + } +} + +template +inline size_t findIndex(const C& container, T val) { + auto pos = container.find(val); + if (pos == container.end()) throw std::out_of_range("not found"); + return pos - container.begin(); +} + +inline void Encoder::EncoderState::markFieldSet() { + // only useful for structs + if (state != IN_FIELD || field.isRequired) return; + optionalSet[findIndex(dataType->optionalFields, tag)] = true; +} + +template +inline void Encoder::EncoderState::checkType() const { + throw TLibraryException(folly::to("Invalid type ", field.type)); +} + +template +inline void Encoder::EncoderState::checkType(reflection::Type t, + Args... tail) const { + if (t == reflection::getType(field.type)) return; + checkType(tail...); +} + +template +inline void Encoder::EncoderState::appendToOutput(const Vec& vec) { + size_t bytes = vec.size() * sizeof(typename Vec::value_type::second_type); + for (auto& p : vec) { + appender.writeBE(p.second); + } + bytesWritten += bytes; +} + +inline void Encoder::writeMapBegin(TType keyType, TType valType, + uint32_t size) { + push(reflection::TYPE_MAP, topType(), size); +} + +inline void Encoder::writeMapEnd() { + DCHECK_EQ(top().state, IN_MAP_KEY); + flush(); + pop(); +} + +inline void Encoder::writeListBegin(TType elemType, uint32_t size) { + push(reflection::TYPE_LIST, topType(), size); +} + +inline void Encoder::writeListEnd() { + DCHECK_EQ(top().state, IN_LIST_VALUE); + flush(); + pop(); +} + +inline void Encoder::writeSetBegin(TType elemType, uint32_t size) { + push(reflection::TYPE_SET, topType(), size); +} + +inline void Encoder::writeSetEnd() { + DCHECK_EQ(top().state, IN_SET_VALUE); + flush(); + pop(); +} + +inline void Encoder::writeStructBegin(const char* name) { + push(reflection::TYPE_STRUCT, topType(), 0); +} + +inline void Encoder::writeStructEnd() { + DCHECK_EQ(top().state, FLUSHED); + // writeFieldStop() called flush() + pop(); +} + +inline void Encoder::push(reflection::Type rtype, int64_t type, + uint32_t size) { + DCHECK(stack_.empty() || top().inDataState()); + if (reflection::getType(type) != rtype) { + throw TLibraryException(folly::to( + "Invalid aggregate type ", reflection::getType(type), + " expected ", rtype)); + } + + const DataType* dt = &(schema_->map().at(type)); + stack_.emplace_back(new EncoderState(type, dt, size)); +} + +inline void Encoder::pop() { + auto& s = top(); + DCHECK_EQ(s.state, FLUSHED); + int64_t size = s.dataType->fixedSize; + DCHECK(size == -1 || size == s.buf->computeChainDataLength()); + size_t bytesWritten = s.bytesWritten; + DCHECK_EQ(bytesWritten, s.buf->computeChainDataLength()); + auto buf = std::move(s.buf); + stack_.pop_back(); + if (stack_.empty()) { + outputBuf_->prependChain(std::move(buf)); + bytesWritten_ = bytesWritten; + } else { + writeData(std::move(buf)); + top().bytesWritten += bytesWritten; + } +} + +inline Encoder::EncoderState& Encoder::top() { + DCHECK(!stack_.empty()); + DCHECK(stack_.back()); + return *stack_.back(); +} + +inline const Encoder::EncoderState& Encoder::top() const { + DCHECK(!stack_.empty()); + DCHECK(stack_.back()); + return *stack_.back(); +} + +inline int64_t Encoder::topType() const { + return (stack_.empty() ? rootType_ : top().field.type); +} + +inline void Encoder::writeBool(bool v) { + auto& s = top(); + DCHECK(s.inDataState()); + s.checkType(reflection::TYPE_BOOL); + s.markFieldSet(); + s.bools.emplace_back(s.tag, v); + s.dataWritten(); +} + +inline void Encoder::writeByte(int8_t v) { + auto& s = top(); + DCHECK(s.inDataState()); + s.markFieldSet(); + s.checkType(reflection::TYPE_BYTE); + s.bytes.emplace_back(s.tag, v); + s.dataWritten(); +} + +inline void Encoder::writeI16(int16_t v) { + auto& s = top(); + DCHECK(s.inDataState()); + s.checkType(reflection::TYPE_I16); + s.markFieldSet(); + if (s.field.isFixed) { + s.fixedInt16s.emplace_back(s.tag, v); + } else { + s.varInts.emplace_back(s.tag, v); + } + s.dataWritten(); +} + +inline void Encoder::writeI32(int32_t v) { + auto& s = top(); + DCHECK(s.inDataState()); + s.checkType(reflection::TYPE_I32, reflection::TYPE_ENUM); + s.markFieldSet(); + if (reflection::getType(s.field.type) == reflection::TYPE_ENUM && + s.field.isStrictEnum) { + auto& dt = schema_->map().at(s.field.type); + uint8_t nbits = dt.enumBits(); + uint32_t value = findIndex(dt.enumValues, v); + s.strictEnums.push_back({s.tag, {nbits, value}}); + s.totalStrictEnumBits += nbits; + } else { + if (s.field.isFixed) { + s.fixedInt32s.emplace_back(s.tag, v); + } else { + s.varInts.emplace_back(s.tag, v); + } + } + s.dataWritten(); +} + +inline void Encoder::writeI64(int64_t v) { + innerWriteI64(v, reflection::TYPE_I64); +} + +inline void Encoder::writeDouble(double v) { + innerWriteI64(bitwise_cast(v), reflection::TYPE_DOUBLE); +} + +inline void Encoder::innerWriteI64(int64_t v, reflection::Type expected) { + auto& s = top(); + DCHECK(s.inDataState()); + s.markFieldSet(); + s.checkType(expected); + if (s.field.isFixed) { + s.fixedInt64s.emplace_back(s.tag, v); + } else { + s.varInt64s.emplace_back(s.tag, v); + } + s.dataWritten(); +} + +namespace { +std::unique_ptr copyBufferToSize( + const void* data, size_t dataSize, size_t outSize, char pad) { + auto buf = folly::IOBuf::create(outSize); + dataSize = std::min(dataSize, outSize); + memcpy(buf->writableData(), data, dataSize); + if (dataSize < outSize) { + memset(buf->writableData() + dataSize, pad, outSize - dataSize); + } + buf->append(outSize); + return buf; +} + +std::unique_ptr copyBufferAndTerminate( + const void* data, size_t dataSize, char terminator) { + if (memchr(data, terminator, dataSize)) { + throw TProtocolException("terminator found in terminated string"); + } + // 1 byte of tailroom for the terminator + auto buf = folly::IOBuf::copyBuffer(data, dataSize, 0, 1); + buf->writableTail()[0] = terminator; + buf->append(1); + return buf; +} + +} // namespace + + +// TODO(tudorb): Zero-copy version +inline void Encoder::writeBytes(folly::StringPiece data) { + auto& s = top(); + DCHECK(s.inDataState()); + s.checkType(reflection::TYPE_STRING); + s.markFieldSet(); + if (s.field.isInterned) { + CHECK(internTable_); + s.varInternIds.emplace_back(s.tag, internTable_->add(data)); + } else if (s.field.isFixed) { + s.strings.emplace_back( + s.tag, copyBufferToSize(data.data(), data.size(), + s.field.fixedStringSize, s.field.pad)); + s.bytesWritten += s.field.fixedStringSize; + } else if (s.field.isTerminated) { + s.strings.emplace_back( + s.tag, copyBufferAndTerminate(data.data(), data.size(), + s.field.terminator)); + s.bytesWritten += data.size() + 1; + } else { + s.varLengths.emplace_back(s.tag, data.size()); + s.strings.emplace_back( + s.tag, folly::IOBuf::copyBuffer(data.data(), data.size())); + s.bytesWritten += data.size(); + } + s.dataWritten(); +} + +inline void Encoder::writeData(std::unique_ptr&& data) { + auto& s = top(); + DCHECK(s.inDataState()); + s.markFieldSet(); + s.strings.emplace_back(s.tag, std::move(data)); + s.dataWritten(); +} + +inline void Encoder::flush() { + auto& s = top(); + DCHECK(s.inFlushableState()); + if (s.state == IN_STRUCT) { + // TODO(tudorb): Check that all required fields were actually specified. + flushStruct(); + } + flushData(s.state == IN_STRUCT); + s.state = FLUSHED; +} + +} // namespace neutronium +} // namespace protocol +} // namespace thrift +} // namespace apache + +#endif /* THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_ENCODER_INL_H_ */ + diff --git a/thrift/lib/cpp/protocol/neutronium/Encoder.h b/thrift/lib/cpp/protocol/neutronium/Encoder.h new file mode 100644 index 00000000..be2a5590 --- /dev/null +++ b/thrift/lib/cpp/protocol/neutronium/Encoder.h @@ -0,0 +1,180 @@ +/** + * Copyright 2012 Facebook + * @author Tudor Bosman (tudorb@fb.com) + */ + +#ifndef THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_ENCODER_H_ +#define THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_ENCODER_H_ + +#include "thrift/lib/cpp/protocol/neutronium/Utils.h" +#include "thrift/lib/cpp/protocol/neutronium/Schema.h" +#include "thrift/lib/cpp/protocol/neutronium/InternTable.h" +#include "thrift/lib/cpp/protocol/TProtocol.h" +#include "folly/FBString.h" +#include "folly/Range.h" +#include "folly/experimental/io/IOBuf.h" +#include "folly/experimental/io/Cursor.h" + +namespace apache { +namespace thrift { +namespace protocol { +namespace neutronium { + +class Encoder { + public: + Encoder(const Schema* schema, InternTable* internTable, folly::IOBuf* buf); + void setRootType(int64_t rootType); + + // Similar interface to the writing part of TProtocol + void writeStructBegin(const char* name); + void writeStructEnd(); + + void writeFieldBegin(const char* name, TType fieldType, int16_t fieldId); + void writeFieldEnd(); + void writeFieldStop(); + + void writeMapBegin(TType keyType, TType valType, uint32_t size); + void writeMapEnd(); + void writeListBegin(TType elemType, uint32_t size); + void writeListEnd(); + void writeSetBegin(TType elemType, uint32_t size); + void writeSetEnd(); + + void writeBool(bool value); + void writeByte(int8_t byte); + void writeI16(int16_t i16); + void writeI32(int32_t i32); + void writeI64(int64_t i64); + void writeDouble(double dub); + + void writeBinary(const std::string& str) { + writeString(str); + } + template + void writeString(const StrType& str) { + writeBytes(str); + } + + /** + * Return number of bytes written. Non-zero only at root level, after + * the final writeStructEnd(). + */ + size_t bytesWritten() const { + return bytesWritten_; + } + + private: + void innerWriteI64(int64_t i64, reflection::Type expected); + + void writeData(std::unique_ptr&& data); + void markFieldSet(); + + void writeBytes(folly::StringPiece data); + + int32_t intern(folly::StringPiece data); + + const Schema* schema_; + int64_t rootType_; + size_t bytesWritten_; + + enum State { + IN_STRUCT, + IN_FIELD, + DONE_FIELD, + IN_MAP_KEY, + IN_MAP_VALUE, + IN_LIST_VALUE, + IN_SET_VALUE, + FLUSHED, + }; + + struct EncoderState { + EncoderState(int64_t type, const DataType* dt, uint32_t size); + + const DataType* dataType; + State state; + // TODO(tudorb): Check type_ + int16_t tag; + StructField field; + std::unique_ptr buf; + folly::io::Appender appender; + + std::vector> bools; // bool + struct StrictEnum { + uint8_t bits; + uint32_t value; + }; + // strict (bit-field) enums + std::vector> strictEnums; + size_t totalStrictEnumBits; + std::vector> bytes; // byte + + // Integer fields that were requested to be represented as fixed-length + std::vector> fixedInt16s; // i16 + std::vector> fixedInt32s; // i32 + std::vector> fixedInt64s; // i64, double + + // Integer fields that are represented as variable-length (GroupVarint) + std::vector> varInts; // i16, i32 + std::vector> varInt64s; // i64, double + + // Lengths of strings of unknown size, represented as GroupVarint + std::vector> varLengths; + + // Ids of interned strings, represented as GroupVarint + // (see InternTable.h) + std::vector> varInternIds; + + // Strings AND child elements (structs, lists, sets, maps) + // Note that only strings can be of unknown size (and thus use up one + // entry in varLengths, above); we always fully decode children and so + // we determine their size that way + std::vector>> strings; + + // Bitset (see Utils.h) of which optional fields are set; the index is + // the index in DataType::optionalFields. + std::vector optionalSet; + + size_t bytesWritten; + + bool inDataState() const; + void dataWritten(); + + bool inFlushableState() const; + void markFieldSet(); + + template void checkType() const; + template void checkType(reflection::Type t, + Args... tail) const; + + template + void appendToOutput(const Vec& vec); + }; + + std::vector> stack_; + void push(reflection::Type expected, int64_t type, uint32_t size); + void pop(); + int64_t topType() const; + EncoderState& top(); + const EncoderState& top() const; + + void flush(); + void flushBitValues(); + void flushStruct(); + void flushData(bool isStruct); + + InternTable* internTable_; + folly::IOBuf* outputBuf_; +}; + +} // namespace neutronium +} // namespace protocol +} // namespace thrift +} // namespace apache + + +#define THRIFT_INCLUDE_ENCODER_INL +#include "thrift/lib/cpp/protocol/neutronium/Encoder-inl.h" +#undef THRIFT_INCLUDE_ENCODER_INL + +#endif /* THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_ENCODER_H_ */ diff --git a/thrift/lib/cpp/protocol/neutronium/InternTable.h b/thrift/lib/cpp/protocol/neutronium/InternTable.h new file mode 100644 index 00000000..48ad0323 --- /dev/null +++ b/thrift/lib/cpp/protocol/neutronium/InternTable.h @@ -0,0 +1,102 @@ +/** + * Copyright 2012 Facebook + * @author Tudor Bosman (tudorb@fb.com) + */ + +#ifndef THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_INTERNTABLE_H_ +#define THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_INTERNTABLE_H_ + +#include +#include +#include +#include "folly/Range.h" +#include "folly/experimental/io/IOBuf.h" +#include "folly/experimental/io/Cursor.h" + +namespace apache { +namespace thrift { +namespace protocol { +namespace neutronium { + +/** + * Interned string table. + * + * Strings are stored in a chain of IOBufs, so serializing and deserializing + * the InternTable is fast and easy. + */ +class InternTable { + public: + InternTable(); + + /** + * Add a string to the table, returning the id. + */ + uint32_t add(folly::StringPiece str); + + /** + * Get a string from the table, by id; throws std::out_of_range if the + * id is invalid. + */ + folly::StringPiece get(uint32_t id) const { + return strings_.at(id); + } + + /** + * Serialize the table to a IOBuf chain. + * Note that part of the chain may be shared with the InternTable, so + * you must call unshare() on the returned buffers if you want to + * write to them. + */ + std::unique_ptr serialize(); + + /** + * Load the table from a IOBuf chain. + * Takes ownership of the IOBuf chain. + * InternTable will call unshare() appropriately before writing to + * buffers from the provided chain. + */ + void deserialize(std::unique_ptr&& data); + + /** + * Clear the table. + */ + void clear(); + + private: + // Performance optimization to reduce the number of calls to unshare() / + // unshareOne(), which folly::io::Cursor benchmarks have shown to be + // somewhat expensive. Given that we know that we only write to the tail + // of the IOBuf chain, we can often tell with certainty that the tail + // is private to us and so we don't need to check or call unshareOne(). + bool maybeShared_; + std::unique_ptr head_; + std::vector strings_; + + typedef + std::unordered_map + StringMap; + + // Only allocate writer if needed (when actually add()ing) + struct Writer { + template + /* implicit */ Writer(Args... args) : appender(args...) { } + folly::io::Appender appender; + StringMap map; + }; + std::unique_ptr writer_; + + // Not copiable; not movable + InternTable(const InternTable&) = delete; + InternTable(InternTable&&) = delete; + InternTable& operator=(const InternTable&) = delete; + InternTable& operator=(InternTable&&) = delete; + +}; + +} // namespace neutronium +} // namespace protocol +} // namespace thrift +} // namespace apache + +#endif /* THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_INTERNTABLE_H_ */ + diff --git a/thrift/lib/cpp/protocol/neutronium/README b/thrift/lib/cpp/protocol/neutronium/README new file mode 100644 index 00000000..b5ff365e --- /dev/null +++ b/thrift/lib/cpp/protocol/neutronium/README @@ -0,0 +1,67 @@ +Neutronium: a very dense encoding of Thrift objects + +Neutronium is a Thrift encoding format optimized for space at the expense of +speed. It achieves high efficiency in a few ways: + +1. It does not encode type and tag information. This is stored out of line in +a Schema object, which must be provided at both encoding and decoding time. +If encoding many Thrift objects, you can transmit / store the Schema only +once. The Schema (in thrift/lib/thrift/reflection.thrift) is itself a +Thrift object, and can be serialized / deserialized in the usual way. + +2. It encodes data very compactly. Bytes use one byte each; larger numbers +(i16, i32, i64, double) use variable-length encoding (GroupVarint). Booleans +use one bit each. We also encode one bit for every optional field that exists +in the structure definition (indicating whether the field is set or not). +Strings can be encoded in a variety of formats, see below. + +3. Aggregates (lists, maps, sets) are encoded efficiently -- they are encoded +like a structure with a variable number of fields. So list takes +advantage of GroupVarint encoding among consecutive values. + +4. Strings can be interned: when encoding multiple strings, we can detect +duplicates and store only an ID. This requires using an InternTable and +passing the same InternTable to the encoder and decoder (the InternTable +can be easily serialized and deserialized). + +Neutronium is backwards compatible as long as the schema is identical from +encoding to decoding, and the changes you made to the Thrift definition are +backwards compatible (that is, fields were added, removed, or renamed, but +field ids remained the same) + +Configuration: + +Neutronium can be configured by using field attributes in your Thrift +definition: + +struct Foo { + 1: i32 a (neutronium.fixed = 1), +} + +Attributes for number fields: + neutronium.fixed = 1 + Encode the number as a fixed-length value (i16 takes 2 bytes, i32 + takes 4 bytes, i64 takes 8 bytes) instead of using Varint encoding + +Attributes for string fields: + neutronium.fixed = + neutronium.pad = 'X' + Do not encode the string length, assume that all strings have length + . Strings longer than are truncated; strings + shorter than are padded with 'X' (default: the null byte, '\0'). + Use this when you expect that all / most strings have a fixed length. + + neutronium.terminator = 'X' + Do not encode the string length; store strings terminated with a + terminator ('\0' will likely be a popular choice). Encoding strings that + contain the terminator is an error. + + neutronium.intern = 1 + Intern strings; requires a non-NULL InternTable. + +Attributes for enum fields: + neutronium.strict = 1 + Encode the enum using as few bits as necessary to encode all possible + values; note that it becomes an error to encode an enum value that is not + specified in the Thrift definition. + diff --git a/thrift/lib/cpp/protocol/neutronium/Schema-inl.h b/thrift/lib/cpp/protocol/neutronium/Schema-inl.h new file mode 100644 index 00000000..8ba257e7 --- /dev/null +++ b/thrift/lib/cpp/protocol/neutronium/Schema-inl.h @@ -0,0 +1,32 @@ +/** + * Copyright 2012 Facebook + * @author Tudor Bosman (tudorb@fb.com) + */ + +#ifndef THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_SCHEMA_INL_H_ +#define THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_SCHEMA_INL_H_ + +#ifndef THRIFT_INCLUDE_SCHEMA_INL +#error This file may only be included from Schema.h +#endif + +namespace apache { +namespace thrift { +namespace protocol { +namespace neutronium { + +namespace detail { +extern const TType typeToTType[]; +} // namespace detail + +inline TType toTType(reflection::Type t) { + return detail::typeToTType[t]; +} + +} // namespace neutronium +} // namespace protocol +} // namespace thrift +} // namespace apache + +#endif /* THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_SCHEMA_INL_H_ */ + diff --git a/thrift/lib/cpp/protocol/neutronium/Schema.h b/thrift/lib/cpp/protocol/neutronium/Schema.h new file mode 100644 index 00000000..aea16993 --- /dev/null +++ b/thrift/lib/cpp/protocol/neutronium/Schema.h @@ -0,0 +1,111 @@ +/** + * Copyright 2012 Facebook + * @author Tudor Bosman (tudorb@fb.com) + */ + +#ifndef THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_SCHEMA_H_ +#define THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_SCHEMA_H_ + +#include +#include "boost/interprocess/containers/flat_map.hpp" +#include "boost/interprocess/containers/flat_set.hpp" +#include "thrift/lib/cpp/protocol/TProtocol.h" +#include "thrift/lib/cpp/Reflection.h" +#include "external/glog/logging.h" +#include "folly/Bits.h" +#include "thrift/lib/cpp/protocol/neutronium/Utils.h" + +namespace apache { +namespace thrift { +namespace protocol { +namespace neutronium { + +struct StructField { + StructField() + : type(0), + isRequired(false), + isInterned(false), + isFixed(false), + isTerminated(false), + fixedStringSize(0), + pad('\0'), + terminator('\0') { + } + + void setFlags(const reflection::DataType& rtype, + const reflection::StructField& rfield); + + void clear() { + *this = StructField(); + } + + // from reflection::StructField + int64_t type; + bool isRequired : 1; + bool isInterned : 1; + + // numbers: not varint-encoded + // strings: fixed size, fixedStringSize bytes, padded with 'pad' + bool isFixed : 1; + + // strings: terminated with 'terminator' which may not occur in the string + bool isTerminated : 1; + + // enums: strict (bitfield) encoding + bool isStrictEnum : 1; + + uint32_t fixedStringSize; + char pad; + char terminator; +}; + +struct DataType { + DataType() : mapKeyType(0), valueType(0), fixedSize(-1) { } + + // from reflection::StructField + boost::container::flat_map fields; + int64_t mapKeyType; + int64_t valueType; + // generated + int64_t fixedSize; // -1 = not fixed size + boost::container::flat_set optionalFields; + boost::container::flat_set enumValues; + + // Minimum number of bits needed to represent all enum values + // 0 if there's only one possible value -- there's nothing to encode! + size_t enumBits() const { + return enumValues.empty() ? 0 : folly::findLastSet(enumValues.size() - 1); + } +}; + +class Schema { + public: + typedef std::unordered_map Map; + Schema() { } + explicit Schema(const reflection::Schema& rschema); + void add(const reflection::Schema& rschema); + + const Map& map() const { return map_; } + + private: + int64_t fixedSizeForField(const StructField& field) const; + + int64_t add(const reflection::Schema& rschema, int64_t type); + void add(const reflection::Schema& rschema, int64_t type, + const reflection::DataType& dt); + Map map_; +}; + +TType toTType(reflection::Type t); + +} // namespace neutronium +} // namespace protocol +} // namespace thrift +} // namespace apache + +#define THRIFT_INCLUDE_SCHEMA_INL +#include "thrift/lib/cpp/protocol/neutronium/Schema-inl.h" +#undef THRIFT_INCLUDE_SCHEMA_INL + +#endif /* THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_SCHEMA_H_ */ + diff --git a/thrift/lib/cpp/protocol/neutronium/Utils.h b/thrift/lib/cpp/protocol/neutronium/Utils.h new file mode 100644 index 00000000..d1f6dc53 --- /dev/null +++ b/thrift/lib/cpp/protocol/neutronium/Utils.h @@ -0,0 +1,110 @@ +/** + * Copyright 2012 Facebook + * @author Tudor Bosman (tudorb@fb.com) + */ + +#ifndef THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_UTILS_H_ +#define THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_UTILS_H_ + +#include +#include +#include +#include + +namespace apache { +namespace thrift { +namespace protocol { +namespace neutronium { + +// Helper functions for using an array of uint8_t values as a bitset + +// byte index +constexpr inline size_t byteIndex(size_t bit) { + return bit / 8; +} + +// offset within byte +constexpr inline size_t bitOffset(size_t bit) { + return bit % 8; +} + +// number of bytes needed to represent bitCount bits (round up) +constexpr inline size_t byteCount(size_t bitCount) { + return bitCount / 8 + (bitCount % 8 != 0); +} + +// set bit +inline void setBit(uint8_t* p, size_t bit) { + p[byteIndex(bit)] |= (1 << bitOffset(bit)); +} + +inline void setBits(uint8_t* p, size_t bit, size_t count, uint32_t value) { + assert(value < (1 << count)); + while (count) { + size_t index = byteIndex(bit); + size_t offset = bitOffset(bit); + size_t countInThisByte = std::min(count, 8 - offset); + // Extract "countInThisByte" bits from value + uint8_t mask = (1 << countInThisByte) - 1; + uint8_t v = value & mask; + // Wipe out these bits, then set them to the new value + p[index] = (p[index] & ~(mask << offset)) | (v << offset); + + value >>= countInThisByte; + bit += countInThisByte; + count -= countInThisByte; + } +} + +inline uint32_t getBits(uint8_t* p, size_t bit, size_t count) { + uint32_t value = 0; + size_t shift = 0; + while (count) { + size_t index = byteIndex(bit); + size_t offset = bitOffset(bit); + size_t countInThisByte = std::min(count, 8 - offset); + uint8_t mask = (1 << countInThisByte) - 1; + uint8_t v = (p[index] & (mask << offset)) >> offset; + + value |= (v << shift); + shift += countInThisByte; + bit += countInThisByte; + count -= countInThisByte; + } + return value; +} + +// clear bit +inline void clearBit(uint8_t* p, size_t bit) { + p[byteIndex(bit)] &= ~(1 << bitOffset(bit)); +} + +// test bit +inline bool testBit(const uint8_t* p, size_t bit) { + return p[byteIndex(bit)] & (1 << bitOffset(bit)); +} + +// Overloads for vector, array, or anything else that has +// a working operator[] +template +inline void setBit(T& p, size_t bit) { + setBit(&p[0], bit); +} + +template +inline void clearBit(T& p, size_t bit) { + clearBit(&p[0], bit); +} + +template +inline bool testBit(const T& p, size_t bit) { + return testBit(&p[0], bit); +} + +} // namespace neutronium +} // namespace protocol +} // namespace thrift +} // namespace apache + +#endif /* THRIFT_LIB_CPP_PROTOCOL_NEUTRONIUM_UTILS_H_ */ + diff --git a/thrift/lib/cpp/protocol/neutronium/intern_table.thrift b/thrift/lib/cpp/protocol/neutronium/intern_table.thrift new file mode 100644 index 00000000..4951c990 --- /dev/null +++ b/thrift/lib/cpp/protocol/neutronium/intern_table.thrift @@ -0,0 +1,6 @@ +namespace cpp apache.thrift.protocol.neutronium + +struct InternTableSizes { + 1: required list sizes, +} + diff --git a/thrift/lib/cpp/protocol/neutronium/test/neutronium_test.thrift b/thrift/lib/cpp/protocol/neutronium/test/neutronium_test.thrift new file mode 100644 index 00000000..ec049953 --- /dev/null +++ b/thrift/lib/cpp/protocol/neutronium/test/neutronium_test.thrift @@ -0,0 +1,80 @@ +namespace cpp apache.thrift.protocol.neutronium.test + +cpp_include "folly/FBString.h" + +struct TestFixedSizeStruct1 { + 1: bool a, + 2: bool b, + 3: bool c, + 4: byte d, +} + +struct TestFixedSizeStruct2 { + 1: i32 a (neutronium.fixed = 1), + 2: i64 b (neutronium.fixed = 1), +} + +struct TestNotFixedSizeStruct2 { + 1: i32 a, + 2: i64 b, +} + +struct TestStruct1 { + 1: bool a, + 2: optional bool b, + 3: i32 c (neutronium.fixed = 1), + 4: optional i32 d, + 5: i64 e, + 6: optional i64 f, + 7: string g +} + +struct TestStruct2 { + 1: i32 a, + 2: TestStruct1 b, + 3: string c, + 4: list d, + 5: list e, + 6: map f, +} + +struct TestStringEncoding1 { + 1: i32 a, + 2: string b, + 3: string c (neutronium.intern = 1), + 4: string d1 (neutronium.fixed = 10, neutronium.pad = 'X'), + 5: string d2 (neutronium.fixed = 10, neutronium.pad = 'X'), + 6: string e (neutronium.terminator = 'X'), +} + +enum Foo { + HELLO = 1, // 0 + WORLD = 42, // 1 + MEOW = 23456, // 3 + GOODBYE = 12345 // 2 +} + +struct TestEnumEncoding1 { + 1: Foo a, + 2: Foo b (neutronium.strict = 1), + 3: bool c, + 4: i32 d +} + +struct TestEnumEncoding2 { + 1: bool a, + 2: Foo b (neutronium.strict = 1), + 4: optional Foo d (neutronium.strict = 1), + 5: Foo e (neutronium.strict = 1), +} + +struct BenchStruct1 { + 1: required i32 a, +} + +struct BenchStruct2 { + 1: optional i32 a, + 4: optional string b, + 5: optional list c +} + diff --git a/thrift/lib/cpp/server/TConnectionContext.h b/thrift/lib/cpp/server/TConnectionContext.h new file mode 100644 index 00000000..41da039c --- /dev/null +++ b/thrift/lib/cpp/server/TConnectionContext.h @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TCONNECTIONCONTEXT_H_ +#define THRIFT_TCONNECTIONCONTEXT_H_ 1 + +#include + +#include +#include "thrift/lib/cpp/protocol/TProtocol.h" + +namespace apache { namespace thrift { + +namespace transport { +class TSocketAddress; +} + +namespace protocol { +class TProtocol; +} + +namespace server { + +class TConnectionContext { + public: + TConnectionContext() + : userData_(NULL) + , destructor_(NULL) {} + + virtual ~TConnectionContext() { + cleanupUserData(); + } + + // expose getPeerAddress() defined in TRpcTransportContext + + virtual const transport::TSocketAddress* getPeerAddress() const = 0; + + virtual boost::shared_ptr getInputProtocol() const = 0; + + virtual boost::shared_ptr getOutputProtocol() const = 0; + /** + * Get the user data field. + */ + void* getUserData() const { + return userData_; + } + + /** + * Set the user data field. + * + * @param data The new value for the user data field. + * @param destructor A function pointer to invoke when the connection + * context is destroyed. It will be invoked with the + * contents of the user data field. + * + * @return Returns the old user data value. + */ + virtual void* setUserData(void* data, void (*destructor)(void*) = NULL) { + void* oldData = userData_; + userData_ = data; + destructor_ = destructor; + return oldData; + } + + protected: + void cleanupUserData() { + if (destructor_) { + destructor_(userData_); + destructor_ = NULL; + } + userData_ = NULL; + } + + private: + void* userData_; + void (*destructor_)(void*); +}; + +}}} // apache::thrift::server + +#endif // THRIFT_TCONNECTIONCONTEXT_H_ diff --git a/thrift/lib/cpp/server/TNonblockingServer.h b/thrift/lib/cpp/server/TNonblockingServer.h new file mode 100644 index 00000000..18dce011 --- /dev/null +++ b/thrift/lib/cpp/server/TNonblockingServer.h @@ -0,0 +1,1165 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_SERVER_TNONBLOCKINGSERVER_H_ +#define THRIFT_SERVER_TNONBLOCKINGSERVER_H_ 1 + +#include "thrift/lib/cpp/Thrift.h" +#include "thrift/lib/cpp/server/TServer.h" +#include "thrift/lib/cpp/transport/TBufferTransports.h" +#include "thrift/lib/cpp/transport/TSocket.h" +#include "thrift/lib/cpp/concurrency/ThreadManager.h" +#include "thrift/lib/cpp/concurrency/Thread.h" +#include "thrift/lib/cpp/concurrency/PosixThreadFactory.h" +#include "thrift/lib/cpp/concurrency/Mutex.h" +#include "thrift/lib/cpp/concurrency/ThreadLocal.h" +#include +#include +#include +#include +#include +#include +#include +#include // libevent +#include + + +namespace apache { namespace thrift { namespace server { + +using apache::thrift::transport::TMemoryBuffer; +using apache::thrift::transport::TSocket; +using apache::thrift::protocol::TProtocol; +using apache::thrift::concurrency::Runnable; +using apache::thrift::concurrency::ThreadManager; +using apache::thrift::concurrency::PosixThreadFactory; +using apache::thrift::concurrency::ThreadFactory; +using apache::thrift::concurrency::Thread; +using apache::thrift::concurrency::Mutex; +using apache::thrift::concurrency::Guard; + +/** + * This is a non-blocking server in C++ for high performance that + * operates a set of IO threads (by default only one). It assumes that + * all incoming requests are framed with a 4 byte length indicator and + * writes out responses using the same framing. + * + * It does not use the TServerTransport framework, but rather has socket + * operations hardcoded for use with select. + * + */ + + +/// Overload condition actions. +enum TOverloadAction { + T_OVERLOAD_NO_ACTION, ///< Don't handle overload */ + T_OVERLOAD_CLOSE_ON_ACCEPT, ///< Drop new connections immediately */ + T_OVERLOAD_DRAIN_TASK_QUEUE, ///< Drop some tasks from head of task queue */ + T_OVERLOAD_PAUSE_ACCEPTING ///< do not accept any new connections +}; + +class TNonblockingIOThread; +class TNonblockingServerObserver; + +class TNonblockingServer : public TServer { + private: + class TConnection; + + friend class TNonblockingIOThread; + private: + /// Listen backlog + static const int LISTEN_BACKLOG = 1024; + + /// Default limit on size of idle connection pool + static const int CONNECTION_STACK_LIMIT = -1; + + /// Default limit on frame size + static const int MAX_FRAME_SIZE = 256 * 1024 * 1024; + + /// Default limit on total number of connected sockets + static const int MAX_CONNECTIONS = INT_MAX; + + /// Default limit on connections in handler/task processing + static const int MAX_ACTIVE_PROCESSORS = INT_MAX; + + /// Default limit on the number of active requests on the server. + static const int MAX_ACTIVE_REQUESTS = INT_MAX; + + /// Default limit on memory usage + static const uint64_t MAX_MEMORY_USAGE_BYTES = ULONG_MAX; + + /// Default size of write buffer + static const int WRITE_BUFFER_DEFAULT_SIZE = 1024; + + /// Maximum size of read buffer allocated to idle connection (0 = unlimited) + static const int IDLE_READ_BUFFER_LIMIT = 8192; + + /// Maximum size of write buffer allocated to idle connection (0 = unlimited) + static const int IDLE_WRITE_BUFFER_LIMIT = 0; + + /// # of calls before resizing oversized buffers (0 = check only on close) + static const int RESIZE_BUFFER_EVERY_N = 0; + + /// # of IO threads to use by default + static const int DEFAULT_IO_THREADS = 1; + + /// File descriptor of an invalid socket + static const int INVALID_SOCKET = -1; + + /// # of IO threads this server will use + size_t numIOThreads_; + + /// Whether to set high scheduling priority for IO threads + bool useHighPriorityIOThreads_; + + /// Server socket file descriptor + int serverSocket_; + + /// Port server runs on + int port_; + + /// For processing via thread pool, may be NULL + boost::shared_ptr threadManager_; + + /// Is thread pool processing? + bool threadPoolProcessing_; + + // Factory to create the IO threads + boost::shared_ptr ioThreadFactory_; + + // Vector of IOThread objects that will handle our IO + std::vector > ioThreads_; + + // Index of next IO Thread to be used (for round-robin) + int nextIOThread_; + + // Synchronizes access to connection stack and similar data, such as + // numActiveRequests_. + Mutex connMutex_; + + /// Number of TConnection object we've created + size_t numTConnections_; + + /// Number of Connections processing or waiting to process + size_t numActiveProcessors_; + + /// Number of active/outstanding requests on the server. I.e., sum of requests + /// that are being processed, waiting to be processed and are waiting for the + /// reply to be sent out over the wire. + size_t numActiveRequests_; + + /// Limit for the number of requests that are being processed, waiting to be + /// processed, or are waiting for the reply to be sent out over the wire. + size_t maxActiveRequests_; + + /// listen backlog + int32_t listenBacklog_; + + /// Limit for how many TConnection objects to cache + /// 0 = infinite, -1 = none. + size_t connectionStackLimit_; + + /// Limit for number of connections processing or waiting to process + size_t maxActiveProcessors_; + + /// Limit for number of open connections + size_t maxConnections_; + + /// Limit for memory usage + uint64_t maxMemoryUsageBytes_; + + /// Limit for frame size + size_t maxFrameSize_; + + /// Time in milliseconds before an unperformed task expires (0 == infinite). + int64_t taskExpireTime_; + + /// Time in milliseconds to pause accepts for OVERLOAD_PAUSE_ACCEPTING + int pauseAcceptDuration_; + + /** + * Hysteresis for overload state. This is the fraction of the overload + * value that needs to be reached before the overload state is cleared; + * must be <= 1.0. + */ + double overloadHysteresis_; + + /// Action to take when we're overloaded. + TOverloadAction overloadAction_; + + /** + * The write buffer is initialized (and when idleWriteBufferLimit_ is checked + * and found to be exceeded, reinitialized) to this size. + */ + size_t writeBufferDefaultSize_; + + /** + * Max read buffer size for an idle TConnection. When we place an idle + * TConnection into connectionStack_ or on every resizeBufferEveryN_ calls, + * we will free the buffer (such that it will be reinitialized by the next + * received frame) if it has exceeded this limit. 0 disables this check. + */ + size_t idleReadBufferLimit_; + + /** + * Max write buffer size for an idle connection. When we place an idle + * TConnection into connectionStack_ or on every resizeBufferEveryN_ calls, + * we insure that its write buffer is <= to this size; otherwise we + * replace it with a new one of writeBufferDefaultSize_ bytes to insure that + * idle connections don't hog memory. 0 disables this check. + */ + size_t idleWriteBufferLimit_; + + /** + * Every N calls we check the buffer size limits on a connected TConnection. + * 0 disables (i.e. the checks are only done when a connection closes). + */ + int32_t resizeBufferEveryN_; + + /// Set if we are currently in an overloaded state. + bool overloaded_; + + /// Count of connections dropped since overload started + uint32_t nConnectionsDropped_; + + /// Count of connections dropped on overload since server started + uint64_t nTotalConnectionsDropped_; + + // Notification of various server events + boost::shared_ptr observer_; + + /** + * This is a stack of all the objects that have been created but that + * are NOT currently in use. When we close a connection, we place it on this + * stack so that the object can be reused later, rather than freeing the + * memory and reallocating a new object later. + */ + std::stack connectionStack_; + + /** + * This contains all existing TConnections, including the ones in the + * connectionStack_. + */ + std::tr1::unordered_set connectionSet_; + + /** + * Struct to help set socket options for + * TNonblockingServer::TConnection->TSocket sockets + */ + TSocket::Options sockOptHelper_; + + /** + * Thread-local data storage to track the current connection being processed. + */ + typedef concurrency::ThreadLocal< + TConnection, + concurrency::NoopThreadLocalManager > + ThreadLocalConnection; + ThreadLocalConnection currentConnection_; + + /** + * Called when server socket had something happen. We accept all waiting + * client connections on listen socket fd and assign TConnection objects + * to handle those requests. + * + * @param fd the listen socket. + * @param which the event flag that triggered the handler. + */ + void handleEvent(int fd, short which); + + void init(int port) { + serverSocket_ = -1; + numIOThreads_ = DEFAULT_IO_THREADS; + nextIOThread_ = 0; + useHighPriorityIOThreads_ = false; + port_ = port; + threadPoolProcessing_ = false; + numTConnections_ = 0; + numActiveProcessors_ = 0; + numActiveRequests_ = 0; + connectionStackLimit_ = CONNECTION_STACK_LIMIT; + maxActiveProcessors_ = MAX_ACTIVE_PROCESSORS; + maxActiveRequests_ = MAX_ACTIVE_REQUESTS; + maxConnections_ = MAX_CONNECTIONS; + maxMemoryUsageBytes_ = MAX_MEMORY_USAGE_BYTES; + maxFrameSize_ = MAX_FRAME_SIZE; + taskExpireTime_ = 0; + pauseAcceptDuration_ = 1; + overloadHysteresis_ = 0.8; + overloadAction_ = T_OVERLOAD_NO_ACTION; + writeBufferDefaultSize_ = WRITE_BUFFER_DEFAULT_SIZE; + idleReadBufferLimit_ = IDLE_READ_BUFFER_LIMIT; + idleWriteBufferLimit_ = IDLE_WRITE_BUFFER_LIMIT; + resizeBufferEveryN_ = RESIZE_BUFFER_EVERY_N; + overloaded_ = false; + nConnectionsDropped_ = 0; + nTotalConnectionsDropped_ = 0; + listenBacklog_ = LISTEN_BACKLOG; + + } + + size_t getWriteBufferBytesImpl() const; + size_t getReadBufferBytesImpl() const; + + protected: + + /// Increment the count of connections currently processing. + void incrementActiveProcessors() { + Guard g(connMutex_); + ++numActiveProcessors_; + } + + /// Decrement the count of connections currently processing. + void decrementActiveProcessors() { + Guard g(connMutex_); + if (numActiveProcessors_ > 0) { + --numActiveProcessors_; + } + } + + /// Increment the number of active requests on the server. + void incrementNumActiveRequests() { + Guard g(connMutex_); + ++numActiveRequests_; + } + + /// Decrement the number of active requests on the server. + void decrementNumActiveRequests() { + Guard g(connMutex_); + if (numActiveRequests_ > 0) { + --numActiveRequests_; + } + } + + public: + template + TNonblockingServer( + const boost::shared_ptr& processorFactory, + int port, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)) : + TServer(processorFactory) { + init(port); + } + + template + TNonblockingServer(const boost::shared_ptr& processor, + int port, + THRIFT_OVERLOAD_IF(Processor, TProcessor)) : + TServer(processor) { + init(port); + } + + template + TNonblockingServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& protocolFactory, + int port, + const boost::shared_ptr& threadManager = + boost::shared_ptr(), + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)) : + TServer(processorFactory) { + + init(port); + + setProtocolFactory(protocolFactory); + setThreadManager(threadManager); + } + + template + TNonblockingServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& duplexProtocolFactory, + int port, + const boost::shared_ptr& threadManager = + boost::shared_ptr(), + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)) : + TServer(processorFactory) { + + init(port); + + setDuplexProtocolFactory(duplexProtocolFactory); + setThreadManager(threadManager); + } + + template + TNonblockingServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& protocolFactory, + int port, + const boost::shared_ptr& threadManager = + boost::shared_ptr(), + THRIFT_OVERLOAD_IF(Processor, TProcessor)) : + TServer(processor) { + + init(port); + + setProtocolFactory(protocolFactory); + setThreadManager(threadManager); + } + + template + TNonblockingServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& duplexProtocolFactory, + int port, + const boost::shared_ptr& threadManager = + boost::shared_ptr(), + THRIFT_OVERLOAD_IF(Processor, TProcessor)) : + TServer(processor) { + + init(port); + + setDuplexProtocolFactory(duplexProtocolFactory); + setThreadManager(threadManager); + } + + template + TNonblockingServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& duplexTransportFactory, + const boost::shared_ptr& duplexProtocolFactory, + int port, + const boost::shared_ptr& threadManager = + boost::shared_ptr(), + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)): + TServer(processorFactory) { + + init(port); + + setDuplexTransportFactory(duplexTransportFactory); + setDuplexProtocolFactory(duplexProtocolFactory); + setThreadManager(threadManager); + } + + template + TNonblockingServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& duplexTransportFactory, + const boost::shared_ptr& duplexProtocolFactory, + int port, + const boost::shared_ptr& threadManager = + boost::shared_ptr(), + THRIFT_OVERLOAD_IF(Processor, TProcessor)): + TServer(processor) { + + init(port); + + setDuplexTransportFactory(duplexTransportFactory); + setDuplexProtocolFactory(duplexProtocolFactory); + setThreadManager(threadManager); + } + + void setThreadManager(boost::shared_ptr threadManager); + + boost::shared_ptr getThreadManager() { + return threadManager_; + } + + /** + * Sets the number of IO threads used by this server. Can only be used before + * the call to serve() and has no effect afterwards. We always use a + * PosixThreadFactory for the IO worker threads, because they must joinable + * for clean shutdown. + */ + void setNumIOThreads(size_t numThreads) { + numIOThreads_ = numThreads; + } + + /** Return whether the IO threads will get high scheduling priority */ + bool useHighPriorityIOThreads() const { + return useHighPriorityIOThreads_; + } + + /** Set whether the IO threads will get high scheduling priority. */ + void setUseHighPriorityIOThreads(bool val) { + useHighPriorityIOThreads_ = val; + } + + /** Return the number of IO threads used by this server. */ + size_t getNumIOThreads() const { + return numIOThreads_; + } + + /** + * Get the maximum number of unused TConnection we will hold in reserve. + * + * @return the current limit on TConnection pool size. + */ + size_t getConnectionStackLimit() const { + return connectionStackLimit_; + } + + /** + * Set the maximum number of unused TConnection we will hold in reserve. + * + * @param sz the new limit for TConnection pool size. + */ + void setConnectionStackLimit(size_t sz) { + connectionStackLimit_ = sz; + } + + bool isThreadPoolProcessing() const { + return threadPoolProcessing_; + } + + /** + * set the listen backlog + * + * @param listenBacklog the new listen backlog + */ + void setListenBacklog(int32_t listenBacklog) { + listenBacklog_ = listenBacklog; + } + + /** + * Return the count of sockets currently connected to. + * + * @return count of connected sockets. + */ + size_t getNumConnections() const { + return numTConnections_; + } + + /** + * Return the count of sockets currently connected to. + * + * @return count of connected sockets. + */ + size_t getNumActiveConnections() const { + return getNumConnections() - getNumIdleConnections(); + } + + /** + * Return the bytes in all connection's write buffer. + * + * @return bytes + */ + size_t getWriteBufferBytes() const { + concurrency::Guard g(connMutex_); + return getWriteBufferBytesImpl(); + } + + /** + * Return the bytes in all connection's read buffer. + * + * @return bytes + */ + size_t getReadBufferBytes() const { + concurrency::Guard g(connMutex_); + return getReadBufferBytesImpl(); + } + + /** + * Return the count of connection objects allocated but not in use. + * + * @return count of idle connection objects. + */ + size_t getNumIdleConnections() const { + return connectionStack_.size(); + } + + /** + * Return count of number of connections which are currently processing. + * This is defined as a connection where all data has been received and + * either assigned a task (when threading) or passed to a handler (when + * not threading), and where the handler has not yet returned. + * + * @return # of connections currently processing. + */ + size_t getNumActiveProcessors() const { + return numActiveProcessors_; + } + + /** + * Return the number of active/outstanding requests on the server. This + * includes requests that are processing, waiting to be processed and have + * been processed, but are waiting for the reply to be sent out over the wire. + * + * @return # of currently active requests. + */ + size_t getNumActiveRequests() const { + return numActiveRequests_; + } + + /** + * Get the maximum number of active requests. + * + * @return current setting. + */ + size_t getMaxActiveRequests() const { + return maxActiveRequests_; + } + + /** + * Set the maximum # of active requests allowed before overload. + * + * @param maxActiveRequsts new setting for maximum # of active requests. + */ + void setMaxActiveRequests(size_t maxActiveRequests) { + maxActiveRequests_ = maxActiveRequests; + } + + /** + * Get the maximum # of connections allowed before overload. + * + * @return current setting. + */ + size_t getMaxConnections() const { + return maxConnections_; + } + + /** + * Set the maximum # of connections allowed before overload. + * + * @param maxConnections new setting for maximum # of connections. + */ + void setMaxConnections(size_t maxConnections) { + maxConnections_ = maxConnections; + } + + /** + * Get the maximum # of connections waiting in handler/task before overload. + * + * @return current setting. + */ + size_t getMaxActiveProcessors() const { + return maxActiveProcessors_; + } + + /** + * Set the maximum # of connections waiting in handler/task before overload. + * + * @param maxActiveProcessors new setting for maximum # of active processes. + */ + void setMaxActiveProcessors(size_t maxActiveProcessors) { + maxActiveProcessors_ = maxActiveProcessors; + } + + /** + * Get the maximum memory usage allowed before overload. + * + * @return current setting. + */ + uint64_t getMaxMemoryUsageBytes() const { + return maxMemoryUsageBytes_; + } + + /** + * Set the maximum memory usage allowed before overload. + * + * @param maxMemoryUsage new setting for maximum memory usage. + */ + void setMaxMemoryUsageBytes(uint64_t maxMemoryUsageBytes) { + maxMemoryUsageBytes_ = maxMemoryUsageBytes; + } + + /** + * Get the maximum allowed frame size. + * + * If a client tries to send a message larger than this limit, + * its connection will be closed. + * + * @return Maxium frame size, in bytes. + */ + size_t getMaxFrameSize() const { + return maxFrameSize_; + } + + /** + * Set the maximum allowed frame size, up to 2^31-1 + * + * @param maxFrameSize The new maximum frame size. + */ + void setMaxFrameSize(size_t maxFrameSize) { + if (maxFrameSize > 0x7fffffff) { + maxFrameSize = 0x7fffffff; + } + maxFrameSize_ = maxFrameSize; + } + + /** + * Get fraction of maximum limits before an overload condition is cleared. + * + * @return hysteresis fraction + */ + double getOverloadHysteresis() const { + return overloadHysteresis_; + } + + /** + * Set fraction of maximum limits before an overload condition is cleared. + * A good value would probably be between 0.5 and 0.9. + * + * @param hysteresisFraction fraction <= 1.0. + */ + void setOverloadHysteresis(double hysteresisFraction) { + if (hysteresisFraction <= 1.0 && hysteresisFraction > 0.0) { + overloadHysteresis_ = hysteresisFraction; + } + } + + /** + * Get duration of stopping accepts when overload + * + * @return pauseAcceptDuration_ + */ + int getPauseAcceptDuration() const { + return pauseAcceptDuration_; + } + + /** + * Set the accept pause duration (when overload) in ms + * + * @param pauseDuration > 0 + */ + void setPauseAcceptDuration(int pauseDuration) { + if (pauseDuration > 0) { + pauseAcceptDuration_ = pauseDuration; + } + } + + /** + * Get the action the server will take on overload. + * + * @return a TOverloadAction enum value for the currently set action. + */ + TOverloadAction getOverloadAction() const { + return overloadAction_; + } + + /** + * Set the action the server is to take on overload. + * + * @param overloadAction a TOverloadAction enum value for the action. + */ + void setOverloadAction(TOverloadAction overloadAction) { + overloadAction_ = overloadAction; + } + + /** + * Get the time in milliseconds after which a task expires (0 == infinite). + * + * @return a 64-bit time in milliseconds. + */ + int64_t getTaskExpireTime() const { + return taskExpireTime_; + } + + /** + * Set the time in milliseconds after which a task expires (0 == infinite). + * + * @param taskExpireTime a 64-bit time in milliseconds. + */ + void setTaskExpireTime(int64_t taskExpireTime) { + taskExpireTime_ = taskExpireTime; + } + + /** + * Determine if the server is currently overloaded. + * This function checks the maximums for open connections and connections + * currently in processing, and sets an overload condition if they are + * exceeded. The overload will persist until both values are below the + * current hysteresis fraction of their maximums. + * + * @return true if an overload condition exists, false if not. + */ + bool serverOverloaded(); + + /** + * Check if the server is overloaded and overloadAction_ is + * T_OVERLOAD_PAUSE_ACCEPTING, and if so, pause the accept on the listening + * socket + * + * @return true if overloadAction_ != OVERLOAD_PAUSE_ACCEPTING, or + * if overload condition doesn't exist. + */ + bool canContinueToAccept(); + + /** + * Check if the server is overloaded, and if so, take the necessary action. + * + * @param conn The connection currently being processed that is triggering + * the overload check. + * + * Returns true if the current connection has been closed due to overload + * processing, and false otherwise. (Note that a false return value does not + * mean that the server is not overloaded.) + */ + bool checkForOverload(TConnection* conn); + + + /** Pop and discard next task on threadpool wait queue. + * + * @return true if a task was discarded, false if the wait queue was empty. + */ + bool drainPendingTask(); + + /** + * Get the starting size of a TConnection object's write buffer. + * + * @return # bytes we initialize a TConnection object's write buffer to. + */ + size_t getWriteBufferDefaultSize() const { + return writeBufferDefaultSize_; + } + + /** + * Set the starting size of a TConnection object's write buffer. + * + * @param size # bytes we initialize a TConnection object's write buffer to. + */ + void setWriteBufferDefaultSize(size_t size) { + writeBufferDefaultSize_ = size; + } + + /** + * Get the maximum size of read buffer allocated to idle TConnection objects. + * + * @return # bytes beyond which we will dealloc idle buffer. + */ + size_t getIdleReadBufferLimit() const { + return idleReadBufferLimit_; + } + + /** + * [NOTE: This is for backwards compatibility, use getIdleReadBufferLimit().] + * Get the maximum size of read buffer allocated to idle TConnection objects. + * + * @return # bytes beyond which we will dealloc idle buffer. + */ + size_t getIdleBufferMemLimit() const { + return idleReadBufferLimit_; + } + + /** + * Set the maximum size read buffer allocated to idle TConnection objects. + * If a TConnection object is found (either on connection close or between + * calls when resizeBufferEveryN_ is set) with more than this much memory + * allocated to its read buffer, we free it and allow it to be reinitialized + * on the next received frame. + * + * @param limit of bytes beyond which we will shrink buffers when checked. + */ + void setIdleReadBufferLimit(size_t limit) { + idleReadBufferLimit_ = limit; + } + + /** + * [NOTE: This is for backwards compatibility, use setIdleReadBufferLimit().] + * Set the maximum size read buffer allocated to idle TConnection objects. + * If a TConnection object is found (either on connection close or between + * calls when resizeBufferEveryN_ is set) with more than this much memory + * allocated to its read buffer, we free it and allow it to be reinitialized + * on the next received frame. + * + * @param limit of bytes beyond which we will shrink buffers when checked. + */ + void setIdleBufferMemLimit(size_t limit) { + idleReadBufferLimit_ = limit; + } + + + + /** + * Get the maximum size of write buffer allocated to idle TConnection objects. + * + * @return # bytes beyond which we will reallocate buffers when checked. + */ + size_t getIdleWriteBufferLimit() const { + return idleWriteBufferLimit_; + } + + /** + * Set the maximum size write buffer allocated to idle TConnection objects. + * If a TConnection object is found (either on connection close or between + * calls when resizeBufferEveryN_ is set) with more than this much memory + * allocated to its write buffer, we destroy and construct that buffer with + * writeBufferDefaultSize_ bytes. + * + * @param limit of bytes beyond which we will shrink buffers when idle. + */ + void setIdleWriteBufferLimit(size_t limit) { + idleWriteBufferLimit_ = limit; + } + + /** + * Get # of calls made between buffer size checks. 0 means disabled. + * + * @return # of calls between buffer size checks. + */ + int32_t getResizeBufferEveryN() const { + return resizeBufferEveryN_; + } + + /** + * Check buffer sizes every "count" calls. This allows buffer limits + * to be enforced for persistant connections with a controllable degree + * of overhead. 0 disables checks except at connection close. + * + * @param count the number of calls between checks, or 0 to disable + */ + void setResizeBufferEveryN(int32_t count) { + resizeBufferEveryN_ = count; + } + + /** + * Sets the sockOptHelper_ + * Socket options on underlying TSockets are set by passing + * the sockOptHelper_ to TSocket::setSocketOptions() function + * in the TConnection constructor + */ + void setSocketOptions(const TSocket::Options& oh) { + sockOptHelper_ = oh; + } + + void setObserver( + const boost::shared_ptr& observer) { + observer_ = observer; + } + + /** + * Main workhorse function, starts up the server listening on a port and + * loops over the libevent handler. + */ + void serve(); + + /** + * Causes the server to terminate gracefully (can be called from any thread). + */ + void stop(); + + TConnectionContext* getConnectionContext() const; + + private: + void addTask(boost::shared_ptr task) { + threadManager_->add(task, 0LL, taskExpireTime_); + } + + void setCurrentConnection(TConnection* conn) { + assert(currentConnection_.get() == NULL); + currentConnection_.set(conn); + } + void clearCurrentConnection() { + currentConnection_.clear(); + } + + /** + * Callback function that the threadmanager calls when a task reaches + * its expiration time. It is needed to clean up the expired connection. + * + * @param task the runnable associated with the expired task. + */ + void expireClose(boost::shared_ptr task); + + const boost::shared_ptr& getObserver() const { + return observer_; + } + + /// Creates a socket to listen on and binds it to the local port. + void createAndListenOnSocket(); + + /** + * Takes a socket created by createAndListenOnSocket() and sets various + * options on it to prepare for use in the server. + * + * @param fd descriptor of socket to be initialized/ + */ + void listenSocket(int fd); + /** + * Return an initialized connection object. Creates or recovers from + * pool a TConnection and initializes it with the provided socket FD + * and flags. + * + * @param socket FD of socket associated with this connection. + * @param addr the sockaddr of the client + * @param addrLen the length of addr + * @return pointer to initialized TConnection object. + */ + TConnection* createConnection(int socket, const sockaddr* addr, + socklen_t addrLen); + + /** + * Returns a connection to pool or deletion. If the connection pool + * (a stack) isn't full, place the connection object on it, otherwise + * just delete it. + * + * @param connection the TConection being returned. + */ + void returnConnection(TConnection* connection); +}; + +class TNonblockingIOThread : public Runnable { + public: + // Creates an IO thread and sets up the event base. The listenSocket should + // be a valid FD on which listen() has already been called. If the + // listenSocket is < 0, accepting will not be done. + TNonblockingIOThread(TNonblockingServer* server, + int number, + int listenSocket, + bool useHighPriority); + + ~TNonblockingIOThread(); + + // Returns the event-base for this thread. + event_base* getEventBase() const { return eventBase_; } + + // Returns the server for this thread. + TNonblockingServer* getServer() const { return server_; } + + // Returns the number of this IO thread. + int getThreadNumber() const { return number_; } + + // Returns the thread id associated with this object. This should + // only be called after the thread has been started. + pthread_t getThreadId() const { return threadId_; } + + // Returns the send-fd for task complete notifications. + int getNotificationSendFD() const { return notificationPipeFDs_[1]; } + + // Returns the read-fd for task complete notifications. + int getNotificationRecvFD() const { return notificationPipeFDs_[0]; } + + // Returns the actual thread object associated with this IO thread. + boost::shared_ptr getThread() const { return thread_; } + + // Sets the actual thread object associated with this IO thread. + void setThread(const boost::shared_ptr& t) { thread_ = t; } + + // Used by TConnection objects to indicate processing has finished. + bool notify(TNonblockingServer::TConnection* conn); + + // Enters the event loop and does not return until a call to stop(). + virtual void run(); + + // Exits the event loop as soon as possible. + void stop(); + + // Ensures that the event-loop thread is fully finished and shut down. + void join(); + + /// Maintains a count of requests for sampling purposes + /// request counter is maintained module the sample rate + uint32_t incrementRequestCounter(uint32_t sampleRate); + + /// Return true if the currently running thread is this I/O thread + bool isInIOThread() const { + return pthread_equal(pthread_self(), threadId_); + } + + /// Pauses accept event handling for pauseDuration milliseconds + void pauseAcceptHandling(int pauseDuration); + + private: + /** + * C-callable event handler for signaling task completion. Provides a + * callback that libevent can understand that will read a connection + * object's address from a pipe and call connection->transition() for + * that object. + * + * @param fd the descriptor the event occurred on. + */ + static void notifyHandler(int fd, short which, void* v); + + /** + * C-callable event handler for listener events. Provides a callback + * that libevent can understand which invokes server->handleEvent(). + * + * @param fd the descriptor the event occurred on. + * @param which the flags associated with the event. + * @param v void* callback arg where we placed TNonblockingServer's "this". + */ + static void listenHandler(int fd, short which, void* v) { + ((TNonblockingServer*)v)->handleEvent(fd, which); + } + + /** + * C-callable event handler to re-enable accept handling. + * Provides a callback that libevent can understand. + * + * @param fd unused. + * @param which the flags associated with the event. + * @param v void* callback arg where we placed TNonblockingIOThread's "this". + */ + static void reenableAcceptHandler(int fd, short which, void* v) { + ((TNonblockingIOThread*)v)->reenableAccept(); + } + + /// Re-enables accept event handling. + void reenableAccept(); + + /// Exits the loop ASAP in case of shutdown or error. + void breakLoop(bool error); + + /// Registers the events for the notification & listen sockets + void registerEvents(); + + /// Create the pipe used to notify I/O process of task completion. + void createNotificationPipe(); + + /// Unregisters our events for notification and listen sockets. + void cleanupEvents(); + + /// Sets (or clears) high priority scheduling status for the current thread. + void setCurrentThreadHighPriority(bool value); + + private: + /// associated server + TNonblockingServer* server_; + + /// thread number (for debugging). + const int number_; + + /// The actual physical thread id. + pthread_t threadId_; + + /// If listenSocket_ >= 0, adds an event on the event_base to accept conns + int listenSocket_; + + /// Sets a high scheduling priority when running + bool useHighPriority_; + + /// pointer to eventbase to be used for looping + event_base* eventBase_; + + /// Whether the server is currently accepting connections + bool acceptingConnections_; + + /// Used with eventBase_ for connection events (only in listener thread) + struct event serverEvent_; + + /// Used with eventBase_ for backing off on accept handling until there are + /// available fds + struct event acceptBackoffEvent_; + + /// Used with eventBase_ for task completion notification + struct event notificationEvent_; + + /// File descriptors for pipe used for task completion notification. + int notificationPipeFDs_[2]; + + /// Actual IO Thread + boost::shared_ptr thread_; + + /// Call counter + uint32_t requestCounter_; +}; + + +}}} // apache::thrift::server + +#endif // #ifndef THRIFT_SERVER_TNONBLOCKINGSERVER_H_ diff --git a/thrift/lib/cpp/server/TNonblockingServerObserver.h b/thrift/lib/cpp/server/TNonblockingServerObserver.h new file mode 100644 index 00000000..594a2849 --- /dev/null +++ b/thrift/lib/cpp/server/TNonblockingServerObserver.h @@ -0,0 +1,54 @@ +#ifndef THRIFT_SERVER_TNONBLOCKINGSERVEROBSERVER_H_ +#define THRIFT_SERVER_TNONBLOCKINGSERVEROBSERVER_H_ 1 + +#include + +namespace apache { namespace thrift { namespace server { + +class TNonblockingServerObserver { + public: + + virtual ~TNonblockingServerObserver() {} + + TNonblockingServerObserver() : sampleRate_(0) {} + TNonblockingServerObserver(uint32_t sampleRate) : sampleRate_(sampleRate) {} + + class CallTimestamps { + public: + uint64_t readBegin; + uint64_t readEnd; + uint64_t processBegin; + uint64_t processEnd; + uint64_t writeBegin; + uint64_t writeEnd; + + CallTimestamps() { + init(); + } + + void init() { + readBegin = readEnd = 0; + processBegin = processEnd = 0; + writeBegin = writeEnd = 0; + } + + }; + + // Notifications for various events on the TNonblockingServer + virtual void connDropped() = 0; + + virtual void taskKilled() = 0; + + virtual void callCompleted(const CallTimestamps& runtimes) = 0; + + // The observer has to specify a sample rate for callCompleted notifications + inline uint32_t getSampleRate() const { + return sampleRate_; + } + + protected: + uint32_t sampleRate_; +}; + +}}} // apache::thrift::server +#endif diff --git a/thrift/lib/cpp/server/TRpcTransportContext.h b/thrift/lib/cpp/server/TRpcTransportContext.h new file mode 100644 index 00000000..cb1a3022 --- /dev/null +++ b/thrift/lib/cpp/server/TRpcTransportContext.h @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_SERVER_TRPCTRANSPORTCONTEXT_H_ +#define THRIFT_SERVER_TRPCTRANSPORTCONTEXT_H_ 1 + +#include "thrift/lib/cpp/server/TConnectionContext.h" + +#include + +namespace apache { namespace thrift { + +namespace transport { +class TRpcTransport; +} + +namespace server { + +class TRpcTransportContext : public TConnectionContext { + public: + TRpcTransportContext(boost::shared_ptr transport) + : transport_(transport) {} + + TRpcTransportContext( + const boost::shared_ptr& transport, + const boost::shared_ptr& iprot, + const boost::shared_ptr& oprot) + : transport_(transport), + iprot_(iprot), + oprot_(oprot) {} + + virtual const transport::TSocketAddress* getPeerAddress() const; + + const boost::shared_ptr& getTransport() const { + return transport_; + } + + virtual boost::shared_ptr getInputProtocol() const { + return iprot_; + } + + virtual boost::shared_ptr getOutputProtocol() const { + return oprot_; + } + + private: + boost::shared_ptr transport_; + boost::shared_ptr iprot_; + boost::shared_ptr oprot_; +}; + +}}} // apache::thrift::server + +#endif // THRIFT_SERVER_TRPCTRANSPORTCONTEXT_H_ diff --git a/thrift/lib/cpp/server/TServer.h b/thrift/lib/cpp/server/TServer.h new file mode 100644 index 00000000..9623b41d --- /dev/null +++ b/thrift/lib/cpp/server/TServer.h @@ -0,0 +1,324 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_SERVER_TSERVER_H +#define THRIFT_SERVER_TSERVER_H 1 + +#include "thrift/lib/cpp/TProcessor.h" +#include "thrift/lib/cpp/transport/TServerTransport.h" +#include "thrift/lib/cpp/protocol/TBinaryProtocol.h" +#include "thrift/lib/cpp/concurrency/Thread.h" +#include "thrift/lib/cpp/util/shared_ptr_util.h" + +namespace apache { namespace thrift { + +namespace transport { +class TSocketAddress; +} + +namespace server { + +using apache::thrift::TProcessor; +using apache::thrift::protocol::TBinaryProtocolFactory; +using apache::thrift::protocol::TProtocol; +using apache::thrift::protocol::TProtocolFactory; +using apache::thrift::protocol::TDuplexProtocolFactory; +using apache::thrift::protocol::TDualProtocolFactory; +using apache::thrift::protocol::TSingleProtocolFactory; +using apache::thrift::transport::TServerTransport; +using apache::thrift::transport::TTransport; +using apache::thrift::transport::TTransportFactory; +using apache::thrift::transport::TDuplexTransportFactory; +using apache::thrift::transport::TDualTransportFactory; +using apache::thrift::transport::TSingleTransportFactory; + +class TConnectionContext; + +/** + * Virtual interface class that can handle events from the server core. To + * use this you should subclass it and implement the methods that you care + * about. Your subclass can also store local data that you may care about, + * such as additional "arguments" to these methods (stored in the object + * instance's state). + */ +class TServerEventHandler { + public: + + virtual ~TServerEventHandler() {} + + /** + * Called before the server begins. + * + * @param address The address on which the server is listening. + */ + virtual void preServe(const transport::TSocketAddress* address) {} + + /** + * Called when a new client has connected and is about to being processing. + * + * @param ctx A pointer to the connection context. The context will remain + * valid until the corresponding connectionDestroyed() call. + */ + virtual void newConnection(TConnectionContext* ctx) { + (void)ctx; + } + + /** + * Called when a client has finished request-handling to delete server + * context. + * + * @param ctx A pointer to the connection context. The context will be + * destroyed after connectionDestroyed() returns. + */ + virtual void connectionDestroyed(TConnectionContext* ctx) { + (void)ctx; + } + + protected: + + /** + * Prevent direct instantiation. + */ + TServerEventHandler() {} + +}; + +/** + * Thrift server. + * + */ +class TServer : public concurrency::Runnable { + public: + + virtual ~TServer() {} + + virtual void serve() = 0; + + virtual void stop() {} + + // This API is intended to stop listening on the server + // socket and stop accepting new connection first while + // still letting the established connections to be + // processed on the server. + virtual void stopListening() {} + + // Allows running the server as a Runnable thread + virtual void run() { + serve(); + } + + boost::shared_ptr getProcessorFactory() { + return processorFactory_; + } + + boost::shared_ptr getServerTransport() { + return serverTransport_; + } + + boost::shared_ptr getDuplexTransportFactory() { + return duplexTransportFactory_; + } + + boost::shared_ptr getDuplexProtocolFactory() { + return duplexProtocolFactory_; + } + + boost::shared_ptr getEventHandler() { + return eventHandler_; + } + + /** + * Get the TConnectionContext for the connection currently being processed. + * + * This is intended to be invoked from within the TProcessor (or the handler + * used by the TProcessor). + * + * Note: Not all server types currently support getConnectionContext(). Some + * servers may always return NULL. + * + * TODO: Eventually this method should be supported by all server types, and + * made into a pure virtual method. + * + * @return Return a pointer to the TConnectionContext for the current + * connection, or NULL if invoked outside of a call to + * TProcessor::process(). The returned object is only guaranteed to + * be valid until process() returns. + */ + virtual TConnectionContext* getConnectionContext() const { + return NULL; + } + +protected: + template + TServer(const boost::shared_ptr& processorFactory, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)): + processorFactory_(processorFactory) { + setTransportFactory(boost::shared_ptr( + new TTransportFactory())); + setProtocolFactory(boost::shared_ptr( + new TBinaryProtocolFactory())); + } + + template + TServer(const boost::shared_ptr& processor, + THRIFT_OVERLOAD_IF(Processor, TProcessor)): + processorFactory_(new TSingletonProcessorFactory(processor)) { + setTransportFactory(boost::shared_ptr( + new TTransportFactory())); + setProtocolFactory(boost::shared_ptr( + new TBinaryProtocolFactory())); + } + + template + TServer(const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)): + processorFactory_(processorFactory), + serverTransport_(serverTransport) { + setTransportFactory(boost::shared_ptr( + new TTransportFactory())); + setProtocolFactory(boost::shared_ptr( + new TBinaryProtocolFactory())); + } + + template + TServer(const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + THRIFT_OVERLOAD_IF(Processor, TProcessor)): + processorFactory_(new TSingletonProcessorFactory(processor)), + serverTransport_(serverTransport) { + setTransportFactory(boost::shared_ptr( + new TTransportFactory())); + setProtocolFactory(boost::shared_ptr( + new TBinaryProtocolFactory())); + } + + template + TServer(const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)): + processorFactory_(processorFactory), + serverTransport_(serverTransport) { + setTransportFactory(transportFactory); + setProtocolFactory(protocolFactory); + } + + template + TServer(const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + THRIFT_OVERLOAD_IF(Processor, TProcessor)): + processorFactory_(new TSingletonProcessorFactory(processor)), + serverTransport_(serverTransport) { + setTransportFactory(transportFactory); + setProtocolFactory(protocolFactory); + } + + template + TServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& duplexTransportFactory, + const boost::shared_ptr& duplexProtocolFactory, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)) : + processorFactory_(processorFactory), + serverTransport_(serverTransport), + duplexTransportFactory_(duplexTransportFactory), + duplexProtocolFactory_(duplexProtocolFactory) {} + + template + TServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& duplexTransportFactory, + const boost::shared_ptr& duplexProtocolFactory, + THRIFT_OVERLOAD_IF(Processor, TProcessor)) : + processorFactory_(new TSingletonProcessorFactory(processor)), + serverTransport_(serverTransport), + duplexTransportFactory_(duplexTransportFactory), + duplexProtocolFactory_(duplexProtocolFactory) {} + + /** + * Get a TProcessor to handle calls on a particular connection. + * + * This method should only be called once per connection (never once per + * call). This allows the TProcessorFactory to return a different processor + * for each connection if it desires. + */ + boost::shared_ptr getProcessor(TConnectionContext* ctx) { + return processorFactory_->getProcessor(ctx); + } + + // Class variables + boost::shared_ptr processorFactory_; + boost::shared_ptr serverTransport_; + + boost::shared_ptr duplexTransportFactory_; + boost::shared_ptr duplexProtocolFactory_; + + boost::shared_ptr eventHandler_; + +public: + void setProcessorFactory( + boost::shared_ptr processorFactory) { + processorFactory_ = processorFactory; + } + + void setTransportFactory( + boost::shared_ptr transportFactory) { + duplexTransportFactory_.reset( + new TSingleTransportFactory(transportFactory)); + } + + void setDuplexTransportFactory( + boost::shared_ptr duplexTransportFactory) { + duplexTransportFactory_ = duplexTransportFactory; + } + + void setProtocolFactory(boost::shared_ptr protocolFactory) { + duplexProtocolFactory_.reset( + new TSingleProtocolFactory(protocolFactory)); + } + + void setDuplexProtocolFactory( + boost::shared_ptr duplexProtocolFactory) { + duplexProtocolFactory_ = duplexProtocolFactory; + } + + void setServerEventHandler( + boost::shared_ptr eventHandler) { + eventHandler_ = eventHandler; + } + +}; + +/** + * Helper function to increase the max file descriptors limit + * for the current process and all of its children. + * By default, tries to increase it to as much as 2^24. + */ + int increase_max_fds(int max_fds=(1<<24)); + + +}}} // apache::thrift::server + +#endif // #ifndef THRIFT_SERVER_TSERVER_H diff --git a/thrift/lib/cpp/server/TSimpleServer.h b/thrift/lib/cpp/server/TSimpleServer.h new file mode 100644 index 00000000..6a35d0d0 --- /dev/null +++ b/thrift/lib/cpp/server/TSimpleServer.h @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_SERVER_TSIMPLESERVER_H +#define THRIFT_SERVER_TSIMPLESERVER_H 1 + +#include "thrift/lib/cpp/server/TServer.h" +#include "thrift/lib/cpp/transport/TServerTransport.h" + +namespace apache { namespace thrift { namespace server { + +/** + * This is the most basic simple server. It is single-threaded and runs a + * continuous loop of accepting a single connection, processing requests on + * that connection until it closes, and then repeating. It is a good example + * of how to extend the TServer interface. + * + */ +class TSimpleServer : public TServer { + public: + template + TSimpleServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)) : + TServer(processorFactory, serverTransport, transportFactory, + protocolFactory), + stop_(false), + connectionCtx_(NULL) {} + + template + TSimpleServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + THRIFT_OVERLOAD_IF(Processor, TProcessor)) : + TServer(processor, serverTransport, transportFactory, protocolFactory), + stop_(false), + connectionCtx_(NULL) {} + + template + TSimpleServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& duplexTransportFactory, + const boost::shared_ptr& duplexProtocolFactory, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)) : + TServer(processorFactory, serverTransport, + duplexTransportFactory, duplexProtocolFactory), + stop_(false), + connectionCtx_(NULL) {} + + template + TSimpleServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& duplexTransportFactory, + const boost::shared_ptr& duplexProtocolFactory, + THRIFT_OVERLOAD_IF(Processor, TProcessor)) : + TServer(processor, serverTransport, + duplexTransportFactory, duplexProtocolFactory), + stop_(false), + connectionCtx_(NULL) {} + + ~TSimpleServer() {} + + void serve(); + + void stop(); + + TConnectionContext* getConnectionContext() const; + + protected: + bool stop_; + TConnectionContext* connectionCtx_; +}; + +}}} // apache::thrift::server + +#endif // #ifndef THRIFT_SERVER_TSIMPLESERVER_H diff --git a/thrift/lib/cpp/server/TThreadPoolServer.h b/thrift/lib/cpp/server/TThreadPoolServer.h new file mode 100644 index 00000000..2ce0e2e3 --- /dev/null +++ b/thrift/lib/cpp/server/TThreadPoolServer.h @@ -0,0 +1,130 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_SERVER_TTHREADPOOLSERVER_H +#define THRIFT_SERVER_TTHREADPOOLSERVER_H 1 + +#include "thrift/lib/cpp/concurrency/ThreadManager.h" +#include "thrift/lib/cpp/server/TServer.h" +#include "thrift/lib/cpp/transport/TServerTransport.h" +#include "thrift/lib/cpp/concurrency/ThreadLocal.h" + +#include + +namespace apache { namespace thrift { namespace server { + +using apache::thrift::concurrency::ThreadManager; +using apache::thrift::protocol::TProtocolFactory; +using apache::thrift::transport::TServerTransport; +using apache::thrift::transport::TTransportFactory; + +class TThreadPoolServer : public TServer { + public: + template + TThreadPoolServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + const boost::shared_ptr& threadManager, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)) : + TServer(processorFactory, serverTransport, transportFactory, + protocolFactory), + threadManager_(threadManager), + stop_(false), + timeout_(0) {} + + template + TThreadPoolServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + const boost::shared_ptr& threadManager, + THRIFT_OVERLOAD_IF(Processor, TProcessor)) : + TServer(processor, serverTransport, transportFactory, protocolFactory), + threadManager_(threadManager), + stop_(false), + timeout_(0) {} + + template + TThreadPoolServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& duplexTransportFactory, + const boost::shared_ptr& duplexProtocolFactory, + const boost::shared_ptr& threadManager, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)): + TServer(processorFactory, serverTransport, + duplexTransportFactory, duplexProtocolFactory), + threadManager_(threadManager), + stop_(false), + timeout_(0) {} + + template + TThreadPoolServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& duplexTransportFactory, + const boost::shared_ptr& duplexProtocolFactory, + const boost::shared_ptr& threadManager, + THRIFT_OVERLOAD_IF(Processor, TProcessor)): + TServer(processor, serverTransport, + duplexTransportFactory, duplexProtocolFactory), + threadManager_(threadManager), + stop_(false), + timeout_(0) {} + + virtual ~TThreadPoolServer(); + + virtual void serve(); + + virtual int64_t getTimeout() const; + + virtual void setTimeout(int64_t value); + + virtual void stop() { + stop_ = true; + serverTransport_->interrupt(); + } + + virtual TConnectionContext* getConnectionContext() const; + + protected: + class Task; + typedef concurrency::ThreadLocal > + ThreadLocalTask; + + void setCurrentTask(Task* task); + void clearCurrentTask(); + + boost::shared_ptr threadManager_; + volatile bool stop_; + volatile int64_t timeout_; + + /** + * Thread-local data storage to track the current connection being processed. + */ + ThreadLocalTask currentTask_; +}; + +}}} // apache::thrift::server + +#endif // #ifndef THRIFT_SERVER_TTHREADPOOLSERVER_H diff --git a/thrift/lib/cpp/server/TThreadedServer.h b/thrift/lib/cpp/server/TThreadedServer.h new file mode 100644 index 00000000..61c50345 --- /dev/null +++ b/thrift/lib/cpp/server/TThreadedServer.h @@ -0,0 +1,223 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_SERVER_TTHREADEDSERVER_H +#define THRIFT_SERVER_TTHREADEDSERVER_H 1 + +#include "thrift/lib/cpp/server/TServer.h" +#include "thrift/lib/cpp/transport/TServerTransport.h" +#include "thrift/lib/cpp/concurrency/Monitor.h" +#include "thrift/lib/cpp/concurrency/Thread.h" +#include "thrift/lib/cpp/concurrency/ThreadLocal.h" + +#include + +namespace apache { namespace thrift { namespace server { + +using apache::thrift::TProcessor; +using apache::thrift::transport::TServerTransport; +using apache::thrift::transport::TTransportFactory; +using apache::thrift::concurrency::Monitor; +using apache::thrift::concurrency::ThreadFactory; + +class TThreadedServer : public TServer { + + public: + class Task; + + template + TThreadedServer(const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)); + + template + TThreadedServer(const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + const boost::shared_ptr& threadFactory, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)); + + template + TThreadedServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& duplexTransportFactory, + const boost::shared_ptr& duplexProtocolFactory, + const boost::shared_ptr& threadFactory, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)); + + template + TThreadedServer(const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + THRIFT_OVERLOAD_IF(Processor, TProcessor)); + + template + TThreadedServer(const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + const boost::shared_ptr& threadFactory, + THRIFT_OVERLOAD_IF(Processor, TProcessor)); + + template + TThreadedServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& duplexTransportFactory, + const boost::shared_ptr& duplexProtocolFactory, + THRIFT_OVERLOAD_IF(Processor, TProcessor)); + + template + TThreadedServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& duplexTransportFactory, + const boost::shared_ptr& duplexProtocolFactory, + const boost::shared_ptr& threadFactory, + THRIFT_OVERLOAD_IF(Processor, TProcessor)); + + virtual ~TThreadedServer(); + + virtual void serve(); + + void stop() { + stop_ = true; + serverTransport_->interrupt(); + } + + virtual TConnectionContext* getConnectionContext() const; + + protected: + typedef concurrency::ThreadLocal > + ThreadLocalTask; + + void init(); + void setCurrentTask(Task* task); + + boost::shared_ptr threadFactory_; + volatile bool stop_; + + Monitor tasksMonitor_; + std::set tasks_; + + /** + * Thread-local data storage to track the current connection being processed. + */ + ThreadLocalTask currentTask_; +}; + +template +TThreadedServer::TThreadedServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + THRIFT_OVERLOAD_IF_DEFN(ProcessorFactory, TProcessorFactory)) : + TServer(processorFactory, serverTransport, transportFactory, + protocolFactory) { + init(); +} + +template +TThreadedServer::TThreadedServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + const boost::shared_ptr& threadFactory, + THRIFT_OVERLOAD_IF_DEFN(ProcessorFactory, TProcessorFactory)) : + TServer(processorFactory, serverTransport, transportFactory, + protocolFactory), + threadFactory_(threadFactory) { + init(); +} + +template +TThreadedServer::TThreadedServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& duplexTransportFactory, + const boost::shared_ptr& duplexProtocolFactory, + const boost::shared_ptr& threadFactory, + THRIFT_OVERLOAD_IF_DEFN(ProcessorFactory, TProcessorFactory)): + TServer(processorFactory, serverTransport, duplexTransportFactory, + duplexProtocolFactory), + threadFactory_(threadFactory) { + init(); +} + +template +TThreadedServer::TThreadedServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + THRIFT_OVERLOAD_IF_DEFN(Processor, TProcessor)) : + TServer(processor, serverTransport, transportFactory, protocolFactory) { + init(); +} + +template +TThreadedServer::TThreadedServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + const boost::shared_ptr& threadFactory, + THRIFT_OVERLOAD_IF_DEFN(Processor, TProcessor)) : + TServer(processor, serverTransport, transportFactory, protocolFactory), + threadFactory_(threadFactory) { + init(); +} + +template +TThreadedServer::TThreadedServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& duplexTransportFactory, + const boost::shared_ptr& duplexProtocolFactory, + THRIFT_OVERLOAD_IF_DEFN(Processor, TProcessor)) : + TServer(processor, serverTransport, duplexTransportFactory, + duplexProtocolFactory) { + init(); +} + +template +TThreadedServer::TThreadedServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& duplexTransportFactory, + const boost::shared_ptr& duplexProtocolFactory, + const boost::shared_ptr& threadFactory, + THRIFT_OVERLOAD_IF_DEFN(Processor, TProcessor)): + TServer(processor, serverTransport, duplexTransportFactory, + duplexProtocolFactory), + threadFactory_(threadFactory) { + init(); +} + +}}} // apache::thrift::server + +#endif // #ifndef _THRIFT_SERVER_TTHREADEDSERVER_H_ diff --git a/thrift/lib/cpp/server/test/AggregatorTest.thrift b/thrift/lib/cpp/server/test/AggregatorTest.thrift new file mode 100644 index 00000000..3f94ba36 --- /dev/null +++ b/thrift/lib/cpp/server/test/AggregatorTest.thrift @@ -0,0 +1,41 @@ +#!/usr/local/bin/thrift -cpp + +include "common/fb303/if/fb303.thrift" + +namespace cpp apache.thrift.async + +struct StructRequest { + 1:i32 i32Val, + 2:i64 i64Val, + 3:double doubleVal, + 4:string stringVal, +} + +struct StructResponse { + 1:StructRequest request, + 2:i32 errorCode + 3:string answerString, +} + +service AggregatorTest extends fb303.FacebookService { + StructResponse sendStructRecvStruct(1:StructRequest request), + oneway void sendStructNoRecv(1:StructRequest request), + StructResponse sendMultiParamsRecvStruct( + 1:i32 i32Val, + 2:i64 i64Val, + 3:double doubleVal, + 4:string stringVal, + 5:StructRequest structVal, + ), + oneway void sendMultiParamsNoRecv( + 1:i32 i32Val, + 2:i64 i64Val, + 3:double doubleVal, + 4:string stringVal, + 5:StructRequest structVal, + ), + StructResponse noSendRecvStruct(), + oneway void noSendNoRecv(), +} + + diff --git a/thrift/lib/cpp/server/test/AggregatorUtilTest.h b/thrift/lib/cpp/server/test/AggregatorUtilTest.h new file mode 100644 index 00000000..6020ad80 --- /dev/null +++ b/thrift/lib/cpp/server/test/AggregatorUtilTest.h @@ -0,0 +1,143 @@ +#ifndef COMMON_CLIENT_MGMT_AGGR_UTILTEST +#define COMMON_CLIENT_MGMT_AGGR_UTILTEST 1 + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "thrift/lib/cpp/server/test/gen-cpp/AggregatorTest_types.h" +#include "thrift/lib/cpp/server/test/gen-cpp/AggregatorTest.h" + +#include "common/logging/logging.h" + +static inline void defaultData(apache::thrift::async::StructRequest* res) { + res->i32Val = 32; + res->i64Val = 64; + res->doubleVal = -12.34; + res->stringVal = "string"; +} + +static inline void randomData(apache::thrift::async::StructRequest* res) { + res->i32Val = ::random(); + res->i64Val = ::random(); + res->doubleVal = ::random() * ((::random() % 2) == 0 ? -1 : 1); + res->stringVal = boost::lexical_cast(::random()); +} + +static inline void toAnswerString(std::string* dest, + const int32_t i32Val, + const int64_t i64Val, + const double doubleVal, + const std::string& stringVal) { + *dest += + boost::lexical_cast(i32Val) + + ";" + + boost::lexical_cast(i64Val) + + ";" + + boost::lexical_cast(doubleVal) + + ";" + + boost::lexical_cast(stringVal); +} + +static inline void toAnswerString(std::string* dest, + const apache::thrift::async::StructRequest& request) { + toAnswerString(dest, request.i32Val, + request.i64Val, + request.doubleVal, + request.stringVal); +} + +static inline void toAnswerString(std::string* dest, + const int32_t i32Val, + const int64_t i64Val, + const double doubleVal, + const std::string& stringVal, + const apache::thrift::async::StructRequest& structVal) { + toAnswerString(dest, i32Val, + i64Val, + doubleVal, + stringVal); + *dest += "*"; + toAnswerString(dest, structVal); +} + +static inline void zeroResponse(apache::thrift::async::StructResponse* dest) { + dest->request.i32Val = 0; + dest->request.i64Val = 0; + dest->request.doubleVal = 0.0; + dest->request.stringVal = ""; + dest->errorCode = 0; + dest->answerString = ""; +} + +static inline void printResponse( + const apache::thrift::async::StructResponse& x) { + LOG(INFO) << "request.i32Val: " << x.request.i32Val + << ", request.i64Val: " << x.request.i64Val + << ", request.doubleVal: " << x.request.doubleVal + << ", request.stringVal: " << x.request.stringVal + << ", request.stringVal: " << x.request.stringVal + << ", errorCode: " << x.errorCode + << ", answerString: " << x.answerString; +} + +static inline bool equalResult( + const apache::thrift::async::StructResponse& ethalon, + const apache::thrift::async::StructResponse& response) { + bool res = ethalon.request.i32Val == response.request.i32Val + && ethalon.request.i64Val == response.request.i64Val + && fabs(ethalon.request.doubleVal - response.request.doubleVal) < 0.0001 + && ethalon.request.stringVal == response.request.stringVal + && ethalon.errorCode == response.errorCode + && ethalon.answerString == response.answerString; + if (!res) { + printResponse(ethalon); + printResponse(response); + } + return res; +} + +static inline void addResponse(apache::thrift::async::StructResponse* dest, + const apache::thrift::async::StructResponse& src) { + dest->request.i32Val += src.request.i32Val; + dest->request.i64Val += src.request.i64Val; + dest->request.doubleVal += src.request.doubleVal; + dest->request.stringVal += src.request.stringVal; + dest->errorCode += src.errorCode; + dest->answerString += "/"; + dest->answerString += src.answerString; +} + +static inline void addRequest(apache::thrift::async::StructResponse* dest, + const apache::thrift::async::StructRequest& src) { + apache::thrift::async::StructResponse response; + response.request = src; + response.errorCode = 0; + response.answerString = ""; + toAnswerString(&response.answerString, response.request); + addResponse(dest, response); +} + +static inline void addRequest(apache::thrift::async::StructResponse* dest, + const int32_t i32Val, + const int64_t i64Val, + const double doubleVal, + const std::string& stringVal, + const apache::thrift::async::StructRequest& structVal) { + apache::thrift::async::StructResponse response; + response.request = structVal; + response.errorCode = 0; + response.answerString = ""; + toAnswerString(&response.answerString, + i32Val, i64Val, doubleVal, stringVal, response.request); + addResponse(dest, response); +} + +#endif diff --git a/thrift/lib/cpp/server/test/connctx.thrift b/thrift/lib/cpp/server/test/connctx.thrift new file mode 100644 index 00000000..3f65fb36 --- /dev/null +++ b/thrift/lib/cpp/server/test/connctx.thrift @@ -0,0 +1,7 @@ +exception CtxError { + 1: string message +} (message = "message") + +service ConnCtxService { + binary getClientAddress() throws (1: CtxError error) +} diff --git a/thrift/lib/cpp/test/DebugProtocolTest.thrift b/thrift/lib/cpp/test/DebugProtocolTest.thrift new file mode 100644 index 00000000..7a7278ec --- /dev/null +++ b/thrift/lib/cpp/test/DebugProtocolTest.thrift @@ -0,0 +1,27 @@ +struct Message { + 1: bool a, + 2: byte b, + 3: i16 c, + 4: i32 d, + 5: i64 e, + 6: double f, + 7: string g +} + +typedef list MsgList +typedef list IntList +typedef list StringList + + +typedef map MsgMap +typedef set MsgSet + +struct Ooo { + 1: MsgList l, + 2: MsgMap m, + 3: MsgSet s +} + +service DebugProtocolService { + void Func(1: MsgList lst); +} diff --git a/thrift/lib/cpp/test/NetworkUtil.h b/thrift/lib/cpp/test/NetworkUtil.h new file mode 100644 index 00000000..853d413c --- /dev/null +++ b/thrift/lib/cpp/test/NetworkUtil.h @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_NETWORKUTIL_H_ +#define THRIFT_TEST_NETWORKUTIL_H_ 1 + +#include + +namespace apache { namespace thrift { + +namespace transport { +class TSocketAddress; +} + +namespace test { + +/** + * Get a list of all configured local IP addresses. + */ +void getLocalAddresses(std::vector* results); + +}}} // apache::thrift::test + +#endif // THRIFT_TEST_NETWORKUTIL_H_ diff --git a/thrift/lib/cpp/test/STAR.newdev.facebook.com.crt b/thrift/lib/cpp/test/STAR.newdev.facebook.com.crt new file mode 100644 index 00000000..3b91dcfa --- /dev/null +++ b/thrift/lib/cpp/test/STAR.newdev.facebook.com.crt @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIF9DCCBNygAwIBAgIKEf4IyQAAAAAt5DANBgkqhkiG9w0BAQUFADBKMRMwEQYK +CZImiZPyLGQBGRYDY29tMRswGQYKCZImiZPyLGQBGRYLVGhlRmFjZWJvb2sxFjAU +BgNVBAMTDVRoZUZhY2Vib29rQ0EwHhcNMTEwNDI4MTkxMjU0WhcNMTMwNDI3MTkx +MjU0WjAgMR4wHAYDVQQDDBUqLm5ld2Rldi5mYWNlYm9vay5jb20wggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC42UW2BSdL/OkaP7OGsPGxmZjKEvkYLnSC +WEJLrs9axKTe35jLD6SZjZtUkQn8DelgeDgKrHo5mbPz7yO4TKDBZaVj0nhJRnto +sCrRXyNinslmgThaIGkQOglNO9zly7fKYl0DQDJ+YG4zX6oV/43ZosjXjeLJNHiD +A14rXfUoooUoFFULb4QeKehI9FZo9KyMMtUofAl4Ms2Yu+eO3oOfq+fK0H3qLRVX +KP0+fQXknx6O/a584CkedLpuc+i2a7Lp6iuT7ZHyJgTpE1Lw2JawlE7MACcAHsve +ODpC5AL53luvu1uvVQqUOeQ6Thz4n0BtPKn+KIzEleDCdeCy5QLXAgMBAAGjggME +MIIDADAdBgNVHQ4EFgQUn79HO8QnhoLhTFmXyIMYpNQLgMowHwYDVR0jBBgwFoAU +/c5mcfzW2IaPBA5cUuOYapXlvScwggEPBgNVHR8EggEGMIIBAjCB/6CB/KCB+YaB +u2xkYXA6Ly8vQ049VGhlRmFjZWJvb2tDQSxDTj1TQy1DQVNVQjAxLENOPUNEUCxD +Tj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1 +cmF0aW9uLERDPVRoZUZhY2Vib29rLERDPWNvbT9jZXJ0aWZpY2F0ZVJldm9jYXRp +b25MaXN0P2Jhc2U/b2JqZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnSGOWh0 +dHA6Ly9jZXJ0cy50aGVmYWNlYm9vay5jb20vQ2VydEVucm9sbC9UaGVGYWNlYm9v +a0NBLmNybDCCAScGCCsGAQUFBwEBBIIBGTCCARUwgbAGCCsGAQUFBzAChoGjbGRh +cDovLy9DTj1UaGVGYWNlYm9va0NBLENOPUFJQSxDTj1QdWJsaWMlMjBLZXklMjBT +ZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9uLERDPVRoZUZhY2Vi +b29rLERDPWNvbT9jQUNlcnRpZmljYXRlP2Jhc2U/b2JqZWN0Q2xhc3M9Y2VydGlm +aWNhdGlvbkF1dGhvcml0eTBgBggrBgEFBQcwAoZUaHR0cDovL2NlcnRzLnRoZWZh +Y2Vib29rLmNvbS9DZXJ0RW5yb2xsL1NDLUNBU1VCMDEuVGhlRmFjZWJvb2suY29t +X1RoZUZhY2Vib29rQ0EuY3J0MA4GA1UdDwEB/wQEAwIFoDA+BgkrBgEEAYI3FQcE +MTAvBicrBgEEAYI3FQiCuMAag87Wd4fdgReE4Kg9h9aFb4E4hrepboP/41MCAWQC +AQIwEwYDVR0lBAwwCgYIKwYBBQUHAwEwGwYJKwYBBAGCNxUKBA4wDDAKBggrBgEF +BQcDATANBgkqhkiG9w0BAQUFAAOCAQEAgVv0ngnjVzRNv9tu1pk/a9nW6+tKDMCO +IgqUHFO5MmnlOSGK+PLBV8gflBnzjDl7y+LCtMXPSpdTFA7hBrxsVGsLwMjluttO +Az50eskueoO2jxUe21uQw+7Fiy5EhtVdsDPQ/CXZXA2MNGV0cFVxLIY+IpzddP25 +fz1j/r3YtomHaEtGaJXDkgb7YdcLlJ5XZKM59Idp4KfLRNUTjaZXIUpTEBRcIdYV +WXcbFRNBM9oBRej9YEeXdlx51w38eX1BczQ40pwTsi7ze+1ZNESaK9oqvZuNsisg +CYJunbzTNfHWB6M/uvLiwoWjGihr8cf3/ULtxcq9+IFmsphavEzn7A== +-----END CERTIFICATE----- diff --git a/thrift/lib/cpp/test/STAR.newdev.facebook.com.key b/thrift/lib/cpp/test/STAR.newdev.facebook.com.key new file mode 100644 index 00000000..eab6acf2 --- /dev/null +++ b/thrift/lib/cpp/test/STAR.newdev.facebook.com.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAuNlFtgUnS/zpGj+zhrDxsZmYyhL5GC50glhCS67PWsSk3t+Y +yw+kmY2bVJEJ/A3pYHg4Cqx6OZmz8+8juEygwWWlY9J4SUZ7aLAq0V8jYp7JZoE4 +WiBpEDoJTTvc5cu3ymJdA0AyfmBuM1+qFf+N2aLI143iyTR4gwNeK131KKKFKBRV +C2+EHinoSPRWaPSsjDLVKHwJeDLNmLvnjt6Dn6vnytB96i0VVyj9Pn0F5J8ejv2u +fOApHnS6bnPotmuy6eork+2R8iYE6RNS8NiWsJROzAAnAB7L3jg6QuQC+d5br7tb +r1UKlDnkOk4c+J9AbTyp/iiMxJXgwnXgsuUC1wIDAQABAoIBAQCAFHxLDPMXodxa +hbz9HOm7Z3QIwHC8oqO0FTeKfUvL1uluTHvwZ5xjkU0JoZ3LelA0udgK/UuLUcbw +xMh5UQ8qMiYRLqqOCzpDZZ2liUhZczCVx/+l40MpLS14yHvc9fUZVGKid/8Etghl +rGmL6JD/Nd34DaYQSD0gelrrraTLS/K/f3II1AkJUYUNGoe+FHlBOIMw0rrl2yLX +nvCK7DCCWXkdy5PAolm1sEek3ZWRLvykYQm+Pe7tDDAXb7JEhnp1MCwz8QPv3A+8 +Wotk8LdIsRbqdHjychBaHNu4XfyIwfK2W3+yTBudbs3eHzMOvbY7lznb1tcpAiFQ +ot+YwMJhAoGBAOm0dSj2DbAvf53F49EoqNqRlrXuH5PHRFsPeGPHRJXt+AVYzwMe +lMlDXhU3+hgZmE1aKci9sr2i0z71GpLxTAcIzITC0iyWok2h7NC6HtFW0xM3U/oc +1THDWwbxULTzGEzEuYq5AR5xu54aEfjEpCBVBWP52lyNs3hPTHlcOoLpAoGBAMp7 +pgTPnJr/Nr4Fdny/D3Iy+aKKe2wu1vgEaTqYGGpKq976C+8nEZ1hqHzFTQgdsTIK +QUPGAw2LgtSPcB+jIvJoG8LHPum7n3/7lV3JeEXbDhMMrSX7emJ2KZ+qO5dSRMgT +PDtjeK33egEvXw24j1d4ZSef4smw87xmSNk1Fj+/AoGAOxIezvSqbw8CbamYNMTX +MS+9bUy79IlYcL/PSUETx+W3W/qfkIVJTDnX7PsSHsdRZLPWfePc6uveAzrGtb+B +3QFPWHs5zoVgjsjP584zfew5O9EvS7e/920OdAnIwYP0b2sGDtdGPiC3MHYcdsmV +RorW6vc7R0uVwmIgzUgPjgkCgYBImXD7RJ04Dc3I8Bh9vduB7LkJCHIcZeb54ksA +kUwfwEpDlo/03aM5NKy+n9dw04SXFoo0DKlHkAAGyq8/CLUdCSr6+YmbMISN1NzH +Vddj5Jj1R5RFjBdjek6OSvE23m5+9jagbJf2eEcsaZnBR61NhYNvY6pi+qlJobr4 +9knV7QKBgQDRC1lTIcONxZIWRQMhgIdiVjRL4jfITRmrgAUHnOTDqrDr6pzDmHGO +Js8jRQxq3h8mWHnF2P5HMI4QVmpQ8RuH9bJhycIKbPN0r/QsynsHJeVN/pvWe1ke +Z8U59I9XJnB0KEXRkGEZyftw5GDFX1EqEJBbR3iHojkWZB/SZ/65YQ== +-----END RSA PRIVATE KEY----- diff --git a/thrift/lib/cpp/test/ScopedEventBaseThread.h b/thrift/lib/cpp/test/ScopedEventBaseThread.h new file mode 100644 index 00000000..8736544d --- /dev/null +++ b/thrift/lib/cpp/test/ScopedEventBaseThread.h @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_SCOPEDEVENTBASETHREAD_H_ +#define THRIFT_TEST_SCOPEDEVENTBASETHREAD_H_ 1 + +#include +#include + +namespace apache { namespace thrift { namespace async { +class TEventBase; +}}} +namespace apache { namespace thrift { namespace concurrency { +class Thread; +}}} + +namespace apache { namespace thrift { namespace test { + +/** + * A helper class to start a new thread running a TEventBase loop. + * + * The new thread will be started by the ScopedEventBaseThread constructor. + * When the ScopedEventBaseThread object is destroyed, the thread will be + * stopped. + */ +class ScopedEventBaseThread { + public: + ScopedEventBaseThread(); + ~ScopedEventBaseThread(); + + ScopedEventBaseThread(ScopedEventBaseThread&& other); + ScopedEventBaseThread &operator=(ScopedEventBaseThread&& other); + + /** + * Get a pointer to the TEventBase driving this thread. + */ + async::TEventBase *getEventBase() const { + return eventBase_.get(); + } + + private: + ScopedEventBaseThread(const ScopedEventBaseThread& other) = delete; + ScopedEventBaseThread& operator=(const ScopedEventBaseThread& other) = delete; + + std::unique_ptr eventBase_; + boost::shared_ptr thread_; +}; + +}}} // apache::thrift::test + +#endif // THRIFT_TEST_SCOPEDEVENTBASETHREAD_H_ diff --git a/thrift/lib/cpp/test/SocketPair.h b/thrift/lib/cpp/test/SocketPair.h new file mode 100644 index 00000000..eebe534e --- /dev/null +++ b/thrift/lib/cpp/test/SocketPair.h @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_SOCKETPAIR_H_ +#define THRIFT_TEST_SOCKETPAIR_H_ 1 + +namespace apache { namespace thrift { namespace test { + +class SocketPair { + public: + enum Mode { + BLOCKING, + NONBLOCKING + }; + + SocketPair(Mode mode = NONBLOCKING); + ~SocketPair(); + + int operator[](int index) const { + return fds_[index]; + } + + void closeFD0(); + void closeFD1(); + + int extractFD0() { + return extractFD(0); + } + int extractFD1() { + return extractFD(1); + } + int extractFD(int index) { + int fd = fds_[index]; + fds_[index] = -1; + return fd; + } + + private: + int fds_[2]; +}; + +}}} // apache::thrift::test + +#endif // THRIFT_TEST_SOCKETPAIR_H_ diff --git a/thrift/lib/cpp/test/TimeUtil.h b/thrift/lib/cpp/test/TimeUtil.h new file mode 100644 index 00000000..d4f0fcd7 --- /dev/null +++ b/thrift/lib/cpp/test/TimeUtil.h @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_TIMEUTIL_H_ +#define THRIFT_TEST_TIMEUTIL_H_ 1 + +#include +#include + +namespace apache { namespace thrift { namespace test { + +class TimePoint { + public: + explicit TimePoint(bool set = true) + : timeStart_(0), + timeEnd_(0), + timeWaiting_(0), + tid_(0) { + if (set) { + reset(); + } + } + + void reset(); + + bool isUnset() const { + return (timeStart_ == 0 && timeEnd_ == 0 && timeWaiting_ == 0); + } + + int64_t getTime() const { + return timeStart_; + } + + int64_t getTimeStart() const { + return timeStart_; + } + + int64_t getTimeEnd() const { + return timeStart_; + } + + int64_t getTimeWaiting() const { + return timeWaiting_; + } + + pid_t getTid() const { + return tid_; + } + + private: + int64_t timeStart_; + int64_t timeEnd_; + int64_t timeWaiting_; + pid_t tid_; +}; + +std::ostream& operator<<(std::ostream& os, const TimePoint& timePoint); + +boost::test_tools::predicate_result checkTimeout(const TimePoint& start, + const TimePoint& end, + int64_t expectedMS, + bool allowSmaller, + int64_t tolerance = 5); + +/** + * Check how long a timeout took to fire. + * + * This method verifies: + * - that the timeout did not fire too early (never less than expectedMS) + * - that the timeout fired within a reasonable period of the expected + * duration. It must fire within the specified tolerance, excluding time + * that this process spent waiting to be scheduled. + * + * @param start A TimePoint object set just before the timeout + * was scheduled. + * @param end A TimePoint object set when the timeout fired. + * @param expectedMS The timeout duration, in milliseconds + * @param tolerance The tolerance, in milliseconds. + */ +#define T_CHECK_TIMEOUT(start, end, expectedMS, ...) \ + BOOST_CHECK(apache::thrift::test::checkTimeout((start), (end), \ + (expectedMS), false, \ + ##__VA_ARGS__)) + +/** + * Verify that an event took less than a specified amount of time. + * + * This is similar to T_CHECK_TIMEOUT, but does not fail if the event took less + * than the allowed time. + */ +#define T_CHECK_TIME_LT(start, end, expectedMS, ...) \ + BOOST_CHECK(apache::thrift::test::checkTimeout((start), (end), \ + (expectedMS), true, \ + ##__VA_ARGS__)) + +}}} // apache::thrift::test + +#endif // THRIFT_TEST_TIMEUTIL_H_ diff --git a/thrift/lib/cpp/test/checks.h b/thrift/lib/cpp/test/checks.h new file mode 100644 index 00000000..4ee07f5d --- /dev/null +++ b/thrift/lib/cpp/test/checks.h @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_TEST_CHECKS_H_ +#define THRIFT_TEST_CHECKS_H_ 1 + +#include +#include "common/logging/logging.h" +#include "thrift/lib/cpp/protocol/TDebugProtocol.h" + + +namespace apache { namespace thrift { namespace test { + +template +inline std::string* formatString(const T1& v1, const T2& v2, + const std::string& op) { + std::stringstream ss; + ss << ThriftDebugString(v1) << " "<< op <<" " << ThriftDebugString(v2); + return new std::string(ss.str()); +} + +template +inline std::string* checkThriftEqImpl(const T1& val1, const T2& val2) +{ + if (val1 == val2) { + return NULL; + } + return formatString(val1, val2, "=="); +} + +template +inline std::string* checkThriftNeImpl(const T1& val1, const T2& val2) +{ + if (val1 != val2) { + return NULL; + } + return formatString(val1, val2, "!="); +} + +template +inline std::string* checkThriftLeImpl(const T1& val1, const T2& val2) +{ + if (val1 <= val2) { + return NULL; + } + return formatString(val1, val2, "<="); +} + +template +inline std::string* checkThriftLtImpl(const T1& val1, const T2& val2) { + + if (val1 < val2) { + return NULL; + } + return formatString(val1, val2, "<"); +} + +template +inline std::string* checkThriftGeImpl(const T1& val1, const T2& val2) +{ + if (val1 >= val2) { + return NULL; + } + return formatString(val1, val2, ">="); +} + +template +inline std::string* checkThriftGtImpl(const T1& val1, const T2& val2) +{ + if (val1 > val2) { + return NULL; + } + return formatString(val1, val2, ">"); +} + +}}} + +#define THRIFT_CHECK_OP(name, val1, val2) \ + while (std::string* _checkResult = \ + apache::thrift::test::checkThrift##name##Impl((val1), (val2))) \ + google::LogMessageFatal(__FILE__, __LINE__, \ + google::CheckOpString(_checkResult)).stream() + +#define THRIFT_CHECK_EQ(val1, val2) THRIFT_CHECK_OP(Eq, val1, val2) +#define THRIFT_CHECK_NE(val1, val2) THRIFT_CHECK_OP(Ne, val1, val2) +#define THRIFT_CHECK_LE(val1, val2) THRIFT_CHECK_OP(Le, val1, val2) +#define THRIFT_CHECK_LT(val1, val2) THRIFT_CHECK_OP(Lt, val1, val2) +#define THRIFT_CHECK_GE(val1, val2) THRIFT_CHECK_OP(Ge, val1, val2) +#define THRIFT_CHECK_GT(val1, val2) THRIFT_CHECK_OP(Gt, val1, val2) + +#endif diff --git a/thrift/lib/cpp/test/loadgen/Controller.h b/thrift/lib/cpp/test/loadgen/Controller.h new file mode 100644 index 00000000..84805664 --- /dev/null +++ b/thrift/lib/cpp/test/loadgen/Controller.h @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_LOADGEN_CONTROLLER_H_ +#define THRIFT_TEST_LOADGEN_CONTROLLER_H_ 1 + +#include + +#include "thrift/lib/cpp/concurrency/Monitor.h" +#include "thrift/lib/cpp/test/loadgen/LoadConfig.h" +#include "thrift/lib/cpp/test/loadgen/IntervalTimer.h" + +namespace apache { namespace thrift { + +namespace concurrency { + +class PosixThreadFactory; + +} // apache::thrift::concurrency + +namespace loadgen { + +class WorkerFactory; +class WorkerIf; +class Monitor; + +class Controller : private boost::noncopyable { + public: + Controller(WorkerFactory* factory, Monitor* monitor, + boost::shared_ptr config, + apache::thrift::concurrency::PosixThreadFactory* threadFactory = NULL); + + void run(uint32_t numThreads, double monitorInterval = 1.0); + + private: + class WorkerRunner; + typedef std::vector< boost::shared_ptr > WorkerVector; + + void startWorkers(uint32_t numThreads); + void runMonitor(double interval); + boost::shared_ptr createWorker(); + + concurrency::Monitor initMonitor_; + uint32_t numThreads_; + WorkerFactory* workerFactory_; + Monitor* monitor_; + WorkerVector workers_; + IntervalTimer intervalTimer_; + boost::shared_ptr config_; + apache::thrift::concurrency::PosixThreadFactory* threadFactory_; +}; + +}}} // apache::thrift::loadgen + +#endif // THRIFT_TEST_LOADGEN_CONTROLLER_H_ diff --git a/thrift/lib/cpp/test/loadgen/IntervalTimer.h b/thrift/lib/cpp/test/loadgen/IntervalTimer.h new file mode 100644 index 00000000..92924a07 --- /dev/null +++ b/thrift/lib/cpp/test/loadgen/IntervalTimer.h @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_LOADGEN_INTERVALTIMER_H_ +#define THRIFT_TEST_LOADGEN_INTERVALTIMER_H_ 1 + +#include "thrift/lib/cpp/concurrency/Util.h" +#include "thrift/lib/cpp/concurrency/Mutex.h" +#include "thrift/lib/cpp/TLogging.h" + +#include + +namespace apache { namespace thrift { namespace loadgen { + +/** + * IntervalTimer helps perform tasks at a desired rate. + * + * Call sleep() in between each operation, and it will sleep the required + * amount of time to hit the target rate. It accounts for the time required to + * perform each operation, and it also adjusts the subsequent intervals if the + * system sleep call wakes up later than requested. This allows good accuracy + * for the average rate, even when the requested interval is very small. Works + * between multiple threads. + */ +class IntervalTimer { + public: + /** + * Create a new IntervalTimer + * + * @param intervalNsec The desired number of ns each interval should take. + * @param maxBacklog If we can't keep up with the requested rate, reset + * when we fall more than maxBacklog microseconds + * behind. If the rate does eventually recover, this + * will setting helps reduce the amount of time that the + * timer goes too fast in order to catch up to the + * average rate. + */ + IntervalTimer(uint64_t intervalNsec, + uint64_t maxBacklog = 3 * concurrency::Util::US_PER_S) + : numTimes_(0) + , intervalNsec_(intervalNsec) + , intervalStart_(0) + , maxBacklog_(maxBacklog) { } + + void setIntervalNsec(uint64_t interval) { + intervalNsec_ = interval; + } + + void setRatePerSec(uint64_t rate) { + if (rate == 0) intervalNsec_ = 0; + else intervalNsec_ = concurrency::Util::NS_PER_S / rate; + } + + /** + * Start the timer. + * + * Call this method before the first interval. + */ + void start() { + intervalStart_ = concurrency::Util::currentTimeUsec(); + } + + /** + * Sleep until the next interval should start. + * + * @return Returns true during normal operations, and false if the maxBacklog + * was hit and the timer has reset the average rate calculation. + */ + bool sleep() { + // Go as fast as possible when intervalNsec_ is 0 + if (intervalNsec_ == 0) { + return true; + } + + + uint64_t waitUntil, now; + { + concurrency::Guard guard(mutex_); + + // intervalStart_ is when the just previous interval started (or when it + // was supposed to start, if we aren't able to keep up with the requested + // rate). + // + // Update it to be when the next interval is supposed to start + numTimes_++; + now = concurrency::Util::currentTimeUsec(); + + waitUntil = intervalStart_ + (intervalNsec_ * numTimes_) / 1000; + + if (now > waitUntil) { + // If we can't keep up with the requested rate, we'll keep falling + // farther and farther behind. + // + // If we fall farther than maxBacklog_ behind, reset intervalStart_ to + // the current time. This way, if the operations eventually do speed up + // and we are able to meet the requested rate, we won't exceed it for + // too long trying to catch up. + uint64_t delta = now - waitUntil; + if (delta > maxBacklog_) { + intervalStart_ = now; + numTimes_ = 0; + return false; + } + return true; + } + } + + usleep(waitUntil - now); + return true; + } + + private: + uint64_t numTimes_; + uint64_t intervalNsec_; + uint64_t intervalStart_; + uint64_t maxBacklog_; + concurrency::Mutex mutex_; +}; + +}}} // apache::thrift::loadgen + +#endif // THRIFT_TEST_LOADGEN_INTERVALTIMER_H_ diff --git a/thrift/lib/cpp/test/loadgen/LatencyMonitor.h b/thrift/lib/cpp/test/loadgen/LatencyMonitor.h new file mode 100644 index 00000000..5d6d9522 --- /dev/null +++ b/thrift/lib/cpp/test/loadgen/LatencyMonitor.h @@ -0,0 +1,129 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_LOADGEN_LATENCYMONITOR_H_ +#define THRIFT_TEST_LOADGEN_LATENCYMONITOR_H_ 1 + +#include "thrift/lib/cpp/test/loadgen/TerminalMonitor.h" +#include "thrift/lib/cpp/test/loadgen/OpEnabledState.h" +#include "thrift/lib/cpp/test/loadgen/LatencyScoreBoard.h" + +namespace apache { namespace thrift { namespace loadgen { + +class LoadConfig; + +/** + * A Monitor implementation that prints QPS rates and latency information for + * all operations. + */ +class LatencyMonitor : public TerminalMonitor { + public: + /// The various fields that LatencyMonitor knows how to print + enum FieldEnum { + FIELD_COUNT, + FIELD_QPS, + FIELD_LATENCY, + FIELD_ALL_TIME_COUNT, + FIELD_ALL_TIME_QPS, + FIELD_ALL_TIME_LATENCY, + }; + + struct FieldInfo { + FieldInfo(FieldEnum f, int w = -1) + : field(f) + , width(w) + , dynamicWidth(true) {} + + FieldEnum field; + int width; + bool dynamicWidth; + }; + + typedef std::vector FieldInfoVector; + + LatencyMonitor(const boost::shared_ptr& config); + + /** + * Set the fields printed for the specified operation. + */ + void setFields(uint32_t opType, const FieldInfoVector* fields); + + /** + * Set the fields printed for aggregate statistics for all operations. + */ + void setTotalFields(const FieldInfoVector* fields); + + virtual boost::shared_ptr newScoreBoard(int id); + + virtual void initializeInfo(); + virtual uint32_t printHeader(); + virtual uint32_t printInfo(uint64_t intervalUsec); + + private: + typedef std::vector< boost::shared_ptr > ScoreBoardVector; + + void printOpHeader(FieldInfoVector* fields); + void printOpInfo(FieldInfoVector* fields, + const LatencyScoreBoard::OpData* current, + const LatencyScoreBoard::OpData* prev, + const LatencyScoreBoard::OpData* initial, + uint64_t intervalUsec, + uint64_t allTimeUsec); + + uint32_t getFieldVectorWidth(const FieldInfoVector* fields) const; + const char *getFieldName(FieldEnum field) const; + uint32_t getDefaultFieldWidth(FieldEnum field) const; + + void formatFieldValue(FieldEnum field, + char* buf, + size_t buflen, + const LatencyScoreBoard::OpData* current, + const LatencyScoreBoard::OpData* prev, + const LatencyScoreBoard::OpData* initial, + uint64_t intervalUsec, + uint64_t allTimeUsec); + void formatLatency(char* buf, size_t buflen, double avg, double stddev); + + void aggregateWorkerScorboards(LatencyScoreBoard* scoreboard); + void printField(const char* value, int width); + void printField(const char* value, FieldInfo* fieldInfo); + + void setDefaultOpFields(); + void printLegend(); + bool isFieldInUse(FieldEnum field); + + uint32_t numOpTypes_; + + /// The list of fields to print for each operation + std::vector opFields_; + /// The fields to print for the aggregate information over all operations + FieldInfoVector totalFields_; + + int64_t initialTime_; + LatencyScoreBoard initialScoreBoard_; + + /// A scoreboard with information aggregated across all of the workers + LatencyScoreBoard aggregateScoreBoard_; + /// A vector of the actual scoreboards used by the workers + ScoreBoardVector scoreboards_; + boost::shared_ptr config_; +}; + +}}} // apache::thrift::loadgen + +#endif // THRIFT_TEST_LOADGEN_LATENCYMONITOR_H_ diff --git a/thrift/lib/cpp/test/loadgen/LatencyScoreBoard.h b/thrift/lib/cpp/test/loadgen/LatencyScoreBoard.h new file mode 100644 index 00000000..08037a82 --- /dev/null +++ b/thrift/lib/cpp/test/loadgen/LatencyScoreBoard.h @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_LOADGEN_LATENCYSCOREBOARD_H_ +#define THRIFT_TEST_LOADGEN_LATENCYSCOREBOARD_H_ 1 + +#include "thrift/lib/cpp/test/loadgen/ScoreBoard.h" +#include "thrift/lib/cpp/test/loadgen/ScoreBoardOpVector.h" + +namespace apache { namespace thrift { namespace loadgen { + +/** + * A ScoreBoard that tracks number of queries per second, as well as + * information about how long each operation takes. + * + * This ScoreBoard calls gettimeofday() twice for each operation, so it does + * add a small amount of overhead. If you have extremely high performance + * requirements, you could use QpsScoreBoard to track just the QPS rate and + * eliminate the gettimeofday() calls. + */ +class LatencyScoreBoard : public ScoreBoard { + public: + class OpData { + public: + OpData(); + + void addDataPoint(uint64_t latencyUsecs); + + void zero(); + void accumulate(const OpData* other); + + uint64_t getCount() const; + uint64_t getCountSince(const OpData* other) const; + double getLatencyAvg() const; + double getLatencyAvgSince(const OpData* other) const; + double getLatencyStdDev() const; + double getLatencyStdDevSince(const OpData* other) const; + + uint64_t count_; + uint64_t usecSum_; + uint64_t sumOfSquares_; + }; + + LatencyScoreBoard(uint32_t numOpsHint) + : startTime_(0) + , opData_(numOpsHint) {} + + virtual void opStarted(uint32_t opType); + virtual void opSucceeded(uint32_t opType); + virtual void opFailed(uint32_t opType); + + /** + * Get the OpData for a particular operation type + */ + const OpData* getOpData(uint32_t opType); + + /** + * Compute an OpData object with aggregate information over all operation + * types. + * + * @param result A pointer to the OpData object to fill in with aggregate + * information. + */ + void computeOpAggregate(OpData* result) const; + + /** + * Zero out the statistics. + */ + void zero(); + + /** + * Add the counters from another scoreboard to this one. + */ + void accumulate(const LatencyScoreBoard* other); + + private: + int64_t startTime_; + ScoreBoardOpVector opData_; +}; + +}}} // apache::thrift::loadgen + +#endif // THRIFT_TEST_LOADGEN_LATENCYSCOREBOARD_H_ diff --git a/thrift/lib/cpp/test/loadgen/LoadConfig.h b/thrift/lib/cpp/test/loadgen/LoadConfig.h new file mode 100644 index 00000000..90e2995d --- /dev/null +++ b/thrift/lib/cpp/test/loadgen/LoadConfig.h @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_LOADGEN_LOADCONFIG_H_ +#define THRIFT_TEST_LOADGEN_LOADCONFIG_H_ 1 + +#include +#include +#include + +namespace apache { namespace thrift { namespace loadgen { + +class LoadConfig { + public: + virtual ~LoadConfig() {} + + virtual uint32_t getNumOpTypes() const = 0; + + virtual uint32_t pickOpType() = 0; + virtual uint32_t pickOpsPerConnection() = 0; + + /** + * Return a human-readable name for an operation type. + * + * By default, just converts the integer value to a string, but this may be + * overridden by subclasses. + */ + virtual std::string getOpName(uint32_t opType); + + /** + * Get the number of worker threads to run. + */ + virtual uint32_t getNumWorkerThreads() const = 0; + + /** + * Get the desired number of queries per second. + * + * The workers should attempt to perform only this many operations per + * second. (It is possible that they will perform less than this if they + * cannot drive the requested qps rate.) + * + * @return Return the desired qps rate, or 0 if operations should be + * performed as fast as possible. + */ + virtual uint64_t getDesiredQPS() const { + return 0; + } +}; + +}}} // apache::thrift::loadgen + +#endif // THRIFT_TEST_LOADGEN_LOADCONFIG_H_ diff --git a/thrift/lib/cpp/test/loadgen/Monitor.h b/thrift/lib/cpp/test/loadgen/Monitor.h new file mode 100644 index 00000000..418a9701 --- /dev/null +++ b/thrift/lib/cpp/test/loadgen/Monitor.h @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_LOADGEN_MONITOR_H_ +#define THRIFT_TEST_LOADGEN_MONITOR_H_ 1 + +#include +#include +#include + +namespace apache { namespace thrift { namespace loadgen { + +class ScoreBoard; + +class Monitor { + public: + Monitor() {} + virtual ~Monitor() {} + + /** + * Create a new ScoreBoard object. + * + * This method will be called once for each worker thread. All calls to + * newScoreBoard() will be made before run() is invoked. + * + * For each Worker, newScoreBoard() will be called in the thread that will + * run that worker. However, the caller holds a lock and ensures that it + * will only be called in one thread at a time, so newScoreBoard() doesn't + * need to perform any locking internally. + * + * @param id The id of the Worker that will use this ScoreBoard. + */ + virtual boost::shared_ptr newScoreBoard(int id) = 0; + + /** + * Initialize monitoring information. + * + * This method is called once when the workers start, just before the initial + * monitoring interval. It can be used to get initial counter values from + * all of the Workers, so that statistics reported in the first call to + * redisplay() are accurate. + */ + virtual void initializeInfo() {} + + /** + * Redisplay the monitor information. + * + * @param intervalUsec The number of microseconds since the last call to + * redisplay() or initializeInfo(). + */ + virtual void redisplay(uint64_t intervalUsec) = 0; +}; + +}}} // apache::thrift::loadgen + +#endif // THRIFT_TEST_LOADGEN_MONITOR_H_ diff --git a/thrift/lib/cpp/test/loadgen/OpEnabledState.h b/thrift/lib/cpp/test/loadgen/OpEnabledState.h new file mode 100644 index 00000000..5e834d9d --- /dev/null +++ b/thrift/lib/cpp/test/loadgen/OpEnabledState.h @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_LOADGEN_OPENABLEDSTATE_H_ +#define THRIFT_TEST_LOADGEN_OPENABLEDSTATE_H_ 1 + +#include + +namespace apache { namespace thrift { namespace loadgen { + +/** + * This class tracks a boolean for each operation type, to tell if an operation + * is enabled or not. + * + * This is mainly intended to be used by Monitor implementations, so they can + * avoid monitoring (or at least printing) information for operations that are + * disabled. + */ +class OpEnabledState { + public: + OpEnabledState(uint32_t numOpTypes) { + enabled_.resize(numOpTypes, true); + } + + void setEnabled(uint32_t opType, bool enabled) { + assert(opType < enabled_.size()); + enabled_[opType] = enabled; + } + + void setAllOpsEnabled(bool enabled) { + for (std::vector::iterator it = enabled_.begin(); + it != enabled_.end(); + ++it) { + *it = enabled; + } + } + + bool isEnabled(uint32_t opType) const { + assert(opType < enabled_.size()); + return enabled_[opType]; + } + + uint32_t getNumEnabled() const { + uint32_t num = 0; + for (std::vector::const_iterator it = enabled_.begin(); + it != enabled_.end(); + ++it) { + if (*it) { + ++num; + } + } + + return num; + } + + private: + std::vector enabled_; +}; + +}}} // apache::thrift::loadgen + +#endif // THRIFT_TEST_LOADGEN_OPENABLEDSTATE_H_ diff --git a/thrift/lib/cpp/test/loadgen/QpsMonitor.h b/thrift/lib/cpp/test/loadgen/QpsMonitor.h new file mode 100644 index 00000000..e4e11dfd --- /dev/null +++ b/thrift/lib/cpp/test/loadgen/QpsMonitor.h @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_LOADGEN_QPSMONITOR_H_ +#define THRIFT_TEST_LOADGEN_QPSMONITOR_H_ 1 + +#include "thrift/lib/cpp/test/loadgen/TerminalMonitor.h" +#include "thrift/lib/cpp/test/loadgen/OpEnabledState.h" +#include "thrift/lib/cpp/test/loadgen/QpsScoreBoard.h" + +namespace apache { namespace thrift { namespace loadgen { + +class LoadConfig; + +/** + * A Monitor implementation that prints QPS rates for all operations. + */ +class QpsMonitor : public TerminalMonitor { + public: + QpsMonitor(const boost::shared_ptr& config); + + virtual boost::shared_ptr newScoreBoard(int id); + + virtual void initializeInfo(); + virtual uint32_t printHeader(); + virtual uint32_t printInfo(uint64_t intervalUsec); + + OpEnabledState* getEnabledState() { + return &enabledState_; + } + + const OpEnabledState* getEnabledState() const { + return &enabledState_; + } + + void printAllTimeQps(bool enabled) { + printAllTime_ = enabled; + } + + private: + typedef std::vector< boost::shared_ptr > ScoreBoardVector; + + void computeAggregate(QpsScoreBoard* scoreboard); + + int64_t initialTime_; + uint64_t initialSum_; + + bool printAllTime_; + OpEnabledState enabledState_; + + QpsScoreBoard aggregateScoreBoard_; + ScoreBoardVector scoreboards_; + boost::shared_ptr config_; +}; + +}}} // apache::thrift::loadgen + +#endif // THRIFT_TEST_LOADGEN_QPSMONITOR_H_ diff --git a/thrift/lib/cpp/test/loadgen/QpsScoreBoard.h b/thrift/lib/cpp/test/loadgen/QpsScoreBoard.h new file mode 100644 index 00000000..39ed6cb4 --- /dev/null +++ b/thrift/lib/cpp/test/loadgen/QpsScoreBoard.h @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_LOADGEN_QPSSCOREBOARD_H_ +#define THRIFT_TEST_LOADGEN_QPSSCOREBOARD_H_ 1 + +#include "thrift/lib/cpp/test/loadgen/ScoreBoard.h" +#include "thrift/lib/cpp/test/loadgen/ScoreBoardOpVector.h" + +namespace apache { namespace thrift { namespace loadgen { + +/** + * A ScoreBoard that tracks number of queries per second. + * + * This is a very simple scoreboard, that adds very little overhead. + */ +class QpsScoreBoard : public ScoreBoard { + public: + QpsScoreBoard(uint32_t numOpsHint) : opData_(numOpsHint) {} + + virtual void opStarted(uint32_t opType); + virtual void opSucceeded(uint32_t opType); + virtual void opFailed(uint32_t opType); + + /** + * Get the number of operations performed for a specific operation type. + */ + uint64_t getCount(uint32_t opType) const; + + /** + * Compute the total number of operations performed, for all operation types. + */ + uint64_t computeTotalCount() const; + + /** + * Zero out the statistics. + */ + void zero(); + + /** + * Add the counters from another scoreboard to this one. + */ + void accumulate(const QpsScoreBoard* other); + + private: + struct OpData { + OpData() : count(0) {} + + void zero() { + count = 0; + } + + void accumulate(const OpData* other) { + count += other->count; + } + + uint64_t count; + }; + + ScoreBoardOpVector opData_; +}; + +}}} // apache::thrift::loadgen + +#endif // THRIFT_TEST_LOADGEN_QPSSCOREBOARD_H_ diff --git a/thrift/lib/cpp/test/loadgen/RNG.h b/thrift/lib/cpp/test/loadgen/RNG.h new file mode 100644 index 00000000..fb910565 --- /dev/null +++ b/thrift/lib/cpp/test/loadgen/RNG.h @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_LOADGEN_RNG_H_ +#define THRIFT_TEST_LOADGEN_RNG_H_ 1 + +#include + +namespace apache { namespace thrift { namespace loadgen { + +/** + * A random number generator to use for load tests. + * + * We keep one RNG per thread, to avoid having to perform locking when getting + * random numbers. + * + * RNG also implements the boost random number generator interface, so it can + * be used as an engine for boost random distributions. + * + * + * This class is essentially just a wrapper around boost::mt19937. + * We have to wrap it because some of the boost code copy-constructs the + * generators, causing the state of the original generator to never be updated. + * (In particular uniform_01 copy constructs its generator argument, and + * variate_generator may end up using uniform_01.) + * + * It's rather annoying that we have to define our own wrapper class for this. + */ +class RNG { + public: + // Use boost::mt19937 as the underlying RNG + typedef boost::mt19937 BoostRNG; + + // result_type and has_fixed_range are required for the boost interfaces + typedef BoostRNG::result_type result_type; + static const bool has_fixed_range = false; + + RNG(BoostRNG* rng) : rng_(rng) {} + + /** + * Get the thread-local RNG. + */ + static RNG& getRNG(); + + /** + * Set the RNG seed. + * + * This value is used to pick seeds for new thread-local RNGs. + * It won't affect thread-local RNGs that have already been created. + * + * Note that that the seed value used for each thread-local RNG depends on + * the order in which the thread-local RNGs are created. You may not get + * consistent results across runs if your threads are not initialized in a + * consistent order. + */ + static void setGlobalSeed(result_type s); + + /** + * Re-seed this RNG + */ + void seed(result_type s) { + rng_->seed(s); + } + + /** + * Get a random number. + * + * Part of the boost random generator interface. + */ + result_type operator()() { + return (*rng_)(); + } + + /** + * Get the minimum value that can be returned. + * + * Part of the boost random generator interface. + */ + result_type min() const { + return rng_->min(); + } + + /** + * Get the maximum value that can be returned. + * + * Part of the boost random generator interface. + */ + result_type max() const { + return rng_->max(); + } + + /* + * Helper functions to pick random uint32_t values + */ + static uint32_t getU32(); + static uint32_t getU32(uint32_t max); + static uint32_t getU32(uint32_t min, uint32_t max); + + /** + * Helper function to pick random double values in the range [0.0, 1.0) + */ + static double getReal(); + + /** + * Helper function to pick random double values in the range [min, max) + */ + static double getReal(double min, double max); + + /** + * Helper function to pick random values in a log-normal distribution. + * + * @param mean The mean value for the log-normal distribution. + * @param sigma The sigma value for the log-normal distribution. + * (This controls how spread-out the distribution will be.) + * If negative, defaults to half the mean. + */ + static double getLogNormal(double mean, double sigma = -1.0); + + private: + BoostRNG* rng_; +}; + +}}} // apache::thrift::test + +#endif // THRIFT_TEST_LOADGEN_RNG_H_ diff --git a/thrift/lib/cpp/test/loadgen/ScoreBoard.h b/thrift/lib/cpp/test/loadgen/ScoreBoard.h new file mode 100644 index 00000000..fd5cd333 --- /dev/null +++ b/thrift/lib/cpp/test/loadgen/ScoreBoard.h @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_LOADGEN_SCOREBOARD_H_ +#define THRIFT_TEST_LOADGEN_SCOREBOARD_H_ 1 + +#include + +namespace apache { namespace thrift { namespace loadgen { + +/** + * A ScoreBoard object keeps statistics for a Worker. + * + * There is intended to be one ScoreBoard object per Worker, so that it doesn't + * need to perform locking when recording statistics. + * + * The Monitor object is responsible for aggregating the statistics from the + * various ScoreBoards. + */ +class ScoreBoard { + public: + virtual ~ScoreBoard() {} + + /** + * opStarted() is invoked just before each call to + * Worker::performOperation(). + */ + virtual void opStarted(uint32_t opType) = 0; + + /** + * opSucceeded() is invoked after each successful call to + * Worker::performOperation(). + */ + virtual void opSucceeded(uint32_t opType) = 0; + + /** + * opFailed() is invoked if Worker::performOperation() throws an exception. + */ + virtual void opFailed(uint32_t opType) = 0; +}; + +}}} // apache::thrift::loadgen + +#endif // THRIFT_TEST_LOADGEN_SCOREBOARD_H_ diff --git a/thrift/lib/cpp/test/loadgen/ScoreBoardOpVector.h b/thrift/lib/cpp/test/loadgen/ScoreBoardOpVector.h new file mode 100644 index 00000000..1935a846 --- /dev/null +++ b/thrift/lib/cpp/test/loadgen/ScoreBoardOpVector.h @@ -0,0 +1,127 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_LOADGEN_SCOREBOARDOPVECTOR_H_ +#define THRIFT_TEST_LOADGEN_SCOREBOARDOPVECTOR_H_ 1 + +#include "thrift/lib/cpp/test/loadgen/ScoreBoard.h" + +#include +#include +#include + +namespace apache { namespace thrift { namespace loadgen { + +/** + * A vector of per-operation scoreboard data. + * + * This is useful for implementing ScoreBoard classes. + * + * The OpDataT class must have: + * - a default constructor + * - a zero() method + * - an accumulate() method + */ +template +class ScoreBoardOpVector { + private: + typedef std::vector DataVector; + + public: + typedef typename DataVector::iterator Iterator; + typedef typename DataVector::const_iterator ConstIterator; + + ScoreBoardOpVector(uint32_t numOpsHint) { + resize(numOpsHint); + } + + OpDataT* getOpData(uint32_t opType) { + if (opType >= opData_.size()) { + resize(opType + 1); + } + return &opData_[opType]; + } + + const OpDataT* getOpDataOrNull(uint32_t opType) const { + if (opType >= opData_.size()) { + return NULL; + } + return &opData_[opType]; + } + + void zero() { + for (Iterator it = opData_.begin(); it != opData_.end(); ++it) { + it->zero(); + } + } + + void accumulate(const ScoreBoardOpVector* other) { + if (other->opData_.size() > opData_.size()) { + resize(other->opData_.size()); + } + + uint32_t index = 0; + for (ConstIterator it = other->opData_.begin(); + it != other->opData_.end(); + ++it, ++index) { + opData_[index].accumulate(&(*it)); + } + } + + void accumulateOverOps(OpDataT* result) const { + result->zero(); + for (ConstIterator it = opData_.begin(); it != opData_.end(); ++it) { + result->accumulate(&(*it)); + } + } + + Iterator begin() { + return opData_.begin(); + } + Iterator end() { + return opData_.end(); + } + + ConstIterator begin() const { + return opData_.begin(); + } + ConstIterator end() const { + return opData_.end(); + } + + private: + void resize(uint32_t numOps) { + assert(numOps > opData_.size()); + + // We could add some padding here. In the past, when using glibc malloc + // with QpsScoreBoard and just 1 operation, I've seen the opData for two + // different worker threads end up being allocated on the same cache line. + // This hurts peformance, since the two worker threads run on different + // CPUs and they each keep evicting the cache line from the other CPU. + // With jemalloc this doesn't seem to happen anymore, and allocating more + // space then necessary here can very slightly slow down performance. + + opData_.resize(numOps); + } + + DataVector opData_; +}; + +}}} // apache::thrift::loadgen + +#endif // THRIFT_TEST_LOADGEN_SCOREBOARDOPVECTOR_H_ diff --git a/thrift/lib/cpp/test/loadgen/TerminalMonitor.h b/thrift/lib/cpp/test/loadgen/TerminalMonitor.h new file mode 100644 index 00000000..f06847db --- /dev/null +++ b/thrift/lib/cpp/test/loadgen/TerminalMonitor.h @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_LOADGEN_TERMINALMONITOR_H_ +#define THRIFT_TEST_LOADGEN_TERMINALMONITOR_H_ 1 + +#include "thrift/lib/cpp/test/loadgen/Monitor.h" + +namespace apache { namespace thrift { namespace loadgen { + +/** + * A Monitor object that prints statistics to a terminal. + * + * It handles printing header lines, and re-printing the header whenever it + * scrolls off of the screen. + */ +class TerminalMonitor : public Monitor { + public: + TerminalMonitor(); + + virtual void redisplay(uint64_t intervalUsec); + + /** + * Initialize monitoring information. + * + * This method is called immediately after all of the Workers have started, + * just before the initial monitoring interval. It can be used to get + * initial counter values from all of the Workers, so that statistics + * reported in the first call to printInfo() are accurate. + * + * If subclasses override initializeInfo(), they should make sure to call + * TerminalMonitor::initializeInfo() in their method. + */ + virtual void initializeInfo(); + + /** + * Print header lines. + * + * This is called when monitoring first starts. If the screen height can + * be determined, this is also called every time the previous header scrolls + * off the screen. + * + * @return Returns the number of lines printed. + */ + virtual uint32_t printHeader() = 0; + + /** + * Print monitoring information. + * + * This is called once every specified interval. + * + * @param intervalUsec The number of microseconds since the previous call to + * printInfo(). The first time printInfo() is called, + * this is the number of microseconds since + * initializeInfo() was called. + * + * @return Returns the number of lines printed. + */ + virtual uint32_t printInfo(uint64_t intervalUsec) = 0; + + protected: + int32_t getScreenHeight(); + + int32_t screenHeight_; + uint32_t linesPrinted_; +}; + +}}} // apache::thrift::loadgen + +#endif // THRIFT_TEST_LOADGEN_TERMINALMONITOR_H_ diff --git a/thrift/lib/cpp/test/loadgen/WeightedLoadConfig.h b/thrift/lib/cpp/test/loadgen/WeightedLoadConfig.h new file mode 100644 index 00000000..b76522d7 --- /dev/null +++ b/thrift/lib/cpp/test/loadgen/WeightedLoadConfig.h @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_LOADGEN_WEIGHTEDLOADCONFIG_H_ +#define THRIFT_TEST_LOADGEN_WEIGHTEDLOADCONFIG_H_ 1 + +#include "thrift/lib/cpp/test/loadgen/LoadConfig.h" + +#include +#include + +namespace apache { namespace thrift { namespace loadgen { + +class OpEnabledState; + +class WeightedLoadConfig : public LoadConfig { + public: + WeightedLoadConfig(uint32_t numOps); + + void setOpInfo(uint32_t opType, + const std::string& name, + uint32_t weight); + uint32_t getOpWeight(uint32_t opType); + + virtual uint32_t getNumOpTypes() const; + virtual uint32_t pickOpType(); + virtual uint32_t pickOpsPerConnection() = 0; + + virtual std::string getOpName(uint32_t opType); + + /** + * Update an OpEnabledState object to enable only operations that have a + * non-zero weight. + */ + virtual void configureEnabledState(OpEnabledState* enabledState) const; + + private: + uint32_t weightsSum_; + std::vector weights_; + std::vector names_; +}; + +}}} // apache::thrift::loadgen + +#endif // THRIFT_TEST_LOADGEN_WEIGHTEDLOADCONFIG_H_ diff --git a/thrift/lib/cpp/test/loadgen/Worker.h b/thrift/lib/cpp/test/loadgen/Worker.h new file mode 100644 index 00000000..04db52fa --- /dev/null +++ b/thrift/lib/cpp/test/loadgen/Worker.h @@ -0,0 +1,275 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_LOADGEN_WORKER_H_ +#define THRIFT_TEST_LOADGEN_WORKER_H_ 1 + +#include "thrift/lib/cpp/test/loadgen/WorkerIf.h" + +#include "thrift/lib/cpp/test/loadgen/IntervalTimer.h" +#include "thrift/lib/cpp/test/loadgen/LoadConfig.h" +#include "thrift/lib/cpp/test/loadgen/ScoreBoard.h" +#include "thrift/lib/cpp/concurrency/Util.h" +#include "thrift/lib/cpp/TLogging.h" + +#include +#include + +namespace apache { namespace thrift { namespace loadgen { + +/** + * Main Worker implementation + * + * If you are implementing a new load generator, you should define your own + * subclass of Worker, and implement the createConnection() and + * performOperation() methods. + * + * This is templatized on the client type. + * + * The Config type is also templatized for convenience. This allows + * subclasses to store their own more-specific configuration type that derives + * from LoadConfig. + */ +template +class Worker : public WorkerIf, public boost::noncopyable { + public: + typedef ClientT ClientType; + typedef ConfigT ConfigType; + + enum ErrorAction { + EA_CONTINUE, + EA_NEXT_CONNECTION, + EA_DROP_THREAD, + EA_ABORT + }; + + Worker() + : id_(-1) + , alive_(false) + , intervalTimer_(NULL) + , config_() + , scoreboard_() {} + + /** + * Initialize the Worker. + * + * This is separate from the constructor so that developers writing new + * Worker implementations don't have to pass through additional constructor + * arguments. If the subclass doesn't need any special initialization, they + * can just use the default constructor. + * + * If a Worker implementation does need to perform additional implementation- + * specific initialization after the config object has been set, it can + * override init(). + */ + void init(int id, + const boost::shared_ptr& config, + const boost::shared_ptr& scoreboard, + IntervalTimer* itimer) { + assert(id_ == -1); + assert(!config_); + id_ = id; + config_ = config; + scoreboard_ = scoreboard; + intervalTimer_ = itimer; + alive_ = true; + } + + virtual ~Worker() {} + + int getID() const { + return id_; + } + + /** + * Create a new connection to the server. + * + * Subclasses must implement this method. + */ + virtual boost::shared_ptr createConnection() = 0; + + /** + * Perform an operation on a connection. + * + * Subclasses must implement this method. + */ + virtual void performOperation(const boost::shared_ptr& client, + uint32_t opType) = 0; + + /** + * Determine how to handle an exception raised by createConnection(). + * + * The default behavior is to log an error message and abort. + * Subclasses may override this function to provide alternate behavior. + */ + virtual ErrorAction handleConnError(const std::exception& ex) { + T_ERROR("worker %d caught %s exception while connecting: %s", + id_, typeid(ex).name(), ex.what()); + return EA_ABORT; + } + + /** + * Determine how to handle an exception raised by performOperation(). + * + * The default behavior is to log an error message and continue processing on + * a new connection. Subclasses may override this function to provide + * alternate behavior. + */ + virtual ErrorAction handleOpError(uint32_t opType, const std::exception& ex) { + T_ERROR("worker %d caught %s exception performing operation %s: %s", + id_, typeid(ex).name(), config_->getOpName(opType).c_str(), + ex.what()); + return EA_NEXT_CONNECTION; + } + + /** + * Get the LoadConfig for this worker. + * + * (Returns a templatized config type for convenience, so subclasses can + * store a subclass of LoadConfig, and retrieve it without having to cast it + * back to the subclass type.) + */ + const boost::shared_ptr& getConfig() const { + return config_; + } + + /** + * The main worker method. + * + * Loop forever creating connections and performing operations on them. + * (May return if an error occurs and the error handler returns + * EA_DROP_THREAD.) + */ + virtual void run() { + while (true) { + // Create a new connection + boost::shared_ptr client; + try { + client = createConnection(); + } catch (const std::exception& ex) { + ErrorAction action = handleConnError(ex); + if (action == EA_CONTINUE || action == EA_NEXT_CONNECTION) { + // continue the next connection loop + continue; + } else if (action == EA_DROP_THREAD) { + T_ERROR("worker %d exiting after connection error", id_); + alive_ = false; + return; + } else if (action == EA_ABORT) { + T_ERROR("worker %d causing abort after connection error", id_); + abort(); + } else { + T_ERROR("worker %d received unknown conn error action %d; aborting", + id_, action); + abort(); + } + } + + // Determine how many operations to perform on this connection + uint32_t nops = config_->pickOpsPerConnection(); + + // Perform operations on the connection + for (uint32_t n = 0; n < nops; ++n) { + // Only send as fast as requested + if (!intervalTimer_->sleep()) { + T_ERROR("can't keep up with requested QPS rate"); + } + uint32_t opType = config_->pickOpType(); + scoreboard_->opStarted(opType); + try { + performOperation(client, opType); + scoreboard_->opSucceeded(opType); + } catch (const std::exception& ex) { + scoreboard_->opFailed(opType); + ErrorAction action = handleOpError(opType, ex); + if (action == EA_CONTINUE) { + // nothing to do; continue trying to use this connection + } else if (action == EA_NEXT_CONNECTION) { + // break out of the op loop, + // continue the next connection loop + break; + } else if (action == EA_DROP_THREAD) { + T_ERROR("worker %d exiting after op %d error", id_, opType); + // return from run() + alive_ = false; + return; + } else if (action == EA_ABORT) { + T_ERROR("worker %d causing abort after op %d error", id_, opType); + abort(); + } else { + T_ERROR("worker %d received unknown op error action %d; aborting", + id_, action); + abort(); + } + } + } + } + + assert(false); + alive_ = false; + } + + bool isAlive() const { + return alive_; + } + + protected: + // Methods needed for overriding ::run + const boost::shared_ptr& getScoreBoard() const { + return scoreboard_; + } + + void stopWorker() { + alive_ = false; + } + + private: + int id_; + bool alive_; + IntervalTimer* intervalTimer_; + boost::shared_ptr config_; + boost::shared_ptr scoreboard_; +}; + + +/** + * Default WorkerFactory implementation. + * + * This factory creates Worker objects using the default constructor, + * then calls init(id, config, scoreboard) on each worker before returning it. + */ +template +class SimpleWorkerFactory : public WorkerFactory { + public: + SimpleWorkerFactory(const boost::shared_ptr& config) + : config_(config) {} + + virtual WorkerT* newWorker(int id, + const boost::shared_ptr& scoreboard, + IntervalTimer* itimer) { + std::auto_ptr worker(new WorkerT); + worker->init(id, config_, scoreboard, itimer); + return worker.release(); + } + + boost::shared_ptr config_; +}; + +}}} // apache::thrift::loadgen + +#endif // THRIFT_TEST_LOADGEN_WORKER_H_ diff --git a/thrift/lib/cpp/test/loadgen/WorkerIf.h b/thrift/lib/cpp/test/loadgen/WorkerIf.h new file mode 100644 index 00000000..a5e65fc5 --- /dev/null +++ b/thrift/lib/cpp/test/loadgen/WorkerIf.h @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_LOADGEN_WORKERIF_H_ +#define THRIFT_TEST_LOADGEN_WORKERIF_H_ 1 + +#include + +#include "thrift/lib/cpp/test/loadgen/IntervalTimer.h" + +namespace apache { namespace thrift { namespace loadgen { + +class ScoreBoard; + +/** + * Interface class for all Worker types to inherit from + * + * If you are implementing a new load generator, you generally should derive + * from Worker instead of using WorkerIf directly. WorkerIf + * only exists to provide a common base class for all Worker template + * instantiations. + */ +class WorkerIf { + public: + virtual ~WorkerIf() {} + + /** + * Run the worker + */ + virtual void run() = 0; + + /** + * Determine if this worker is still running. + * + * Returns false if this worker's run() function has returned. + */ + virtual bool isAlive() const = 0; +}; + + +/** + * WorkerFactory + */ +class WorkerFactory { + public: + virtual ~WorkerFactory() {} + + virtual WorkerIf* newWorker(int id, + const boost::shared_ptr& sb, + IntervalTimer* itimer) = 0; +}; + +}}} // apache::thrift::loadgen + +#endif // THRIFT_TEST_LOADGEN_WORKERIF_H_ diff --git a/thrift/lib/cpp/test/loadgen/loadgen.h b/thrift/lib/cpp/test/loadgen/loadgen.h new file mode 100644 index 00000000..8158cace --- /dev/null +++ b/thrift/lib/cpp/test/loadgen/loadgen.h @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TEST_LOADGEN_LOADGEN_H_ +#define THRIFT_TEST_LOADGEN_LOADGEN_H_ 1 + +#include "thrift/lib/cpp/test/loadgen/Worker.h" + +namespace apache { namespace thrift { + +namespace concurrency { + +class PosixThreadFactory; + +} // apache::thrift::concurrency + +namespace loadgen { + +class LoadConfig; +class Monitor; + +/** + * Run load generation. + * + * @param factory The WorkerFactory to use to create each worker thread. + * @param config The LoadConfig object that describes the operations. + * @param interval The number of seconds between each line of statistics + * output. + * @param monitor The Monitor to use for printing statistics. If NULL, + * a LatencyMonitor will be used. + */ +void runLoadGen(WorkerFactory* factory, + const boost::shared_ptr& config, + double interval = 1.0, + Monitor* monitor = NULL, + apache::thrift::concurrency::PosixThreadFactory* threadFactory = NULL); + +/** + * Run load generation. + * + * This is a helper function around runLoadGen() that automatically creates a + * SimpleWorkerFactory. + */ +template +void runLoadGen(const boost::shared_ptr& config, + double interval = 1.0, + Monitor* monitor = NULL, + apache::thrift::concurrency::PosixThreadFactory* threadFactory = NULL) { + SimpleWorkerFactory factory(config); + runLoadGen(&factory, config, interval, monitor, threadFactory); +} + +/** + * Run load generation. + * + * This is a helper function around runLoadGen() that automatically creates a + * SimpleWorkerFactory. + */ +template +void runLoadGen(const boost::shared_ptr& config, + double interval = 1.0, + Monitor* monitor = NULL, + apache::thrift::concurrency::PosixThreadFactory* threadFactory = NULL) { + runLoadGen(config, interval, monitor, threadFactory); +} + +}}} // apache::thrift::loadgen + +#endif // THRIFT_TEST_LOADGEN_LOADGEN_H_ diff --git a/thrift/lib/cpp/thrift_config.h b/thrift/lib/cpp/thrift_config.h new file mode 100644 index 00000000..6a84630c --- /dev/null +++ b/thrift/lib/cpp/thrift_config.h @@ -0,0 +1,61 @@ +#ifndef THRIFT_THRIFT_CONFIG_H_ +#define THRIFT_THRIFT_CONFIG_H_ + +#include + +/* Define to 1 if you have the `clock_gettime' function. */ +#define THRIFT_HAVE_CLOCK_GETTIME 1 + +/* Define to 1 if you have the header file. */ +#define THRIFT_HAVE_ENDIAN_H 1 + +/* Define to 1 if you have the header file. */ +#define THRIFT_HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define THRIFT_HAVE_STDINT_H 1 + +/* Possible value for SIGNED_RIGHT_SHIFT_IS */ +#define ARITHMETIC_RIGHT_SHIFT 1 + +/* Possible value for SIGNED_RIGHT_SHIFT_IS */ +#define LOGICAL_RIGHT_SHIFT 2 + +/* Possible value for SIGNED_RIGHT_SHIFT_IS */ +#define UNKNOWN_RIGHT_SHIFT 3 + +/* Indicates the effect of the right shift operator on negative signed + integers */ +#define SIGNED_RIGHT_SHIFT_IS 1 + +/* + * Define to noexcept if the compiler supports noexcept + * + * If the compiler does not support noexcept, we define to the empty string + * in optimized builds. In debug builds, we define to throw(), so that the + * compiler will complain if a child class does not use THRIFT_NOEXCEPT when + * overriding a virtual method originally declared with THRIFT_NOEXCEPT. In + * debug mode, the program will also immediately call unexpected() if a + * THRIFT_NOEXCEPT function does throw an exception. + */ +#ifdef NDEBUG +#define THRIFT_NOEXCEPT +#else +#define THRIFT_NOEXCEPT throw() +#endif + +/* + * We have std::unique_ptr if we're compiling with gcc-4.4 or greater + * and C++0x features are enabled. + */ +#ifdef __GNUC__ +#if __GNUC_PREREQ(4, 4) +#define THRIFT_HAVE_UNIQUE_PTR __GXX_EXPERIMENTAL_CXX0X__ +#else +#define THRIFT_HAVE_UNIQUE_PTR 0 +#endif +#else /* ! __GNUC__ */ +#define THRIFT_HAVE_UNIQUE_PTR 0 +#endif /* __GNUC__ */ + +#endif /* THRIFT_THRIFT_CONFIG_H_ */ diff --git a/thrift/lib/cpp/transport/HDFS.h b/thrift/lib/cpp/transport/HDFS.h new file mode 100644 index 00000000..41fab864 --- /dev/null +++ b/thrift/lib/cpp/transport/HDFS.h @@ -0,0 +1,61 @@ +// Copyright (c) 2009- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_HDFS_H +#define _THRIFT_TRANSPORT_HDFS_H + +#include +#include + +/** + * Dead-simple wrappers around hdfs and hdfsFile descriptors. + * The wrappers take responsibility of descriptor allocation/release in ctor/dtor. + * + * @author Li Zhang + */ + +class HDFS { + public: + HDFS(); + HDFS(const std::string& host, uint16_t port); + bool disconnect(); + ~HDFS(); + void* getHandle() const { + return hdfs_; + } + bool isConnected() const { + return hdfs_ != NULL; + } + protected: + void* hdfs_; +}; + +class HDFSFile { + public: + enum AccessPolicy { + OPEN_FOR_READ = 0, + CREATE_FOR_WRITE = 1, + OPEN_FOR_APPEND = 2, + }; + HDFSFile(boost::shared_ptr hdfs, const std::string& path, AccessPolicy ap, + int bufferSize = 0, short replication = 0, int32_t blocksize = 0); + bool close(); + void* getHandle() const { + return file_; + } + boost::shared_ptr getFS() const { + return hdfs_; + } + bool isOpen() const { + return file_ != NULL; + } + ~HDFSFile(); + protected: + boost::shared_ptr hdfs_; + void* file_; +}; + +#endif diff --git a/thrift/lib/cpp/transport/TBufferTransports.h b/thrift/lib/cpp/transport/TBufferTransports.h new file mode 100644 index 00000000..0825a18c --- /dev/null +++ b/thrift/lib/cpp/transport/TBufferTransports.h @@ -0,0 +1,973 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_TRANSPORT_TBUFFERTRANSPORTS_H_ +#define THRIFT_TRANSPORT_TBUFFERTRANSPORTS_H_ 1 + +#include +#include "boost/scoped_array.hpp" +#include "folly/Likely.h" + +#include "thrift/lib/cpp/transport/TTransport.h" +#include "thrift/lib/cpp/transport/TVirtualTransport.h" + +namespace apache { namespace thrift { namespace transport { + + +/** + * Base class for all transports that use read/write buffers for performance. + * + * TBufferBase is designed to implement the fast-path "memcpy" style + * operations that work in the common case. It does so with small and + * (eventually) nonvirtual, inlinable methods. TBufferBase is an abstract + * class. Subclasses are expected to define the "slow path" operations + * that have to be done when the buffers are full or empty. + * + */ +class TBufferBase : public TVirtualTransport { + + public: + + /** + * Fast-path read. + * + * When we have enough data buffered to fulfill the read, we can satisfy it + * with a single memcpy, then adjust our internal pointers. If the buffer + * is empty, we call out to our slow path, implemented by a subclass. + * This method is meant to eventually be nonvirtual and inlinable. + */ + uint32_t read(uint8_t* buf, uint32_t len) { + uint8_t* new_rBase = rBase_ + len; + if (LIKELY(new_rBase <= rBound_)) { + std::memcpy(buf, rBase_, len); + rBase_ = new_rBase; + return len; + } + return readSlow(buf, len); + } + + /** + * Shortcutted version of readAll. + */ + uint32_t readAll(uint8_t* buf, uint32_t len) { + uint8_t* new_rBase = rBase_ + len; + if (LIKELY(new_rBase <= rBound_)) { + std::memcpy(buf, rBase_, len); + rBase_ = new_rBase; + return len; + } + return apache::thrift::transport::readAll(*this, buf, len); + } + + /** + * Fast-path write. + * + * When we have enough empty space in our buffer to accommodate the write, we + * can satisfy it with a single memcpy, then adjust our internal pointers. + * If the buffer is full, we call out to our slow path, implemented by a + * subclass. This method is meant to eventually be nonvirtual and + * inlinable. + */ + void write(const uint8_t* buf, uint32_t len) { + uint8_t* new_wBase = wBase_ + len; + if (LIKELY(new_wBase <= wBound_)) { + std::memcpy(wBase_, buf, len); + wBase_ = new_wBase; + return; + } + writeSlow(buf, len); + } + + /** + * Fast-path borrow. A lot like the fast-path read. + */ + const uint8_t* borrow(uint8_t* buf, uint32_t* len) { + if (LIKELY(static_cast(*len) <= rBound_ - rBase_)) { + // With strict aliasing, writing to len shouldn't force us to + // refetch rBase_ from memory. TODO(dreiss): Verify this. + *len = rBound_ - rBase_; + return rBase_; + } + return borrowSlow(buf, len); + } + + /** + * Consume doesn't require a slow path. + * When the read ptr catches up with write ptr, invokes consumeEnd(). + */ + void consume(uint32_t len) { + if (LIKELY(static_cast(len) <= rBound_ - rBase_)) { + rBase_ += len; + if (rBase_ == wBase_) { + // This is required for TMemoryBuffer. + consumeEnd(); + } + } else { + throw TTransportException(TTransportException::BAD_ARGS, + "consume did not follow a borrow."); + } + } + + + protected: + + /// Slow path read. + virtual uint32_t readSlow(uint8_t* buf, uint32_t len) = 0; + + /// Slow path write. + virtual void writeSlow(const uint8_t* buf, uint32_t len) = 0; + + /// consumeEnd, invoked when all data has been consumed. + virtual void consumeEnd() { } + /** + * Slow path borrow. + * + * POSTCONDITION: return == NULL || rBound_ - rBase_ >= *len + */ + virtual const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len) = 0; + + /** + * Trivial constructor. + * + * Initialize pointers safely. Constructing is not a very + * performance-sensitive operation, so it is okay to just leave it to + * the concrete class to set up pointers correctly. + */ + TBufferBase() + : rBase_(NULL) + , rBound_(NULL) + , wBase_(NULL) + , wBound_(NULL) + {} + + /// Convenience mutator for setting the read buffer. + void setReadBuffer(uint8_t* buf, uint32_t len) { + rBase_ = buf; + rBound_ = buf+len; + } + + /// Convenience mutator for setting the write buffer. + void setWriteBuffer(uint8_t* buf, uint32_t len) { + wBase_ = buf; + wBound_ = buf+len; + } + + virtual ~TBufferBase() {} + + /// Reads begin here. + uint8_t* rBase_; + /// Reads may extend to just before here. + uint8_t* rBound_; + + /// Writes begin here. + uint8_t* wBase_; + /// Writes may extend to just before here. + uint8_t* wBound_; +}; + + +/** + * Buffered transport. For reads it will read more data than is requested + * and will serve future data out of a local buffer. For writes, data is + * stored to an in memory buffer before being written out. + * + */ +class TBufferedTransport + : public TVirtualTransport { + public: + + static const int DEFAULT_BUFFER_SIZE = 512; + + /// Use default buffer sizes. + explicit TBufferedTransport(boost::shared_ptr transport) + : transport_(transport) + , rBufSize_(DEFAULT_BUFFER_SIZE) + , wBufSize_(DEFAULT_BUFFER_SIZE) + , wBufResetSize_(0) + , wBufResetEveryN_(0) + , wBufResetCount_(0) + , rBuf_(new uint8_t[rBufSize_]) + , wBuf_(new uint8_t[wBufSize_]) + { + initPointers(); + } + + /// Use specified buffer sizes. + TBufferedTransport(boost::shared_ptr transport, uint32_t sz) + : transport_(transport) + , rBufSize_(sz) + , wBufSize_(sz) + , wBufResetSize_(0) + , wBufResetEveryN_(0) + , wBufResetCount_(0) + , rBuf_(new uint8_t[rBufSize_]) + , wBuf_(new uint8_t[wBufSize_]) + { + initPointers(); + } + + /** + * Ctor with initial read and write buffer sizes and write buffer reset + * behaviour settings. + * + * @param transport Underlying transport. + * @param sz Initial buffer size. + * @param reset_sz Buffer size after a reset. See also reset_every_n. + * @param reset_every_n Reset the buffer after every N calls to flush(). + * If set to zero (default), no reset is done. + */ + TBufferedTransport(boost::shared_ptr transport, uint32_t rsz, + uint32_t wsz, uint32_t reset_sz = 0, + uint32_t reset_every_n = 0) + : transport_(transport) + , rBufSize_(rsz) + , wBufSize_(wsz) + , wBufResetSize_(reset_sz) + , wBufResetEveryN_(reset_every_n) + , wBufResetCount_(0) + , rBuf_(new uint8_t[rBufSize_]) + , wBuf_(new uint8_t[wBufSize_]) + { + initPointers(); + } + + // Tries to put some data back in the beginning of the read buffer. + void putBack(uint8_t* buf, uint32_t len); + + void open() { + transport_->open(); + } + + bool isOpen() { + return transport_->isOpen(); + } + + bool peek() { + if (rBase_ == rBound_) { + setReadBuffer(rBuf_.get(), transport_->read(rBuf_.get(), rBufSize_)); + } + return (rBound_ > rBase_); + } + + void close() { + flush(); + transport_->close(); + } + + virtual uint32_t readSlow(uint8_t* buf, uint32_t len); + + virtual void writeSlow(const uint8_t* buf, uint32_t len); + + void flush(); + + + /** + * The following behavior is currently implemented by TBufferedTransport, + * but that may change in a future version: + * 1/ If len is at most rBufSize_, borrow will never return NULL. + * Depending on the underlying transport, it could throw an exception + * or hang forever. + * 2/ Some borrow requests may copy bytes internally. However, + * if len is at most rBufSize_/2, none of the copied bytes + * will ever have to be copied again. For optimal performance, + * stay under this limit. + */ + virtual const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len); + + boost::shared_ptr getUnderlyingTransport() { + return transport_; + } + + /* + * TVirtualTransport provides a default implementation of readAll(). + * We want to use the TBufferBase version instead. + */ + using TBufferBase::readAll; + + protected: + void initPointers() { + setReadBuffer(rBuf_.get(), 0); + setWriteBuffer(wBuf_.get(), wBufSize_); + // Write size never changes. + } + + boost::shared_ptr transport_; + + uint32_t rBufSize_; + uint32_t wBufSize_; + uint32_t wBufResetSize_; + uint32_t wBufResetEveryN_; + uint32_t wBufResetCount_; + boost::scoped_array rBuf_; + boost::scoped_array wBuf_; +}; + + +/** + * Wraps a transport into a buffered one. + * + */ +class TBufferedTransportFactory : public TTransportFactory { + public: + TBufferedTransportFactory() {} + + virtual ~TBufferedTransportFactory() {} + + /** + * Wraps the transport into a buffered one. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr trans) { + return boost::shared_ptr(new TBufferedTransport(trans)); + } + +}; + + +/** + * Framed transport. All writes go into an in-memory buffer until flush is + * called, at which point the transport writes the length of the entire + * binary chunk followed by the data payload. This allows the receiver on the + * other end to always do fixed-length reads. + * + */ +class TFramedTransport + : public TVirtualTransport { + + public: + + static const int DEFAULT_BUFFER_SIZE = 512; + + + /// Use default buffer sizes. + explicit TFramedTransport(boost::shared_ptr transport) + : transport_(transport) + , rBufSize_(0) + , wBufSize_(DEFAULT_BUFFER_SIZE) + , wBufResetSize_(0) + , wBufResetEveryN_(0) + , wBufResetCount_(0) + , rBuf_() + , wBuf_(new uint8_t[wBufSize_]) + { + initPointers(); + } + + /** + * Ctor with initial buffer size and write buffer reset behaviour settings. + * + * @param transport Underlying transport. + * @param sz Initial buffer size. + * @param reset_sz Buffer size after a reset. See also reset_every_n. + * @param reset_every_n Reset the buffer after every N calls to flush(). + * If set to zero (default), no reset is done. + */ + TFramedTransport(boost::shared_ptr transport, uint32_t sz, + uint32_t reset_sz = 0, uint32_t reset_every_n = 0) + : transport_(transport) + , rBufSize_(0) + , wBufSize_(sz) + , wBufResetSize_(reset_sz) + , wBufResetEveryN_(reset_every_n) + , wBufResetCount_(0) + , rBuf_() + , wBuf_(new uint8_t[wBufSize_]) + { + assert(wBufResetSize_ == 0 || wBufSize_ <= wBufResetSize_); + initPointers(); + } + + void open() { + transport_->open(); + } + + bool isOpen() { + return transport_->isOpen(); + } + + bool peek() { + return (rBase_ < rBound_) || transport_->peek(); + } + + void close() { + flush(); + transport_->close(); + } + + virtual uint32_t readSlow(uint8_t* buf, uint32_t len); + + virtual void writeSlow(const uint8_t* buf, uint32_t len); + + virtual void flush(); + + uint32_t readEnd(); + + uint32_t writeEnd(); + + const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len); + + boost::shared_ptr getUnderlyingTransport() { + return transport_; + } + + /* + * TVirtualTransport provides a default implementation of readAll(). + * We want to use the TBufferBase version instead. + */ + using TBufferBase::readAll; + + protected: + /// Constructor for subclassing. + TFramedTransport() + : rBufSize_(0) + , wBufSize_(DEFAULT_BUFFER_SIZE) + , wBufResetSize_(0) + , wBufResetEveryN_(0) + , wBufResetCount_(0) + , rBuf_() + , wBuf_(new uint8_t[wBufSize_]) + { + initPointers(); + } + + /** + * Reads a frame of input from the underlying stream. + * + * Returns true if a frame was read successfully, or false on EOF. + * (Raises a TTransportException if EOF occurs after a partial frame.) + * + * @param req_sz The size of the requested data. readFrame may read more + * than this amount, but should not read less. + */ + virtual bool readFrame(uint32_t min_frame_sz); + + void initPointers() { + setReadBuffer(NULL, 0); + setWriteBuffer(wBuf_.get(), wBufSize_); + + // Pad the buffer so we can insert the size later. + int32_t pad = 0; + this->write((uint8_t*)&pad, sizeof(pad)); + } + + boost::shared_ptr transport_; + + uint32_t rBufSize_; + uint32_t wBufSize_; + uint32_t wBufResetSize_; + uint32_t wBufResetEveryN_; + uint32_t wBufResetCount_; + boost::scoped_array rBuf_; + boost::scoped_array wBuf_; +}; + +/** + * Wraps a transport into a framed one. + * + */ +class TFramedTransportFactory : public TTransportFactory { + public: + TFramedTransportFactory() {} + + virtual ~TFramedTransportFactory() {} + + /** + * Wraps the transport into a framed one. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr trans) { + return boost::shared_ptr(new TFramedTransport(trans)); + } + +}; + + +/** + * A memory buffer is a transport that simply reads from and writes to an + * in memory buffer. Anytime you call write on it, the data is simply placed + * into a buffer, and anytime you call read, data is read from that buffer. + * + * The buffers are allocated using C constructs malloc,realloc, and the size + * doubles as necessary. We've considered using scoped + * + */ +class TMemoryBuffer : public TVirtualTransport { + private: + + TMemoryBuffer(const TMemoryBuffer&); + TMemoryBuffer &operator=(const TMemoryBuffer&); + + // Common initialization done by all constructors. + void initCommon(uint8_t* buf, uint32_t size, bool owner, uint32_t wPos) { + if (buf == NULL && size != 0) { + assert(owner); + buf = (uint8_t*)std::malloc(size); + if (buf == NULL) { + throw std::bad_alloc(); + } + } + + buffer_ = buf; + bufferSize_ = size; + + rBase_ = buffer_; + rBound_ = buffer_ + wPos; + // TODO(dreiss): Investigate NULL-ing this if !owner. + wBase_ = buffer_ + wPos; + wBound_ = buffer_ + bufferSize_; + + owner_ = owner; + + linkedBuffer_ = NULL; + observerCount_ = 0; + // rBound_ is really an artifact. In principle, it should always be + // equal to wBase_. We update it in a few places (computeRead, etc.). + } + + public: + static const uint32_t defaultSize = 1024; + + /** + * This enum specifies how a TMemoryBuffer should treat + * memory passed to it via constructors or resetBuffer. + * + * OBSERVE: + * TMemoryBuffer will simply store a pointer to the memory. + * It is the callers responsibility to ensure that the pointer + * remains valid for the lifetime of the TMemoryBuffer, + * and that it is properly cleaned up. + * Note that no data can be written to observed buffers. + * + * COPY: + * TMemoryBuffer will make an internal copy of the buffer. + * The caller has no responsibilities. + * + * TAKE_OWNERSHIP: + * TMemoryBuffer will become the "owner" of the buffer, + * and will be responsible for freeing it. + * The memory must have been allocated with malloc. + */ + enum MemoryPolicy + { OBSERVE = 1 + , COPY = 2 + , TAKE_OWNERSHIP = 3 + }; + + /** + * Construct a TMemoryBuffer with a default-sized buffer, + * owned by the TMemoryBuffer object. + */ + TMemoryBuffer() { + initCommon(NULL, defaultSize, true, 0); + } + + /** + * Construct a TMemoryBuffer with a buffer of a specified size, + * owned by the TMemoryBuffer object. + * + * @param sz The initial size of the buffer. + */ + explicit TMemoryBuffer(uint32_t sz) { + initCommon(NULL, sz, true, 0); + } + + /** + * Construct a TMemoryBuffer with buf as its initial contents. + * + * @param buf The initial contents of the buffer. + * Note that, while buf is a non-const pointer, + * TMemoryBuffer will not write to it if policy == OBSERVE, + * so it is safe to const_cast(whatever). + * @param sz The size of @c buf. + * @param policy See @link MemoryPolicy @endlink . + */ + TMemoryBuffer(uint8_t* buf, uint32_t sz, MemoryPolicy policy = OBSERVE) { + if (buf == NULL && sz != 0) { + throw TTransportException(TTransportException::BAD_ARGS, + "TMemoryBuffer given null buffer with non-zero size."); + } + + switch (policy) { + case OBSERVE: + case TAKE_OWNERSHIP: + initCommon(buf, sz, policy == TAKE_OWNERSHIP, sz); + break; + case COPY: + initCommon(NULL, sz, true, 0); + this->write(buf, sz); + break; + default: + throw TTransportException(TTransportException::BAD_ARGS, + "Invalid MemoryPolicy for TMemoryBuffer"); + } + } + + explicit TMemoryBuffer(TMemoryBuffer *buffer) { + initCommon(buffer->rBase_, buffer->available_read(), false, + buffer->available_read()); + // Have to set buffer_ appropriately so this buffer can take ownership + // later if necessary. initCommon sets all other state correctly. + buffer_ = buffer->buffer_; + linkedBuffer_ = buffer; + linkedBuffer_->observe(this); + } + + ~TMemoryBuffer() { + cleanup(); + } + + // Set this buffer to observe the next length bytes of buffer. + void link(TMemoryBuffer *buffer, uint32_t length) { + assert(length <= buffer->available_read()); + cleanup(); + initCommon(buffer->rBase_, length, false, length); + buffer_ = buffer->buffer_; + linkedBuffer_ = buffer; + linkedBuffer_->observe(this); + } + + bool isOpen() { + return true; + } + + bool peek() { + return (rBase_ < wBase_); + } + + void open() {} + + void close() {} + + uint32_t getBufferSize() const { return bufferSize_; } + + // TODO(dreiss): Make bufPtr const. + void getBuffer(uint8_t** bufPtr, uint32_t* sz) { + *bufPtr = rBase_; + *sz = wBase_ - rBase_; + } + + std::string getBufferAsString() { + if (buffer_ == NULL) { + return ""; + } + uint8_t* buf; + uint32_t sz; + getBuffer(&buf, &sz); + return std::string((char*)buf, (std::string::size_type)sz); + } + + void appendBufferToString(std::string& str) { + if (buffer_ == NULL) { + return; + } + uint8_t* buf; + uint32_t sz; + getBuffer(&buf, &sz); + str.append((char*)buf, sz); + } + + void resetBuffer() { + rBase_ = buffer_; + rBound_ = buffer_; + wBase_ = buffer_; + // It isn't safe to write into a buffer we don't own. + if (!owner_) { + wBound_ = wBase_; + bufferSize_ = 0; + } + } + + // Register an observer of the memory in this buffer. + // + // A TMemoryBuffer with one or more observers has special handling + // for operations that would invalidate the data being observed. If + // an operation would invalidate the buffer pointer (eg: realloc, free), + // ownership of that buffer is first transferred to one of the observing + // TMemoryBuffers. + // + // Calls that reset an apparently empty buffer are delayed until all + // observers are detached. + void observe(TMemoryBuffer *observer) { + if (observer != NULL) { + observers_.push_back(observer); + } + observerCount_++; + } + + // Remove an observer of the memory in this buffer. If there is a pending + // consumeEnd call, process it + void unobserve(TMemoryBuffer *observer) { + if (UNLIKELY(observerCount_ == 0)) { + throw TTransportException("Tried to unobserve a buffer with no " + "observers"); + } + bool found = false; + if (observer != NULL) { + for(TMemoryBufferContainer::iterator it = observers_.begin(); + it != observers_.end(); ++it) { + if (*it == observer) { + observers_.erase(it); + found = true; + break; + } + } + } + if (!found) { + throw TTransportException("Tried to remove an observer that was not " + "observing the buffer"); + } + observerCount_--; + if (observerCount_ == 0 && rBase_ == wBase_) { + consumeEnd(); + } + } + + // Remove link to an observed memory buffer. If the buffer is not linked + // this is a no-op. + void unlink() { + if (linkedBuffer_ != NULL) { + linkedBuffer_->unobserve(this); + linkedBuffer_ = NULL; + } + } + + /// See constructor documentation. + void resetBuffer(uint8_t* buf, uint32_t sz, MemoryPolicy policy = OBSERVE) { + // Use a variant of the copy-and-swap trick for assignment operators. + // This is sub-optimal in terms of performance for two reasons: + // 1/ The constructing and swapping of the (small) values + // in the temporary object takes some time, and is not necessary. + // 2/ If policy == COPY, we allocate the new buffer before + // freeing the old one, precluding the possibility of + // reusing that memory. + // I doubt that either of these problems could be optimized away, + // but the second is probably no a common case, and the first is minor. + // I don't expect resetBuffer to be a common operation, so I'm willing to + // bite the performance bullet to make the method this simple. + + // Construct the new buffer. + TMemoryBuffer new_buffer(buf, sz, policy); + // Move it into ourself. + this->swap(new_buffer); + // Our old self gets destroyed. + } + + /// See constructor documentation. + void resetBuffer(uint32_t sz) { + // Construct the new buffer. + TMemoryBuffer new_buffer(sz); + // Move it into ourself. + this->swap(new_buffer); + // Our old self gets destroyed. + } + + std::string readAsString(uint32_t len) { + std::string str; + (void)readAppendToString(str, len); + return str; + } + + uint32_t readAppendToString(std::string& str, uint32_t len); + + // return number of bytes read + uint32_t readEnd() { + uint32_t bytes = rBase_ - buffer_; + if (rBase_ == wBase_) { + resetBuffer(); + } + return bytes; + } + + // Return number of bytes written + uint32_t writeEnd() { + return wBase_ - buffer_; + } + + uint32_t available_read() const { + // Remember, wBase_ is the real rBound_. + return wBase_ - rBase_; + } + + uint32_t available_write() const { + return wBound_ - wBase_; + } + + // Returns a pointer to where the client can write data to append to + // the TMemoryBuffer, and ensures the buffer is big enough to accommodate a + // write of the provided length. The returned pointer is very convenient for + // passing to read(), recv(), or similar. You must call wroteBytes() as soon + // as data is written or the buffer will not be aware that data has changed. + uint8_t* getWritePtr(uint32_t len) { + ensureCanWrite(len); + return wBase_; + } + + // Informs the buffer that the client has written 'len' bytes into storage + // that had been provided by getWritePtr(). + void wroteBytes(uint32_t len); + + /* + * TVirtualTransport provides a default implementation of readAll(). + * We want to use the TBufferBase version instead. + */ + using TBufferBase::readAll; + + /** + * Extract the read buffer from the TMemoryBuffer, or make a copy if this + * buffer does not own it. It's not safe to assume that a buffer created + * with TAKE_OWNERSHIP or COPY is still the owner of it's underlying buffer, + * because some TMemoryBuffer APIs (resetBuffer, link) change the ownership. + * Because of that, it's more consistent to make a copy rather than throw. + * + * The TMemoryBuffer's internal buffer is returned, and the caller is + * given ownership of the buffer. The caller is responsible for eventually + * freeing the buffer using free(). + * + * The TMemoryBuffer itself will be reset and will allocate a new buffer the + * next time data is written into it. + * + * @param buf The returned buffer pointer is stored at the location + * specified by this argument. + * @param buflen This parameter is used to return the number of bytes of + * readable data available at the start of the returned buffer. + * (Note that this is the amount of available data, not the + * buffer capacity.) + */ + void extractReadBuffer(uint8_t** buf, uint32_t* buflen) { + *buflen = available_read(); + if (owner_) { + if (rBase_ != buffer_) { + memmove(buffer_, rBase_, *buflen); + } + *buf = buffer_; + } else { + *buf = (uint8_t *)malloc(*buflen); + if (*buf == NULL) { + throw std::bad_alloc(); + } + memcpy(*buf, rBase_, *buflen); + cleanup(); + } + initCommon(NULL, 0, true, 0); + } + + protected: + void swap(TMemoryBuffer& that) { + using std::swap; + swap(buffer_, that.buffer_); + swap(bufferSize_, that.bufferSize_); + + swap(rBase_, that.rBase_); + swap(rBound_, that.rBound_); + swap(wBase_, that.wBase_); + swap(wBound_, that.wBound_); + + swap(owner_, that.owner_); + swap(linkedBuffer_, that.linkedBuffer_); + swap(observerCount_, that.observerCount_); + observers_.swap(that.observers_); + for (auto buf: observers_) { + buf->linkedBuffer_ = this; + } + for (auto buf: that.observers_) { + buf->linkedBuffer_ = &that; + } + if (linkedBuffer_ != NULL) { + linkedBuffer_->unobserve(&that); + linkedBuffer_->observe(this); + } + if (that.linkedBuffer_ != NULL) { + that.linkedBuffer_->unobserve(this); + that.linkedBuffer_->observe(&that); + } + } + + void transferOwnership() { + TMemoryBuffer *newOwner = NULL; + assert(!observers_.empty()); + // The optimal case is to make the new owner the TMemoryBuffer + // with the longest life-span. Use FIFO as a hueristic and assign + // the new owner to the last registered observer. + newOwner = observers_.back(); + observers_.pop_back(); + newOwner->owner_ = true; + newOwner->linkedBuffer_ = NULL; + for (TMemoryBufferContainer::iterator it = observers_.begin(); + it != observers_.end(); ++it) { + (*it)->linkedBuffer_ = newOwner; + // It's possible that an observer has other observers + newOwner->observers_.push_back(*it); + newOwner->observerCount_++; + } + observers_.clear(); + observerCount_ = 0; + } + + void cleanup() { + if (owner_) { + if (observerCount_ > 0) { + transferOwnership(); + } else { + std::free(buffer_); + } + } + if (linkedBuffer_ != NULL) { + linkedBuffer_->unobserve(this); + } + } + + void consumeEnd() { + if (observerCount_ == 0) { + resetBuffer(); + } + } + + // Make sure there's at least 'len' bytes available for writing. + void ensureCanWrite(uint32_t len); + + // Compute the position and available data for reading. + void computeRead(uint32_t len, uint8_t** out_start, uint32_t* out_give); + + uint32_t readSlow(uint8_t* buf, uint32_t len); + + void writeSlow(const uint8_t* buf, uint32_t len); + + const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len); + + // Data buffer + uint8_t* buffer_; + + // Allocated buffer size + uint32_t bufferSize_; + + // Is this object the owner of the buffer? + bool owner_; + + TMemoryBuffer *linkedBuffer_; + uint32_t observerCount_; + // The container is a vector (rather than a list) for performance + // reasons despite the O(N) penalty in unobserve. The vec keeps the + // overhead lower in the common case, which is a single observer. + typedef std::vector TMemoryBufferContainer; + TMemoryBufferContainer observers_; + // Don't forget to update constrctors, initCommon, and swap if + // you add new members. +}; + +}}} // apache::thrift::transport + +#endif // #ifndef THRIFT_TRANSPORT_TBUFFERTRANSPORTS_H_ diff --git a/thrift/lib/cpp/transport/TFDTransport.h b/thrift/lib/cpp/transport/TFDTransport.h new file mode 100644 index 00000000..1d1a3e68 --- /dev/null +++ b/thrift/lib/cpp/transport/TFDTransport.h @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TFDTRANSPORT_H_ +#define _THRIFT_TRANSPORT_TFDTRANSPORT_H_ 1 + +#include +#include + +#include "TTransport.h" +#include "TVirtualTransport.h" + +namespace apache { namespace thrift { namespace transport { + +/** + * Dead-simple wrapper around a file descriptor. + * + */ +class TFDTransport : public TVirtualTransport { + public: + enum ClosePolicy + { NO_CLOSE_ON_DESTROY = 0 + , CLOSE_ON_DESTROY = 1 + }; + + TFDTransport(int fd, ClosePolicy close_policy = NO_CLOSE_ON_DESTROY) + : fd_(fd) + , close_policy_(close_policy) + {} + + ~TFDTransport() { + if (close_policy_ == CLOSE_ON_DESTROY) { + close(); + } + } + + bool isOpen() { return fd_ >= 0; } + + void open() {} + + void close(); + + uint32_t read(uint8_t* buf, uint32_t len); + + void write(const uint8_t* buf, uint32_t len); + + void setFD(int fd) { fd_ = fd; } + int getFD() { return fd_; } + + protected: + int fd_; + ClosePolicy close_policy_; +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TFDTRANSPORT_H_ diff --git a/thrift/lib/cpp/transport/TFileTransport.h b/thrift/lib/cpp/transport/TFileTransport.h new file mode 100644 index 00000000..381e7dc2 --- /dev/null +++ b/thrift/lib/cpp/transport/TFileTransport.h @@ -0,0 +1,462 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TFILETRANSPORT_H_ +#define _THRIFT_TRANSPORT_TFILETRANSPORT_H_ 1 + +#include "thrift/lib/cpp/transport/TTransport.h" +#include "thrift/lib/cpp/Thrift.h" +#include "thrift/lib/cpp/TProcessor.h" + +#include +#include + +#include +#include +#include + +namespace apache { namespace thrift { namespace transport { + +using apache::thrift::TProcessor; +using apache::thrift::protocol::TProtocolFactory; + +// Data pertaining to a single event +typedef struct eventInfo { + uint8_t* eventBuff_; + uint32_t eventSize_; + uint32_t eventBuffPos_; + + eventInfo():eventBuff_(NULL), eventSize_(0), eventBuffPos_(0){}; + ~eventInfo() { + if (eventBuff_) { + delete[] eventBuff_; + } + } +} eventInfo; + +// information about current read state +typedef struct readState { + eventInfo* event_; + + // keep track of event size + uint8_t eventSizeBuff_[4]; + uint8_t eventSizeBuffPos_; + bool readingSize_; + + // read buffer variables + int32_t bufferPtr_; + int32_t bufferLen_; + + // last successful dispatch point + int32_t lastDispatchPtr_; + + void resetState(uint32_t lastDispatchPtr) { + readingSize_ = true; + eventSizeBuffPos_ = 0; + lastDispatchPtr_ = lastDispatchPtr; + } + + void resetAllValues() { + resetState(0); + bufferPtr_ = 0; + bufferLen_ = 0; + if (event_) { + delete(event_); + } + event_ = 0; + } + + readState() { + event_ = 0; + resetAllValues(); + } + + ~readState() { + if (event_) { + delete(event_); + } + } + +} readState; + +/** + * TFileTransportBuffer - buffer class used by TFileTransport for queuing up events + * to be written to disk. Should be used in the following way: + * 1) Buffer created + * 2) Buffer written to (addEvent) + * 3) Buffer read from (getNext) + * 4) Buffer reset (reset) + * 5) Go back to 2, or destroy buffer + * + * The buffer should never be written to after it is read from, unless it is reset first. + * Note: The above rules are enforced mainly for debugging its sole client TFileTransport + * which uses the buffer in this way. + * + */ +class TFileTransportBuffer { + public: + TFileTransportBuffer(uint32_t size); + ~TFileTransportBuffer(); + + bool addEvent(eventInfo *event); + eventInfo* getNext(); + void reset(); + bool isFull(); + bool isEmpty(); + + private: + TFileTransportBuffer(); // should not be used + + enum mode { + WRITE, + READ + }; + mode bufferMode_; + + uint32_t writePoint_; + uint32_t readPoint_; + uint32_t size_; + eventInfo** buffer_; +}; + +/** + * Abstract interface for transports used to read files + */ +class TFileReaderTransport : virtual public TTransport { + public: + virtual int32_t getReadTimeout() = 0; + virtual void setReadTimeout(int32_t readTimeout) = 0; + + virtual uint32_t getNumChunks() = 0; + virtual uint32_t getCurChunk() = 0; + virtual void seekToChunk(int32_t chunk) = 0; + virtual void seekToEnd() = 0; +}; + +/** + * Abstract interface for transports used to write files + */ +class TFileWriterTransport : virtual public TTransport { + public: + virtual uint32_t getChunkSize() = 0; + virtual void setChunkSize(uint32_t chunkSize) = 0; +}; + +/** + * File implementation of a transport. Reads and writes are done to a + * file on disk. + * + */ +class TFileTransport : public TFileReaderTransport, + public TFileWriterTransport { + public: + TFileTransport(std::string path, bool readOnly=false); + ~TFileTransport(); + + // TODO: what is the correct behavior for this? + // the log file is generally always open + bool isOpen() { + return true; + } + + void write(const uint8_t* buf, uint32_t len); + void flush(); + + uint32_t readAll(uint8_t* buf, uint32_t len); + bool peek(); + uint32_t read(uint8_t* buf, uint32_t len); + + // log-file specific functions + void seekToChunk(int32_t chunk); + void seekToEnd(); + uint32_t getNumChunks(); + uint32_t getCurChunk(); + + // for changing the output file + void resetOutputFile(int fd, std::string filename, int64_t offset); + + // Setter/Getter functions for user-controllable options + void setReadBuffSize(uint32_t readBuffSize) { + if (readBuffSize) { + readBuffSize_ = readBuffSize; + } + } + uint32_t getReadBuffSize() { + return readBuffSize_; + } + + static const int32_t TAIL_READ_TIMEOUT = -1; + static const int32_t NO_TAIL_READ_TIMEOUT = 0; + void setReadTimeout(int32_t readTimeout) { + readTimeout_ = readTimeout; + } + int32_t getReadTimeout() { + return readTimeout_; + } + + void setChunkSize(uint32_t chunkSize) { + if (chunkSize) { + chunkSize_ = chunkSize; + } + } + uint32_t getChunkSize() { + return chunkSize_; + } + + void setEventBufferSize(uint32_t bufferSize) { + if (bufferAndThreadInitialized_) { + GlobalOutput("Cannot change the buffer size after writer thread started"); + return; + } + eventBufferSize_ = bufferSize; + } + + uint32_t getEventBufferSize() { + return eventBufferSize_; + } + + void setFlushMaxUs(uint32_t flushMaxUs) { + if (flushMaxUs) { + flushMaxUs_ = flushMaxUs; + } + } + uint32_t getFlushMaxUs() { + return flushMaxUs_; + } + + void setFlushMaxBytes(uint32_t flushMaxBytes) { + if (flushMaxBytes) { + flushMaxBytes_ = flushMaxBytes; + } + } + uint32_t getFlushMaxBytes() { + return flushMaxBytes_; + } + + void setMaxEventSize(uint32_t maxEventSize) { + maxEventSize_ = maxEventSize; + } + uint32_t getMaxEventSize() { + return maxEventSize_; + } + + void setMaxCorruptedEvents(uint32_t maxCorruptedEvents) { + maxCorruptedEvents_ = maxCorruptedEvents; + } + uint32_t getMaxCorruptedEvents() { + return maxCorruptedEvents_; + } + + void setEofSleepTimeUs(uint32_t eofSleepTime) { + if (eofSleepTime) { + eofSleepTime_ = eofSleepTime; + } + } + uint32_t getEofSleepTimeUs() { + return eofSleepTime_; + } + + /* + * Override TTransport *_virt() functions to invoke our implementations. + * We cannot use TVirtualTransport to provide these, since we need to inherit + * virtually from TTransport. + */ + virtual uint32_t read_virt(uint8_t* buf, uint32_t len) { + return this->read(buf, len); + } + virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len) { + return this->readAll(buf, len); + } + virtual void write_virt(const uint8_t* buf, uint32_t len) { + this->write(buf, len); + } + + private: + // helper functions for writing to a file + void enqueueEvent(const uint8_t* buf, uint32_t eventLen); + bool swapEventBuffers(struct timespec* deadline); + bool initBufferAndWriteThread(); + + // control for writer thread + static void* startWriterThread(void* ptr) { + (((TFileTransport*)ptr)->writerThread()); + return 0; + } + void writerThread(); + + // helper functions for reading from a file + eventInfo* readEvent(); + + // event corruption-related functions + bool isEventCorrupted(); + void performRecovery(); + + // Utility functions + void openLogFile(); + void getNextFlushTime(struct timespec* ts_next_flush); + + // Class variables + readState readState_; + uint8_t* readBuff_; + eventInfo* currentEvent_; + + uint32_t readBuffSize_; + static const uint32_t DEFAULT_READ_BUFF_SIZE = 1 * 1024 * 1024; + + int32_t readTimeout_; + static const int32_t DEFAULT_READ_TIMEOUT_MS = 200; + + // size of chunks that file will be split up into + uint32_t chunkSize_; + static const uint32_t DEFAULT_CHUNK_SIZE = 16 * 1024 * 1024; + + // size of event buffers + uint32_t eventBufferSize_; + static const uint32_t DEFAULT_EVENT_BUFFER_SIZE = 10000; + + // max number of microseconds that can pass without flushing + uint32_t flushMaxUs_; + static const uint32_t DEFAULT_FLUSH_MAX_US = 3000000; + + // max number of bytes that can be written without flushing + uint32_t flushMaxBytes_; + static const uint32_t DEFAULT_FLUSH_MAX_BYTES = 1000 * 1024; + + // max event size + uint32_t maxEventSize_; + static const uint32_t DEFAULT_MAX_EVENT_SIZE = 0; + + // max number of corrupted events per chunk + uint32_t maxCorruptedEvents_; + static const uint32_t DEFAULT_MAX_CORRUPTED_EVENTS = 0; + + // sleep duration when EOF is hit + uint32_t eofSleepTime_; + static const uint32_t DEFAULT_EOF_SLEEP_TIME_US = 500 * 1000; + + // sleep duration when a corrupted event is encountered + uint32_t corruptedEventSleepTime_; + static const uint32_t DEFAULT_CORRUPTED_SLEEP_TIME_US = 1 * 1000 * 1000; + + // sleep duration in seconds when an IO error is encountered in the writer thread + uint32_t writerThreadIOErrorSleepTime_; + static const uint32_t DEFAULT_WRITER_THREAD_SLEEP_TIME_US = 60 * 1000 * 1000; + + // writer thread id + pthread_t writerThreadId_; + + // buffers to hold data before it is flushed. Each element of the buffer stores a msg that + // needs to be written to the file. The buffers are swapped by the writer thread. + TFileTransportBuffer *dequeueBuffer_; + TFileTransportBuffer *enqueueBuffer_; + + // conditions used to block when the buffer is full or empty + pthread_cond_t notFull_, notEmpty_; + volatile bool closing_; + + // To keep track of whether the buffer has been flushed + pthread_cond_t flushed_; + bool forceFlush_; + + // Mutex that is grabbed when enqueuing and swapping the read/write buffers + pthread_mutex_t mutex_; + + // File information + std::string filename_; + int fd_; + + // Whether the writer thread and buffers have been initialized + bool bufferAndThreadInitialized_; + + // Offset within the file + off_t offset_; + + // event corruption information + uint32_t lastBadChunk_; + uint32_t numCorruptedEventsInChunk_; + + bool readOnly_; +}; + +// Exception thrown when EOF is hit +class TEOFException : public TTransportException { + public: + TEOFException(): + TTransportException(TTransportException::END_OF_FILE) {}; +}; + + +// wrapper class to process events from a file containing thrift events +class TFileProcessor { + public: + /** + * Constructor that defaults output transport to null transport + * + * @param processor processes log-file events + * @param protocolFactory protocol factory + * @param inputTransport file transport + */ + TFileProcessor(boost::shared_ptr processor, + boost::shared_ptr protocolFactory, + boost::shared_ptr inputTransport); + + TFileProcessor(boost::shared_ptr processor, + boost::shared_ptr inputProtocolFactory, + boost::shared_ptr outputProtocolFactory, + boost::shared_ptr inputTransport); + + /** + * Constructor + * + * @param processor processes log-file events + * @param protocolFactory protocol factory + * @param inputTransport input file transport + * @param output output transport + */ + TFileProcessor(boost::shared_ptr processor, + boost::shared_ptr protocolFactory, + boost::shared_ptr inputTransport, + boost::shared_ptr outputTransport); + + /** + * processes events from the file + * + * @param numEvents number of events to process (0 for unlimited) + * @param tail tails the file if true + */ + void process(uint32_t numEvents, bool tail); + + /** + * process events until the end of the chunk + * + */ + void processChunk(); + + private: + boost::shared_ptr processor_; + boost::shared_ptr inputProtocolFactory_; + boost::shared_ptr outputProtocolFactory_; + boost::shared_ptr inputTransport_; + boost::shared_ptr outputTransport_; +}; + + +}}} // apache::thrift::transport + +#endif // _THRIFT_TRANSPORT_TFILETRANSPORT_H_ diff --git a/thrift/lib/cpp/transport/THDFSFileTransport.h b/thrift/lib/cpp/transport/THDFSFileTransport.h new file mode 100644 index 00000000..64414fa8 --- /dev/null +++ b/thrift/lib/cpp/transport/THDFSFileTransport.h @@ -0,0 +1,52 @@ +// Copyright (c) 2009- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_THDFSFILETRANSPORT_H_ +#define _THRIFT_TRANSPORT_THDFSFILETRANSPORT_H_ + +#include "thrift/lib/cpp/transport/TTransport.h" +#include "thrift/lib/cpp/transport/TVirtualTransport.h" +#include "HDFS.h" +#include + +#include +#include + +namespace apache { namespace thrift { namespace transport { +/** + * Dead-simple wrapper around libhdfs. + * THDFSFileTransport only takes care of read/write, + * and leaves allocation/release to HDFS and HDFSFile. + * @author Li Zhang + */ +class THDFSFileTransport : public TVirtualTransport { + public: + + THDFSFileTransport(boost::shared_ptr hdfsFile) : hdfsFile_(hdfsFile) { + } + + ~THDFSFileTransport() { + } + + bool isOpen() { + return hdfsFile_->isOpen(); + } + + void open(); + + void close(); + + uint32_t read(uint8_t* buf, uint32_t len); + + void write(const uint8_t* buf, uint32_t len); + + protected: + boost::shared_ptr hdfsFile_; +}; + +}}} // apache::thrift::transport + +#endif // _THRIFT_TRANSPORT_THDFSFILETRANSPORT_H_ diff --git a/thrift/lib/cpp/transport/THeader.h b/thrift/lib/cpp/transport/THeader.h new file mode 100644 index 00000000..01524e53 --- /dev/null +++ b/thrift/lib/cpp/transport/THeader.h @@ -0,0 +1,294 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_TRANSPORT_THEADER_H_ +#define THRIFT_TRANSPORT_THEADER_H_ 1 + +#include + +#include "thrift/lib/cpp/protocol/TBinaryProtocol.h" +#include "thrift/lib/cpp/protocol/TCompactProtocol.h" +#include "thrift/lib/cpp/protocol/TProtocolTypes.h" + +#include "folly/experimental/io/IOBuf.h" +#include "folly/experimental/io/IOBufQueue.h" + +#include +#include "boost/scoped_array.hpp" +#include +#include + +// Don't include the unknown client. +#define CLIENT_TYPES_LEN 5 + +enum CLIENT_TYPE { + THRIFT_HEADER_CLIENT_TYPE = 0, + THRIFT_FRAMED_DEPRECATED = 1, + THRIFT_UNFRAMED_DEPRECATED = 2, + THRIFT_HTTP_CLIENT_TYPE = 3, + THRIFT_FRAMED_COMPACT = 4, + THRIFT_UNKNOWN_CLIENT_TYPE = 5, +}; + +namespace apache { namespace thrift { namespace transport { + +using apache::thrift::protocol::T_COMPACT_PROTOCOL; + +/** + * Class that will take an IOBuf and wrap it in some thrift headers. + * see thrift/doc/HeaderFormat.txt for details. + * + * Supports transforms: zlib snappy hmac + * Supports headers: http-style key/value per request and per connection + * other: Protocol Id and seq ID in header. + * + * Backwards compatible with TFramed format, and unframed format, assuming + * your server transport is compatible (some server types require 4-byte size + * at the start, such as TNonblockingServer). + */ +class THeader { + public: + + virtual ~THeader() {} + + explicit THeader() + : queue_(new folly::IOBufQueue) + , protoId(T_COMPACT_PROTOCOL) + , clientType(THRIFT_HEADER_CLIENT_TYPE) + , seqId(0) + , flags(0) + , identity(s_identity) + { + initSupportedClients(NULL); + } + + explicit THeader(std::bitset const* clientTypes) + : queue_(new folly::IOBufQueue) + , protoId(T_COMPACT_PROTOCOL) + , clientType(THRIFT_HEADER_CLIENT_TYPE) + , seqId(0) + , flags(0) + , identity(s_identity) + { + initSupportedClients(clientTypes); + } + + uint16_t getProtocolId() const; + void setProtocolId(uint16_t protoId) { this->protoId = protoId; } + + virtual void resetProtocol(); + + /** + * We know we got a packet in header format here, try to parse the header + * + * @param IObuf of the header + data. Untransforms the data as appropriate. + * @return Just the data section in an IOBuf + */ + std::unique_ptr readHeaderFormat(std::unique_ptr); + + /** + * Untransform the data based on the received header flags + * On conclusion of function, setReadBuffer is called with the + * untransformed data. + * + * @param IOBuf input data section + * @return IOBuf output data section + */ + std::unique_ptr untransform(std::unique_ptr); + + /** + * Transform the data based on our write transform flags + * At conclusion of function the write buffer is set to the + * transformed data. + * + * @param IOBuf to transform. Returns transformed IOBuf (or chain) + * @return transformed data IOBuf + */ + std::unique_ptr transform(std::unique_ptr); + + uint16_t getNumTransforms() const { + int trans = writeTrans_.size(); + if (macCallback_) { + trans += 1; + } + return trans; + } + + void setTransform(uint16_t transId) { writeTrans_.push_back(transId); } + + // Info headers + typedef std::map StringToStringMap; + + // these work with write headers + void setHeader(const std::string& key, const std::string& value); + void setPersistentHeader(const std::string& key, const std::string& value); + void clearHeaders(); + /** + * this function only clears the local persistent + * header. does not affect the persistent header + * that already set + */ + void clearPersistentHeaders(); + + StringToStringMap& getWriteHeaders() { + return writeHeaders_; + } + + StringToStringMap& getPersistentWriteHeaders() { + return persisWriteHeaders_; + } + + // these work with read headers + const StringToStringMap& getHeaders() const { + return readHeaders_; + } + + std::string getPeerIdentity(); + void setIdentity(const std::string& identity); + + // accessors for seqId + int32_t getSequenceNumber() const { return seqId; } + void setSequenceNumber(int32_t seqId) { this->seqId = seqId; } + + enum TRANSFORMS { + ZLIB_TRANSFORM = 0x01, + HMAC_TRANSFORM = 0x02, + SNAPPY_TRANSFORM = 0x03, + }; + + /** + * Callbacks to get and verify a mac transform. + * + * If a mac callback is provided, it will be called with the outgoing packet, + * with the returned string appended at the end of the data. + * + * If a verify callback is provided, all incoming packets will be called with + * their mac data and packet data to verify. If false is returned, an + * exception is thrown. Packets without any mac also throw an exception if a + * verify function is provided. + * + * If no verify callback is provided, and an incoming packet contains a mac, + * the mac is ignored. + * + **/ + typedef std::tr1::function MacCallback; + typedef std::tr1::function< + bool(const std::string&, const std::string)> VerifyMacCallback; + + void setHmac(MacCallback macCb, VerifyMacCallback verifyCb) { + macCallback_ = macCb; + verifyCallback_ = verifyCb; + } + + /* IOBuf interface */ + + /** + * Adds the header based on the type of transport: + * unframed - does nothing. + * framed - prepends frame size + * header - prepends header, optionally appends mac + * http - only supported for sync case, prepends http header. + * + * @return IOBuf chain with header _and_ data. Data is not copied + */ + std::unique_ptr addHeader(std::unique_ptr); + /** + * Given an IOBuf Chain, remove the header. Supports unframed (sync + * only), framed, header, and http (sync case only). + * + * @param IOBufQueue - queue to try to read message from. + * + * @param needed - if the return is NULL (i.e. we didn't read a full + * message), needed is set to the number of bytes needed + * before you should call removeHeader again. + * + * @return IOBuf - the message chain. May be shared, may be chained. + * If NULL, we didn't get enough data for a whole message, + * call removeHeader again after reading needed more bytes. + */ + std::unique_ptr removeHeader(folly::IOBufQueue*, + size_t& needed); + + protected: + + std::bitset supported_clients; + + void initSupportedClients(std::bitset const*); + + std::unique_ptr queue_; + + // 0 and 16th bits must be 0 to differentiate from framed & unframed + static const uint32_t HEADER_MAGIC = 0x0FFF0000; + static const uint32_t HEADER_MASK = 0xFFFF0000; + static const uint32_t FLAGS_MASK = 0x0000FFFF; + static const uint32_t HTTP_MAGIC = 0x504F5354; // POST + + static const uint32_t MAX_FRAME_SIZE = 0x3FFFFFFF; + + int16_t protoId; + uint16_t clientType; + uint32_t seqId; + uint16_t flags; + std::string identity; + + std::vector readTrans_; + std::vector writeTrans_; + + // Map to use for headers + StringToStringMap readHeaders_; + StringToStringMap writeHeaders_; + + // Map to use for persistent headers + StringToStringMap persisReadHeaders_; + StringToStringMap persisWriteHeaders_; + + static const std::string IDENTITY_HEADER; + static const std::string ID_VERSION_HEADER; + static const std::string ID_VERSION; + + static std::string s_identity; + + MacCallback macCallback_; + VerifyMacCallback verifyCallback_; + + /** + * Returns the maximum number of bytes that write k/v headers can take + */ + size_t getMaxWriteHeadersSize() const; + + /** + * Returns whether the 1st byte of the protocol payload should be hadled + * as compact framed. + */ + bool compactFramed(uint32_t magic); + + struct infoIdType { + enum idType { + // start at 1 to avoid confusing header padding for an infoId + KEYVALUE = 1, + // for persistent header + PKEYVALUE = 2, + END // signal the end of infoIds we can handle + }; + }; +}; + +}}} // apache::thrift::transport + +#endif // #ifndef THRIFT_TRANSPORT_THEADER_H_ diff --git a/thrift/lib/cpp/transport/THeaderTransport.h b/thrift/lib/cpp/transport/THeaderTransport.h new file mode 100644 index 00000000..ddad1af0 --- /dev/null +++ b/thrift/lib/cpp/transport/THeaderTransport.h @@ -0,0 +1,185 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_TRANSPORT_THEADERTRANSPORT_H_ +#define THRIFT_TRANSPORT_THEADERTRANSPORT_H_ 1 + +#include + +#include "thrift/lib/cpp/transport/TBufferTransports.h" +#include "thrift/lib/cpp/transport/THeader.h" +#include "thrift/lib/cpp/transport/THttpServer.h" +#include "thrift/lib/cpp/transport/TTransport.h" +#include "thrift/lib/cpp/transport/TVirtualTransport.h" + +#include "folly/experimental/io/IOBuf.h" +#include "folly/experimental/io/IOBufQueue.h" + +#include +#include "boost/scoped_array.hpp" +#include +#include + +namespace apache { namespace thrift { namespace transport { + +/** + * Header transport. All writes go into an in-memory buffer until flush is + * called, at which point the transport writes the length of the entire + * binary chunk followed by the data payload. This allows the receiver on the + * other end to always do fixed-length reads. + * + * Subclass TFramedTransport because most of the read/write methods are similar + * and need similar buffers. Major changes are readFrame & flush. + */ +class THeaderTransport + : public TVirtualTransport + , public THeader { + public: + + explicit THeaderTransport(const boost::shared_ptr transport) + : THeader() + ,transport_(transport) + , outTransport_(transport) + , httpTransport_(transport) + { + initBuffers(); + } + + THeaderTransport(const boost::shared_ptr transport, + std::bitset const* clientTypes) + : THeader(clientTypes) + , transport_(transport) + , outTransport_(transport) + , httpTransport_(transport) + { + initBuffers(); + } + + THeaderTransport(const boost::shared_ptr inTransport, + const boost::shared_ptr outTransport, + std::bitset const* clientTypes) + : THeader(clientTypes) + , transport_(inTransport) + , outTransport_(outTransport) + , httpTransport_(outTransport) + { + initBuffers(); + } + + THeaderTransport(const boost::shared_ptr transport, uint32_t sz, + std::bitset const* clientTypes) + : THeader(clientTypes) + , transport_(transport) + , outTransport_(transport) + , httpTransport_(transport) + { + initBuffers(); + } + + void resetProtocol(); + + void open() { + transport_->open(); + } + + bool isOpen() { + return transport_->isOpen(); + } + + bool peek() { + return (this->rBase_ < this->rBound_) || transport_->peek(); + } + + void close() { + flush(); + transport_->close(); + } + + virtual uint32_t readSlow(uint8_t* buf, uint32_t len); + virtual uint32_t readAll(uint8_t* buf, uint32_t len); + virtual void flush(); + + boost::shared_ptr getUnderlyingTransport() { + return transport_; + } + + /* + * TVirtualTransport provides a default implementation of readAll(). + * We want to use the TBufferBase version instead. + */ + using TBufferBase::readAll; + + protected: + /** + * Reads a frame of input from the underlying stream. + * + * Returns true if a frame was read successfully, or false on EOF. + * (Raises a TTransportException if EOF occurs after a partial frame.) + */ + bool readFrame(uint32_t minFrameSize); + + void allocateReadBuffer(uint32_t sz); + uint32_t getWriteBytes(); + + void initBuffers() { + setReadBuffer(NULL, 0); + setWriteBuffer(wBuf_.get(), wBufSize_); + } + + boost::shared_ptr transport_; + boost::shared_ptr outTransport_; + + boost::shared_ptr httpTransport_; + + // Buffer to use for readFrame/flush processing + std::unique_ptr readBuf_; +}; + +/** + * Wraps a transport into a header one. + * + */ +class THeaderTransportFactory : public TTransportFactory { + public: + THeaderTransportFactory() {} + + virtual ~THeaderTransportFactory() {} + + /** + * Wraps the transport into a header one. + */ + virtual boost::shared_ptr + getTransport(boost::shared_ptr trans) { + return boost::shared_ptr( + new THeaderTransport(trans, &clientTypes)); + } + + void setClientTypes(const std::bitset& clientTypes) { + for (int i = 0; i < CLIENT_TYPES_LEN; ++i) { + this->clientTypes[i] = clientTypes[i]; + } + } + +private: + std::bitset clientTypes; +}; + +}}} // apache::thrift::transport + +#endif // #ifndef THRIFT_TRANSPORT_THEADERTRANSPORT_H_ diff --git a/thrift/lib/cpp/transport/THttpClient.h b/thrift/lib/cpp/transport/THttpClient.h new file mode 100644 index 00000000..91e04a9c --- /dev/null +++ b/thrift/lib/cpp/transport/THttpClient.h @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_TRANSPORT_THTTPCLIENT_H_ +#define THRIFT_TRANSPORT_THTTPCLIENT_H_ 1 + +#include + +namespace apache { namespace thrift { namespace transport { + +class THttpClient : public THttpTransport { + public: + /* + * Create for a given host and port. The version that doesn't take + * a transport constructs its own TSocket as a transport. + * + * The path must be non-empty and start with "/". + */ + THttpClient(const boost::shared_ptr& transport, + const std::string& host, + const std::string& path); + THttpClient(const std::string& host, int port, const std::string& path); + + virtual ~THttpClient(); + + void setUserAgent(const std::string&); + + virtual void flush(); + + virtual void close() { + connectionClosedByServer_ = false; + THttpTransport::close(); + } + + virtual void init() { + /* + * HTTP requires that the `abs_path' component of a POST message start + * with '/' (see rfc2616 and rfc2396). + */ + assert(!path_.empty() && path_[0] == '/'); + + THttpTransport::init(); + } + + protected: + + const std::string host_; + const std::string path_; + std::string userAgent_; + bool connectionClosedByServer_; + + virtual void parseHeader(char* header); + virtual bool parseStatusLine(char* status); + +}; + +}}} // apache::thrift::transport + +#endif // #ifndef THRIFT_TRANSPORT_THTTPCLIENT_H_ diff --git a/thrift/lib/cpp/transport/THttpServer.h b/thrift/lib/cpp/transport/THttpServer.h new file mode 100644 index 00000000..65234084 --- /dev/null +++ b/thrift/lib/cpp/transport/THttpServer.h @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_THTTPSERVER_H_ +#define _THRIFT_TRANSPORT_THTTPSERVER_H_ 1 + +#include + +namespace apache { namespace thrift { namespace transport { + +class THttpServer : public THttpTransport { + public: + THttpServer(boost::shared_ptr transport); + + virtual ~THttpServer(); + + virtual void flush(); + + protected: + + void readHeaders(); + virtual void parseHeader(char* header); + virtual bool parseStatusLine(char* status); + std::string getTimeRFC1123(); + +}; + +/** + * Wraps a transport into HTTP protocol + */ +class THttpServerTransportFactory : public TTransportFactory { + public: + THttpServerTransportFactory() {} + + virtual ~THttpServerTransportFactory() {} + + /** + * Wraps the transport into a buffered one. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr trans) { + return boost::shared_ptr(new THttpServer(trans)); + } + +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_THTTPSERVER_H_ diff --git a/thrift/lib/cpp/transport/THttpTransport.h b/thrift/lib/cpp/transport/THttpTransport.h new file mode 100644 index 00000000..d315449e --- /dev/null +++ b/thrift/lib/cpp/transport/THttpTransport.h @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_TRANSPORT_THTTPTRANSPORT_H_ +#define THRIFT_TRANSPORT_THTTPTRANSPORT_H_ 1 + +#include +#include "TVirtualTransport.h" + +namespace apache { namespace thrift { namespace transport { + +/** + * HTTP implementation of the thrift transport. This was irritating + * to write, but the alternatives in C++ land are daunting. Linking CURL + * requires 23 dynamic libraries last time I checked (WTF?!?). All we have + * here is a VERY basic HTTP/1.1 client which supports HTTP 100 Continue, + * chunked transfer encoding, keepalive, etc. Tested against Apache. + */ +class THttpTransport : public TVirtualTransport { + public: + explicit THttpTransport(boost::shared_ptr transport); + + virtual ~THttpTransport(); + + void open() { + transport_->open(); + } + + bool isOpen() { + return transport_->isOpen(); + } + + bool peek() { + return transport_->peek(); + } + + virtual void close() { + transport_->close(); + } + + uint32_t read(uint8_t* buf, uint32_t len); + + uint32_t readEnd(); + + void write(const uint8_t* buf, uint32_t len); + + virtual void flush() = 0; + + boost::shared_ptr getUnderlyingTransport() { + return transport_; + } + + protected: + + boost::shared_ptr transport_; + + TMemoryBuffer writeBuffer_; + TMemoryBuffer readBuffer_; + + bool readHeaders_; + bool chunked_; + bool chunkedDone_; + uint32_t chunkSize_; + uint32_t contentLength_; + + char* httpBuf_; + uint32_t httpPos_; + uint32_t httpBufLen_; + uint32_t httpBufSize_; + + virtual void init(); + + uint32_t readMoreData(); + char* readLine(); + + void readHeaders(); + virtual void parseHeader(char* header) = 0; + virtual bool parseStatusLine(char* status) = 0; + + uint32_t readChunked(); + void readChunkedFooters(); + uint32_t parseChunkSize(char* line); + + uint32_t readContent(uint32_t size); + + virtual void refill(); + void shift(); + + static const char* CRLF; + static const int CRLF_LEN; +}; + +}}} // apache::thrift::transport + +#endif // #ifndef THRIFT_TRANSPORT_THTTPCLIENT_H_ diff --git a/thrift/lib/cpp/transport/TMemPagedFactory.h b/thrift/lib/cpp/transport/TMemPagedFactory.h new file mode 100644 index 00000000..3ed65c47 --- /dev/null +++ b/thrift/lib/cpp/transport/TMemPagedFactory.h @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TMEMPAGEDFACTORY_H_ +#define _THRIFT_TRANSPORT_TMEMPAGEDFACTORY_H_ 1 + +#include "external/google_base/spinlock.h" + +namespace apache { namespace thrift { namespace transport { + +/* + * struct keeps information about memory usage for specific page + */ +struct FixedSizeMemoryPage { + FixedSizeMemoryPage* next_; //!< chain hook + uint8_t buffer_[]; //!< pointer to the buffer +}; + +/** + * Fixed size memory pages factory + * Thread safe + * + */ +class FixedSizeMemoryPageFactory { + public: + /** + * Constructor + */ + FixedSizeMemoryPageFactory(size_t pageSize, //!< page size in bytes + size_t maxMemoryUsage, //!< max memory usage + size_t cacheMemorySize); //!< max memory in cache + /** + * Destructor + */ + ~FixedSizeMemoryPageFactory(); + + /** + * Releases all unused memory + */ + void releaseMemory(); + + /** + * Requests for a page allocation + */ + FixedSizeMemoryPage* getPage(bool throwOnError = true); + + /** + * Returns current page size + */ + size_t getPageSize() const; + + /** + * Returns page back to factory + */ + void returnPage(FixedSizeMemoryPage* page); + private: + const size_t pageSize_; + const size_t maxMemoryUsage_; + const size_t cacheMemorySize_; + size_t numAllocatedPages_; + size_t numCachedPages_; + FixedSizeMemoryPage* cachedPages_; + mutable facebook::SpinLock lock_; +}; + + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TMEMPAGEDFACTORY_H_ diff --git a/thrift/lib/cpp/transport/TMemPagedTransport.h b/thrift/lib/cpp/transport/TMemPagedTransport.h new file mode 100644 index 00000000..d9b4e5b9 --- /dev/null +++ b/thrift/lib/cpp/transport/TMemPagedTransport.h @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TMEMPAGEDTRANSPORT_H_ +#define _THRIFT_TRANSPORT_TMEMPAGEDTRANSPORT_H_ 1 + +#include "thrift/lib/cpp/transport/TVirtualTransport.h" +#include "thrift/lib/cpp/transport/TMemPagedFactory.h" +#include + +namespace apache { namespace thrift { namespace transport { + +using namespace boost; + +/** + * Class TTransport for direct usage of paged memory + * NOT thread safe - for a higher performance trade-off + */ +class TMemPagedTransport : public TVirtualTransport { + public: + /** + * Constructor + */ + TMemPagedTransport(shared_ptr& factory); + + /** + * Destructor + */ + ~TMemPagedTransport(); + + /** + * Whether this transport is open. + */ + virtual bool isOpen(); + + /** + * Opens the transport. + */ + virtual void open(); + + /** + * Closes the transport. + */ + virtual void close(); + + /** + * Called when read is completed. + * This can be over-ridden to perform a transport-specific action + * e.g. logging the request to a file + * + * @return number of bytes read if available, 0 otherwise. + */ + virtual uint32_t readEnd(); + + /** + * Called when write is completed. + * This can be over-ridden to perform a transport-specific action + * at the end of a request. + * + * @return number of bytes written if available, 0 otherwise + */ + virtual uint32_t writeEnd(); + + /** + * Implementations of the base functions + */ + inline uint32_t read(uint8_t* buf, uint32_t len); + inline void write(const uint8_t* buf, uint32_t len); + inline const uint8_t* borrow(uint8_t* buf, uint32_t* len); + inline void consume(uint32_t len); + inline uint32_t readAll(uint8_t* buf, uint32_t len); + /** + * interface extension, not part of the TTrasport + * make sure there are some bytes for write at the same page available + */ + inline uint8_t* reserve(uint32_t* len, bool throwOnError = true); + /** + * interface extension, not part of the TTrasport + * similar to consume but for the write + */ + inline void skip(uint32_t len); + + /** + * Reset buffer for read + * Sets read offset to zero + */ + inline void resetForRead(); + + /** + * Reset buffer for write + * Sets write offset to zero and releases extra memory pages + */ + inline void resetForWrite(bool releaseAllPages = false); + + /** + * Returns number of bytes already read from buffer + */ + inline uint32_t getReadBytes() const; + + /** + * Returns current bytes written in buffer + */ + inline uint32_t getWrittenBytes() const; + + private: + /** + * helper function + * write or skip bytes + */ + inline void set(const uint8_t* buf, uint32_t len); + + /** + * helper function + * read or skip bytes + */ + inline uint32_t get(uint8_t* buf, uint32_t len); + + + private: + shared_ptr factory_; //!< memory pages factory + const uint32_t pageSize_; //!< page size + FixedSizeMemoryPage* headPage_; //!< head of the stack + FixedSizeMemoryPage* currentReadPage_; //!< current read page + uint32_t currentReadOffset_; //!< bytes already read + FixedSizeMemoryPage* currentWritePage_; //!< current write page + uint32_t currentWriteOffset_; //!< bytes already written +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TMEMPAGEDTRANSPORT_H_ diff --git a/thrift/lib/cpp/transport/TMemPagedTransport.tcc b/thrift/lib/cpp/transport/TMemPagedTransport.tcc new file mode 100644 index 00000000..480ec8da --- /dev/null +++ b/thrift/lib/cpp/transport/TMemPagedTransport.tcc @@ -0,0 +1,349 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TMEMPAGEDTRANSPORT_HPP_ +#define _THRIFT_TRANSPORT_TMEMPAGEDTRANSPORT_HPP_ 1 + +#include "thrift/lib/cpp/transport/TMemPagedTransport.h" +#include + +namespace apache { namespace thrift { namespace transport { + +/** + * Reset buffer for read + */ +inline void TMemPagedTransport::resetForRead() { + currentReadPage_ = headPage_; + currentReadOffset_ = 0; +} + +/** + * Reset buffer for write + */ +inline void TMemPagedTransport::resetForWrite(bool releaseAllPages) { + FixedSizeMemoryPage* discardPage = NULL; + if (releaseAllPages) { // release all pages + discardPage = headPage_; + headPage_ = NULL; + } else { // make sure head page left or created + if (!headPage_) { // allocate page if any + headPage_ = factory_->getPage(); + } else { + discardPage = headPage_->next_; + headPage_->next_ = NULL; + } + } + while (discardPage) { + FixedSizeMemoryPage* pageForDeletion = discardPage; + discardPage = discardPage->next_; + factory_->returnPage(pageForDeletion); + } + + // reset + currentReadPage_ = currentWritePage_ = headPage_; + currentReadOffset_ = currentWriteOffset_ = 0; +} + +/** + * Returns number of bytes already read from buffer + */ +inline uint32_t TMemPagedTransport::getReadBytes() const { + uint32_t ret = 0; + FixedSizeMemoryPage* page = headPage_; + while (page) { + if (page == currentReadPage_) { + ret += currentReadOffset_; + break; + } else { + ret += pageSize_; + } + page = page->next_; + } + // return result + return ret; +} + +/** + * Returns current bytes written in buffer + */ +inline uint32_t TMemPagedTransport::getWrittenBytes() const { + uint32_t ret = 0; + FixedSizeMemoryPage* page = headPage_; + while (page) { + if (page == currentWritePage_) { + ret += currentWriteOffset_; + break; + } else { + ret += pageSize_; + } + page = page->next_; + } + // return result + return ret; +} + +/** + * Implementations of the base functions + */ +inline uint32_t TMemPagedTransport::read(uint8_t* buf, uint32_t len) { + if (!buf) { + throw TTransportException(TTransportException::BAD_ARGS); + } + return get(buf, len); +} + +inline void TMemPagedTransport::write(const uint8_t* buf, uint32_t len) { + if (!buf) { + throw TTransportException(TTransportException::BAD_ARGS); + } + set(buf, len); +} + +/** + * interface extension, not part of the TTrasport + * similar to consume but for the write + */ +inline void TMemPagedTransport::skip(uint32_t len) { + set(NULL, len); +} + +inline const uint8_t* TMemPagedTransport::borrow(uint8_t* buf, uint32_t* len) { + // - possible scenarios + // - buf is NULL + // -- available bytes for current page >= len - (return internal pointer) + // -- available bytes for current page < len - return NULL, set len 0 + // - buf is not NULL + // -- available bytes for current page >= len - (return internal pointer) + // -- available bytes for current page < len - copy to the external buffer + FixedSizeMemoryPage* page = currentReadPage_; + uint32_t readOffset = currentReadOffset_; + if (!page) { // no memory available + *len = 0; + return NULL; + } + + uint32_t capacity = *len; // requested capacity + uint32_t available = 0; + if (page == currentWritePage_) { + available = currentWriteOffset_ - readOffset; + } else { + available = pageSize_ - readOffset; + } + + if (available >= capacity) { // enough available bytes + *len = available; // assign available bytes + return page->buffer_ + readOffset; // return readable memory pointer + } + // not enough available bytes on the current page + if (!buf) { // buffer is not provided + *len = 0; + return NULL; + } + // buffer is provided, make memory copy from current page if any + available = std::min(available, capacity); + if (available) { + std::memcpy(buf + *len - capacity, + page->buffer_ + readOffset, + available); + // adjust capacity + capacity -= available; + // adjust offset + readOffset += available; + } + // copy the rest if available + while (capacity) { // read until all buffer filled + if (page == currentWritePage_ && + readOffset == currentWriteOffset_) { + *len = 0; + return NULL; // no more available bytes for read + } else { + // if read and write on the same page + if (page == currentWritePage_) { + available = currentWriteOffset_ - readOffset; + } else if (!(available = pageSize_ - readOffset)) { + // move to next page + page = page->next_; + assert(page); + readOffset = 0; + continue; + } + } + // how many bytes we can read + available = std::min(capacity, available); + // memory copy + std::memcpy(buf + *len - capacity, + page->buffer_ + readOffset, + available); + // adjust capacity + capacity -= available; + // adjust page read offset + readOffset += available; + // move to the next page if end is reached + // and more pages for read available + if (readOffset == pageSize_ && + page != currentWritePage_) { + page = page->next_; + assert(page); + // reset offset + readOffset = 0; + } + } + // return result, leave len as it is + return buf; +} + +/** + * interface extension, not part of the TTrasport + * make sure there are some bytes for write at the same page available + */ +inline uint8_t* TMemPagedTransport::reserve(uint32_t* len, bool throwOnError) { + if (!currentWritePage_ || pageSize_ == currentWriteOffset_) { + FixedSizeMemoryPage* newPage = factory_->getPage(throwOnError); + if (!newPage) { // no memory + return NULL; + } + if (currentWritePage_) { + currentWritePage_->next_ = newPage; + } else { + headPage_ = currentReadPage_ = newPage; + } + currentWritePage_ = newPage; + // reset write offset + currentWriteOffset_ = 0; + } + if (len) { // it can be a call just to reserve a new page + *len = pageSize_ - currentWriteOffset_; + } + + return currentWritePage_->buffer_ + currentWriteOffset_; +} + +inline void TMemPagedTransport::consume(uint32_t len) { + get(NULL, len); +} + +inline uint32_t TMemPagedTransport::readAll(uint8_t* buf, uint32_t len) { + // try to read requested bytes + uint32_t res = read(buf, len); + if (res != len) { // not all bytes can be read + // interface description requires throwing exception + throw TTransportException(TTransportException::END_OF_FILE); + } + return res; +} + + +/** + * helper function + * write or skip bytes + */ +inline void TMemPagedTransport::set(const uint8_t* buf, uint32_t len) { + uint32_t capacity = len; // requested capacity + // prepare for rollback in case of out of memory + FixedSizeMemoryPage* saveWritePage = currentWritePage_; + uint32_t saveWriteOffset = currentWriteOffset_; + while (capacity) { // write until all buffer bytes get sent + uint32_t available = 0; + if (!reserve(&available, false)) { // reserve page if any + // rollback + currentWriteOffset_ = saveWriteOffset; + if ((currentWritePage_ = saveWritePage) != NULL) { // there were pages + // remove extra allocated pages if any + // even we remove previously existed pages it won't hurt + FixedSizeMemoryPage* pageForDelete = saveWritePage->next_; + currentWritePage_->next_ = NULL; // cut the tail + while (pageForDelete) { + saveWritePage = pageForDelete; + pageForDelete = pageForDelete->next_; + factory_->returnPage(saveWritePage); + } + } else { + // remove all pages + resetForWrite(true); + } + // throw + throw TTransportException(TTransportException::INTERNAL_ERROR); + } + // how many bytes we can write + available = std::min(capacity, available); + if (buf) { + // memory copy if any + std::memcpy(currentWritePage_->buffer_ + currentWriteOffset_, + buf + len - capacity, + available); + } + // adjust capacity + capacity -= available; + // adjust page write iterator + currentWriteOffset_ += available; + } // while +} + +/** + * Implementations of the base functions + */ +inline uint32_t TMemPagedTransport::get(uint8_t* buf, uint32_t len) { + uint32_t capacity = len; // requested memory + uint32_t available = 0; + if (!currentReadPage_) { + return 0; // nothing to read, did not reset or write bytes + } + while (capacity) { // read until all buffer filled + if (currentReadPage_ == currentWritePage_) { + // if read and write on the same page + if (!(available = currentWriteOffset_ - currentReadOffset_)) { + break; // no more available bytes for read + } + } else if (!(available = pageSize_ - currentReadOffset_)) { + // not the last page + // move to next page + currentReadPage_ = currentReadPage_->next_; + assert(currentReadPage_); + currentReadOffset_ = 0; + available = pageSize_ - currentReadOffset_; + } + // how many bytes we can read + available = std::min(capacity, available); + // memory copy if any + if (buf) { + std::memcpy(buf + len - capacity, + currentReadPage_->buffer_ + currentReadOffset_, + available); + } + // adjust capacity + capacity -= available; + // adjust page read iterator + currentReadOffset_ += available; + // move to the next page if end is reached + // and more pages for read available + if (currentReadOffset_ == pageSize_ && + currentReadPage_ != currentWritePage_) { + currentReadPage_ = currentReadPage_->next_; + assert(currentReadPage_); + // reset offset + currentReadOffset_ = 0; + } + } + // return result + return len - capacity; +} + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TMEMPAGEDTRANSPORT_HPP_ diff --git a/thrift/lib/cpp/transport/TRpcTransport.h b/thrift/lib/cpp/transport/TRpcTransport.h new file mode 100644 index 00000000..b24e5db9 --- /dev/null +++ b/thrift/lib/cpp/transport/TRpcTransport.h @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TRANSPORT_TRPCTRANSPORT_H_ +#define THRIFT_TRANSPORT_TRPCTRANSPORT_H_ 1 + +#include "thrift/lib/cpp/transport/TTransport.h" + +namespace apache { namespace thrift { namespace transport { + +class TSocketAddress; + +/** + * A TRpcTransport adds a getPeerAddress() method to the base TTransport + * interface. + */ +class TRpcTransport : public TTransport { + public: + /** + * Get the address of the peer to which this transport is connected. + * + * @return Returns a pointer to a TSocketAddress. This struct is owned by + * the TRpcTransport and is guaranteed to remain valid for the + * lifetime of the TRpcTransport. It is guaranteed to return + * non-NULL. (On error, a TTransportException will be raised.) + */ + virtual const TSocketAddress* getPeerAddress() = 0; +}; + +}}} // apache::thrift::transport + +#endif // THRIFT_TRANSPORT_TRPCTRANSPORT_H_ diff --git a/thrift/lib/cpp/transport/TSSLServerSocket.h b/thrift/lib/cpp/transport/TSSLServerSocket.h new file mode 100644 index 00000000..178b362f --- /dev/null +++ b/thrift/lib/cpp/transport/TSSLServerSocket.h @@ -0,0 +1,46 @@ +// Copyright (c) 2009- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TSSLSERVERSOCKET_H_ +#define _THRIFT_TRANSPORT_TSSLSERVERSOCKET_H_ 1 + +#include +#include "thrift/lib/cpp/transport/TServerSocket.h" + +namespace apache { namespace thrift { namespace transport { + +class TSSLSocketFactory; + +/** + * Server socket that accepts SSL connections. + */ +class TSSLServerSocket: public TServerSocket { + public: + /** + * Constructor. + * + * @param port Listening port + * @param factory SSL socket factory implementation + */ + TSSLServerSocket(int port, boost::shared_ptr factory); + /** + * Constructor. + * + * @param port Listening port + * @param sendTimeout Socket send timeout + * @param recvTimeout Socket receive timeout + * @param factory SSL socket factory implementation + */ + TSSLServerSocket(int port, int sendTimeout, int recvTimeout, + boost::shared_ptr factory); + protected: + boost::shared_ptr createSocket(int socket); + boost::shared_ptr factory_; +}; + +}}} + +#endif diff --git a/thrift/lib/cpp/transport/TSSLSocket.h b/thrift/lib/cpp/transport/TSSLSocket.h new file mode 100644 index 00000000..66131b87 --- /dev/null +++ b/thrift/lib/cpp/transport/TSSLSocket.h @@ -0,0 +1,365 @@ +// Copyright (c) 2009- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef THRIFT_TRANSPORT_TSSLSOCKET_H_ +#define THRIFT_TRANSPORT_TSSLSOCKET_H_ 1 + +#include +#include +#include +#include "thrift/lib/cpp/concurrency/Mutex.h" +#include "thrift/lib/cpp/transport/TSocket.h" + +namespace apache { namespace thrift { namespace transport { + +class PasswordCollector; +class SSLContext; +class TSocketAddress; + +/** + * OpenSSL implementation for SSL socket interface. + */ +class TSSLSocket: public TVirtualTransport { + public: + /** + * Constructor. + */ + explicit TSSLSocket(const boost::shared_ptr& ctx); + /** + * Constructor, create an instance of TSSLSocket given an existing socket. + * + * @param socket An existing socket + */ + TSSLSocket(const boost::shared_ptr& ctx, int socket); + /** + * Constructor. + * + * @param host Remote host name + * @param port Remote port number + */ + TSSLSocket(const boost::shared_ptr& ctx, + const std::string& host, + int port); + /** + * Constructor. + */ + TSSLSocket(const boost::shared_ptr& ctx, + const TSocketAddress& address); + /** + * Destructor. + */ + ~TSSLSocket(); + + /** + * TTransport interface. + */ + bool isOpen(); + bool peek(); + void open(); + void close(); + uint32_t read(uint8_t* buf, uint32_t len); + void write(const uint8_t* buf, uint32_t len); + void flush(); + + /** + * Set whether to use client or server side SSL handshake protocol. + * + * @param flag Use server side handshake protocol if true. + */ + void server(bool flag) { server_ = flag; } + /** + * Determine whether the SSL socket is server or client mode. + */ + bool server() const { return server_; } + +protected: + /** + * Verify peer certificate after SSL handshake completes. + */ + virtual void verifyCertificate(); + + /** + * Initiate SSL handshake if not already initiated. + */ + void checkHandshake(); + + bool server_; + SSL* ssl_; + boost::shared_ptr ctx_; +}; + +/** + * SSL socket factory. SSL sockets should be created via SSL factory. + */ +class TSSLSocketFactory { + public: + /** + * Constructor/Destructor + */ + explicit TSSLSocketFactory(const boost::shared_ptr& context); + virtual ~TSSLSocketFactory(); + + /** + * Create an instance of TSSLSocket with a fresh new socket. + */ + virtual boost::shared_ptr createSocket(); + /** + * Create an instance of TSSLSocket with the given socket. + * + * @param socket An existing socket. + */ + virtual boost::shared_ptr createSocket(int socket); + /** + * Create an instance of TSSLSocket. + * + * @param host Remote host to be connected to + * @param port Remote port to be connected to + */ + virtual boost::shared_ptr createSocket(const std::string& host, + int port); + /** + * Set/Unset server mode. + * + * @param flag Server mode if true + */ + virtual void server(bool flag) { server_ = flag; } + /** + * Determine whether the socket is in server or client mode. + * + * @return true, if server mode, or, false, if client mode + */ + virtual bool server() const { return server_; } + + private: + boost::shared_ptr ctx_; + bool server_; +}; + +/** + * SSL exception. + */ +class TSSLException: public TTransportException { + public: + explicit TSSLException(const std::string& message): + TTransportException(TTransportException::INTERNAL_ERROR, message) {} + + virtual const char* what() const throw() { + if (message_.empty()) { + return "TSSLException"; + } else { + return message_.c_str(); + } + } +}; + +/** + * Wrap OpenSSL SSL_CTX into a class. + */ +class SSLContext { + public: + + enum SSLVersion { + SSLv2, + SSLv3, + TLSv1 + }; + + /** + * Constructor. + * + * @param version The lowest or oldest SSL version to support. + */ + explicit SSLContext(SSLVersion version = TLSv1); + virtual ~SSLContext(); + + /** + * Set ciphers to be used in SSL handshake process. + * + * @param ciphers A list of ciphers + */ + virtual void ciphers(const std::string& enable); + /** + * Enable/Disable authentication. Peer name validation can only be done + * if checkPeerCert is true. + * + * @param checkPeerCert If true, require peer to present valid certificate + * @param checkPeerName If true, validate that the certificate common name + * or alternate name(s) of peer matches the hostname + * used to connect. + * @param peerName If non-empty, validate that the certificate common + * name of peer matches the given string (altername + * name(s) are not used in this case). + */ + virtual void authenticate(bool checkPeerCert, bool checkPeerName, + const std::string& peerName = std::string()); + /** + * Load server certificate. + * + * @param path Path to the certificate file + * @param format Certificate file format + */ + virtual void loadCertificate(const char* path, const char* format = "PEM"); + /** + * Load private key. + * + * @param path Path to the private key file + * @param format Private key file format + */ + virtual void loadPrivateKey(const char* path, const char* format = "PEM"); + /** + * Load trusted certificates from specified file. + * + * @param path Path to trusted certificate file + */ + virtual void loadTrustedCertificates(const char* path); + /** + * Load trusted certificates from specified X509 certificate store. + * + * @param store X509 certificate store. + */ + virtual void loadTrustedCertificates(X509_STORE* store); + /** + * Default randomize method. + */ + virtual void randomize(); + /** + * Override default OpenSSL password collector. + * + * @param collector Instance of user defined password collector + */ + virtual void passwordCollector(boost::shared_ptr collector); + /** + * Obtain password collector. + * + * @return User defined password collector + */ + virtual boost::shared_ptr passwordCollector() { + return collector_; + } + + /** + * Create an SSL object from this context. + */ + SSL* createSSL() const; + + /** + * Possibly validate the peer's certificate name, depending on how this + * SSLContext was configured by authenticate(). + * + * @return True if the peer's name is acceptable, false otherwise + */ + bool validatePeerName(TSSLSocket* sock, SSL* ssl) const; + + /** + * Set the options on the SSL_CTX object. + */ + void setOptions(long options); + +#ifdef OPENSSL_NPN_NEGOTIATED + /** + * Set the list of protocols that a TLS server should advertise for + * Next Protocol Negotiation (NPN). + * + * @param protocols List of protocol names, or NULL to disable NPN. + * Note: if non-null, this method makes a copy, so + * the caller needn't keep the list in scope after + * the call completes. + */ + void setAdvertisedNextProtocols(const std::list* protocols); +#endif // OPENSSL_NPN_NEGOTIATED + + /** + * Gets the underlying SSL_CTX for advanced usage + */ + SSL_CTX *getSSLCtx() const { + return ctx_; + } + + enum SSLLockType { + LOCK_MUTEX, + LOCK_SPINLOCK, + LOCK_NONE + }; + + /** + * Set preferences for how to treat locks in OpenSSL. This must be + * called before the instantiation of any SSLContext objects, otherwise + * the defaults will be used. + * + * OpenSSL has a lock for each module rather than for each object or + * data that needs locking. Some locks protect only refcounts, and + * might be better as spinlocks rather than mutexes. Other locks + * may be totally unnecessary if the objects being protected are not + * shared between threads in the application. + * + * By default, all locks are initialized as mutexes. OpenSSL's lock usage + * may change from version to version and you should know what you are doing + * before disabling any locks entirely. + * + * Example: if you don't share SSL sessions between threads in your + * application, you may be able to do this + * + * setSSLLockTypes({{CRYPTO_LOCK_SSL_SESSION, SSLContext::LOCK_NONE}}) + */ + static void setSSLLockTypes(std::map lockTypes); + + protected: + SSL_CTX* ctx_; + + private: + bool checkPeerName_; + std::string peerFixedName_; + boost::shared_ptr collector_; + + static concurrency::Mutex mutex_; + static uint64_t count_; + +#ifdef OPENSSL_NPN_NEGOTIATED + /** + * Wire-format list of advertised protocols for use in NPN. + */ + unsigned char* advertisedNextProtocols_; + unsigned advertisedNextProtocolsLength_; + + static int advertisedNextProtocolCallback(SSL* ssl, + const unsigned char** out, unsigned int* outlen, void* data); +#endif // OPENSSL_NPN_NEGOTIATED + + static int passwordCallback(char* password, int size, int, void* data); + + static void initializeOpenSSL(); + static void cleanupOpenSSL(); + + /** + * Helper to match a hostname versus a pattern. + */ + static bool matchName(const char* host, const char* pattern, int size); +}; + +typedef boost::shared_ptr SSLContextPtr; + +/** + * Override the default password collector. + */ +class PasswordCollector { + public: + virtual ~PasswordCollector() {} + /** + * Interface for customizing how to collect private key password. + * + * By default, OpenSSL prints a prompt on screen and request for password + * while loading private key. To implement a custom password collector, + * implement this interface and register it with TSSLSocketFactory. + * + * @param password Pass collected password back to OpenSSL + * @param size Maximum length of password including NULL character + */ + virtual void getPassword(std::string& password, int size) = 0; +}; + +}}} + +#endif diff --git a/thrift/lib/cpp/transport/TServerSocket.h b/thrift/lib/cpp/transport/TServerSocket.h new file mode 100644 index 00000000..992b92d4 --- /dev/null +++ b/thrift/lib/cpp/transport/TServerSocket.h @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TSERVERSOCKET_H_ +#define _THRIFT_TRANSPORT_TSERVERSOCKET_H_ 1 + +#include "thrift/lib/cpp/transport/TServerTransport.h" +#include + +namespace apache { namespace thrift { namespace transport { + +class TSocket; + +/** + * Server socket implementation of TServerTransport. Wrapper around a unix + * socket listen and accept calls. + * + */ +class TServerSocket : public TServerTransport { + public: + TServerSocket(int port); + TServerSocket(int port, int sendTimeout, int recvTimeout); + + ~TServerSocket(); + + int getPort() const { return port_; } + + void setSendTimeout(int sendTimeout); + void setRecvTimeout(int recvTimeout); + + void setAcceptTimeout(int accTimeout); + + void setRetryLimit(int retryLimit); + void setRetryDelay(int retryDelay); + + void setTcpSendBuffer(int tcpSendBuffer); + void setTcpRecvBuffer(int tcpRecvBuffer); + + void listen(); + void close(); + + void interrupt(); + + void getAddress(TSocketAddress* address); + + protected: + boost::shared_ptr acceptImpl(); + virtual boost::shared_ptr createSocket(int client); + + private: + int port_; + int serverSocket_; + int acceptBacklog_; + int sendTimeout_; + int recvTimeout_; + int accTimeout_; + int retryLimit_; + int retryDelay_; + int tcpSendBuffer_; + int tcpRecvBuffer_; + + int intSock1_; + int intSock2_; +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TSERVERSOCKET_H_ diff --git a/thrift/lib/cpp/transport/TServerTransport.h b/thrift/lib/cpp/transport/TServerTransport.h new file mode 100644 index 00000000..cf275a86 --- /dev/null +++ b/thrift/lib/cpp/transport/TServerTransport.h @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TSERVERTRANSPORT_H_ +#define _THRIFT_TRANSPORT_TSERVERTRANSPORT_H_ 1 + +#include "thrift/lib/cpp/transport/TRpcTransport.h" +#include "thrift/lib/cpp/transport/TTransportException.h" +#include + +namespace apache { namespace thrift { namespace transport { + +/** + * Server transport framework. A server needs to have some facility for + * creating base transports to read/write from. + * + */ +class TServerTransport { + public: + virtual ~TServerTransport() {} + + /** + * Starts the server transport listening for new connections. Prior to this + * call most transports will not return anything when accept is called. + * + * @throws TTransportException if we were unable to listen + */ + virtual void listen() {} + + /** + * Gets a new dynamically allocated transport object and passes it to the + * caller. Note that it is the explicit duty of the caller to free the + * allocated object. The returned TRpcTransport object must always be in the + * opened state. NULL should never be returned, instead an Exception should + * always be thrown. + * + * @return A new TRpcTransport object + * @throws TTransportException if there is an error + */ + boost::shared_ptr accept() { + boost::shared_ptr result = acceptImpl(); + if (result == NULL) { + throw TTransportException("accept() may not return NULL"); + } + return result; + } + + /** + * For "smart" TServerTransport implementations that work in a multi + * threaded context this can be used to break out of an accept() call. + * It is expected that the transport will throw a TTransportException + * with the interrupted error code. + */ + virtual void interrupt() {} + + /** + * Closes this transport such that future calls to accept will do nothing. + */ + virtual void close() = 0; + + /** + * Get the address on which this transport is listening. + * + * Should only be called after calling listen(). May raise + * TTransportException on error. + * + * @param address The server's address will be stored in the TSocketAddress + * pointed to by this argument. + */ + virtual void getAddress(TSocketAddress* address) = 0; + + protected: + TServerTransport() {} + + /** + * Subclasses should implement this function for accept. + * + * @return A newly allocated TRpcTransport object + * @throw TTransportException If an error occurs + */ + virtual boost::shared_ptr acceptImpl() = 0; + +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TSERVERTRANSPORT_H_ diff --git a/thrift/lib/cpp/transport/TShortReadTransport.h b/thrift/lib/cpp/transport/TShortReadTransport.h new file mode 100644 index 00000000..cdfc35a0 --- /dev/null +++ b/thrift/lib/cpp/transport/TShortReadTransport.h @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TSHORTREADTRANSPORT_H_ +#define _THRIFT_TRANSPORT_TSHORTREADTRANSPORT_H_ 1 + +#include + +#include "thrift/lib/cpp/transport/TTransport.h" +#include "thrift/lib/cpp/transport/TVirtualTransport.h" + +namespace apache { namespace thrift { namespace transport { namespace test { + +/** + * This class is only meant for testing. It wraps another transport. + * Calls to read are passed through with some probability. Otherwise, + * the read amount is randomly reduced before being passed through. + * + */ +class TShortReadTransport : public TVirtualTransport { + public: + TShortReadTransport(boost::shared_ptr transport, double full_prob) + : transport_(transport) + , fullProb_(full_prob) + {} + + bool isOpen() { + return transport_->isOpen(); + } + + bool peek() { + return transport_->peek(); + } + + void open() { + transport_->open(); + } + + void close() { + transport_->close(); + } + + uint32_t read(uint8_t* buf, uint32_t len) { + if (len == 0) { + return 0; + } + + if (rand()/(double)RAND_MAX >= fullProb_) { + len = 1 + rand()%len; + } + return transport_->read(buf, len); + } + + void write(const uint8_t* buf, uint32_t len) { + transport_->write(buf, len); + } + + void flush() { + transport_->flush(); + } + + const uint8_t* borrow(uint8_t* buf, uint32_t* len) { + return transport_->borrow(buf, len); + } + + void consume(uint32_t len) { + return transport_->consume(len); + } + + boost::shared_ptr getUnderlyingTransport() { + return transport_; + } + + protected: + boost::shared_ptr transport_; + double fullProb_; +}; + +}}}} // apache::thrift::transport::test + +#endif // #ifndef _THRIFT_TRANSPORT_TSHORTREADTRANSPORT_H_ diff --git a/thrift/lib/cpp/transport/TSimpleFileTransport.h b/thrift/lib/cpp/transport/TSimpleFileTransport.h new file mode 100644 index 00000000..6bfb879a --- /dev/null +++ b/thrift/lib/cpp/transport/TSimpleFileTransport.h @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TSIMPLEFILETRANSPORT_H_ +#define _THRIFT_TRANSPORT_TSIMPLEFILETRANSPORT_H_ 1 + +#include "thrift/lib/cpp/transport/TFDTransport.h" + +namespace apache { namespace thrift { namespace transport { + +/** + * Dead-simple wrapper around a file. + * + * @param path file name and path + * @param read whether to open file for reading + * @param write whether to open file for writing(using O_APPEND) + * + * @author David Braginsky + */ +class TSimpleFileTransport : public TFDTransport { + public: + TSimpleFileTransport(const std::string& path, + bool read = true, + bool write = false); +}; + +}}} // apache::thrift::transport + +#endif // _THRIFT_TRANSPORT_TSIMPLEFILETRANSPORT_H_ diff --git a/thrift/lib/cpp/transport/TSocket.h b/thrift/lib/cpp/transport/TSocket.h new file mode 100644 index 00000000..62bad5aa --- /dev/null +++ b/thrift/lib/cpp/transport/TSocket.h @@ -0,0 +1,382 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TSOCKET_H_ +#define _THRIFT_TRANSPORT_TSOCKET_H_ 1 + +#include +#include + +#include "thrift/lib/cpp/transport/TRpcTransport.h" +#include "thrift/lib/cpp/transport/TVirtualTransport.h" +#include "thrift/lib/cpp/transport/TServerSocket.h" +#include "thrift/lib/cpp/transport/TSocketAddress.h" + +namespace apache { namespace thrift { namespace transport { + +/** + * TCP Socket implementation of the TTransport interface. + * + */ +class TSocket : public TVirtualTransport< TSocket, + TTransportDefaults > { + +public: + /** + * Struct that contains socket options related stuff + */ + struct Options { + + Options(): + connTimeout(0), + sendTimeout(0), + recvTimeout(0), + sendBufSize(0), + recvBufSize(0), + lingerOn(false), + lingerVal(0), + noDelay(true), + reuseAddr(false) { + } + + /** Connect timeout in ms */ + int connTimeout; + + /** Send timeout in ms */ + int sendTimeout; + + /** Recv timeout in ms */ + int recvTimeout; + + /** Send Buffer Size in Bytes */ + size_t sendBufSize; + + /** Recv Buffer Size in Bytes */ + size_t recvBufSize; + + /** Linger on */ + bool lingerOn; + + /** Linger val */ + int lingerVal; + + /** Nodelay */ + bool noDelay; + + /** SO_REUSEADDR **/ + bool reuseAddr; + }; + + /** + * Constructs a new socket. Note that this does NOT actually connect the + * socket. + * + */ + TSocket(); + + /** + * Constructs a new socket. Note that this does NOT actually connect the + * socket. + * + * If a hostname is provided, and it resolves to multiple IPs, connect() will + * attempt to connect to each one in sequence, until one connection succeeds. + * + * @param host An IP address or hostname to connect to + * @param port The port to connect on + */ + TSocket(std::string host, int port); + + /** + * Constructs a new socket. Note that this does NOT actually connect the + * socket. + * + * @param adddress The address to connect to + */ + explicit TSocket(const TSocketAddress* address); + + /** + * Constructs a new socket. Note that this does NOT actually connect the + * socket. + * + * @param adddress The address to connect to + */ + explicit TSocket(const TSocketAddress& address); + + /** + * Constructor to create socket from raw UNIX handle. + * + * This is used by the TServerSocket class to create a TSocket from file + * descriptors returned by accept(). + */ + explicit TSocket(int socket); + + + /** + * Destroyes the socket object, closing it if necessary. + */ + virtual ~TSocket(); + + /** + * Whether the socket is alive. + * + * @return Is the socket alive? + */ + bool isOpen(); + + /** + * Calls select on the socket to see if there is more data available. + */ + bool peek(); + + /** + * Creates and opens the UNIX socket. + * + * @throws TTransportException If the socket could not connect + */ + virtual void open(); + + /** + * Shuts down communications on the socket. + */ + virtual void close(); + + /** + * Reads from the underlying socket. + */ + uint32_t read(uint8_t* buf, uint32_t len); + + /** + * Writes to the underlying socket. Loops until done or fail. + */ + void write(const uint8_t* buf, uint32_t len); + + /** + * Writes to the underlying socket. Does single send() and returns result. + */ + uint32_t write_partial(const uint8_t* buf, uint32_t len); + + /** + * Get the host that the socket is connected to + * + * @return string host identifier + */ + std::string getHost(); + + /** + * Get the port that the socket is connected to + * + * @return int port number + */ + int getPort(); + + /** + * Set the host that socket will connect to + * + * @param host host identifier + */ + void setHost(std::string host); + + /** + * Set the port that socket will connect to + * + * @param port port number + */ + void setPort(int port); + + + /** + * Sets the socket options enabled in the + * TSocket::Options object options_; + * Note you can try to individually set any option + * using the methods provided below e.g. setSendBufSize + */ + void setSocketOptions(const Options& oh ); + + /** + * get the options_ object + * + * @return TSocket::Options options_; + */ + TSocket::Options getSocketOptions(); + + /** + * get the currently set socket options + * this function returns the currently set socket options + * using the getsockopt() function rather than trusting + * what is set in the options_ member + * setting socket options via setSocketOption calls can fail + * because of settings in the sysctl + * e.g. trying to set the sendBufSize to some value greater + * than the wmem_max value in sysctl + * + * @return TSocket::Options + */ + TSocket::Options getCurrentSocketOptions(); + + /** + * Controls whether the linger option is set on the socket. + * + * @param on Whether SO_LINGER is on + * @param linger If linger is active, the number of seconds to linger for + */ + void setLinger(bool on, int linger); + + /** + * Whether to enable/disable Nagle's algorithm. + * + * @param noDelay Whether or not to disable the algorithm. + * @return + */ + void setNoDelay(bool noDelay); + + /** + * Set the connect timeout + */ + void setConnTimeout(int ms); + + /** + * Set the receive timeout + */ + void setRecvTimeout(int ms); + + /** + * Set the send bufsize + */ + void setSendBufSize(size_t bufsize); + + /** + * Set the recv bufsize + */ + void setRecvBufSize(size_t bufsize); + + /** + * Set the send timeout + */ + void setSendTimeout(int ms); + + /** + * Set the max number of recv retries in case of an EAGAIN + * error + */ + void setMaxRecvRetries(int maxRecvRetries); + + /** + * Set the SO_REUSEADDR socket option. + */ + void setReuseAddress(bool reuseAddr); + + /** + * Get socket information formated as a string + */ + std::string getSocketInfo(); + + /* + * Returns the address of the host to which the socket is connected + */ + const TSocketAddress* getPeerAddress(); + + /** + * Returns the DNS name of the host to which the socket is connected + */ + std::string getPeerHost(); + + /** + * Returns a string representation of the IP address to which the + * socket is connected + */ + std::string getPeerAddressStr(); + + /** + * Returns the port of the host to which the socket is connected + **/ + uint16_t getPeerPort(); + + /** + * Returns the underlying socket file descriptor. + */ + int getSocketFD() { + return socket_; + } + + /** + * (Re-)initialize a TSocket for the supplied descriptor. This is only + * intended for use by TNonblockingServer -- other use may result in + * unfortunate surprises. + * + * @param fd the descriptor for an already-connected socket + */ + void setSocketFD(int fd); + + /** + * Sets whether to use a low minimum TCP retransmission timeout. + */ + static void setUseLowMinRto(bool useLowMinRto); + + /** + * Gets whether to use a low minimum TCP retransmission timeout. + */ + static bool getUseLowMinRto(); + + /** + * Set a cache of the peer address (used when trivially available: e.g. + * accept() or connect()). Only caches IPV4 and IPV6; unset for others. + */ + void setCachedAddress(const sockaddr* addr, socklen_t len); + + protected: + /** connect, called by open */ + void openConnection(struct addrinfo *res); + + /** Host to connect to */ + std::string host_; + + /** Peer hostname */ + std::string peerHost_; + + /** Peer address */ + std::string peerAddressStr_; + + /** Port number to connect on */ + int port_; + + /** Underlying UNIX socket handle */ + int socket_; + + /** Socket Options Helper */ + Options options_; + + /** Recv EGAIN retries */ + int maxRecvRetries_; + + /** Cached peer address */ + TSocketAddress cachedPeerAddr_; + + /** Connection start time */ + timespec startTime_; + + /** Whether to use low minimum TCP retransmission timeout */ + static bool useLowMinRto_; +}; + +std::ostream& operator<<(std::ostream& os, const TSocket::Options& o); + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TSOCKET_H_ + diff --git a/thrift/lib/cpp/transport/TSocketAddress.h b/thrift/lib/cpp/transport/TSocketAddress.h new file mode 100644 index 00000000..a1ad514c --- /dev/null +++ b/thrift/lib/cpp/transport/TSocketAddress.h @@ -0,0 +1,646 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_TRANSPORT_TSOCKETADDRESS_H_ +#define THRIFT_TRANSPORT_TSOCKETADDRESS_H_ 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace apache { namespace thrift { namespace transport { + +class TSocketAddress { + public: + TSocketAddress() { + storage_.addr.sa_family = AF_UNSPEC; + } + + /** + * Construct a TSocketAddress from a hostname and port. + * + * Note: If the host parameter is not a numeric IP address, hostname + * resolution will be performed, which can be quite slow. + * + * Raises TTransportException on error. + * + * @param host The IP address (or hostname, if allowNameLookup is true) + * @param port The port (in host byte order) + * @pram allowNameLookup If true, attempt to perform hostname lookup + * if the hostname does not appear to be a numeric IP address. + * This is potentially a very slow operation, so is disabled by + * default. + */ + TSocketAddress(const char* host, uint16_t port, + bool allowNameLookup = false) { + // Initialize the address family first, + // since setFromHostPort() and setFromIpPort() will check it. + storage_.addr.sa_family = AF_UNSPEC; + + if (allowNameLookup) { + setFromHostPort(host, port); + } else { + setFromIpPort(host, port); + } + } + + TSocketAddress(const std::string& host, uint16_t port, + bool allowNameLookup = false) { + // Initialize the address family first, + // since setFromHostPort() and setFromIpPort() will check it. + storage_.addr.sa_family = AF_UNSPEC; + + if (allowNameLookup) { + setFromHostPort(host.c_str(), port); + } else { + setFromIpPort(host.c_str(), port); + } + } + + TSocketAddress(const TSocketAddress& addr) { + storage_ = addr.storage_; + if (addr.getFamily() == AF_UNIX) { + storage_.un.init(addr.storage_.un); + } + } + + TSocketAddress& operator=(const TSocketAddress& addr) { + if (getFamily() != AF_UNIX) { + if (addr.getFamily() != AF_UNIX) { + storage_ = addr.storage_; + } else { + storage_ = addr.storage_; + storage_.un.init(addr.storage_.un); + } + } else { + if (addr.getFamily() == AF_UNIX) { + storage_.un.copy(addr.storage_.un); + } else { + storage_.un.free(); + storage_ = addr.storage_; + } + } + return *this; + } + +#if __GXX_EXPERIMENTAL_CXX0X__ + TSocketAddress(TSocketAddress&& addr) { + storage_ = addr.storage_; + addr.storage_.addr.sa_family = AF_UNSPEC; + } + +#if __GNUC_PREREQ(4, 5) + TSocketAddress& operator=(TSocketAddress&& addr) { + std::swap(storage_, addr.storage_); + return *this; + } +#endif +#endif + + ~TSocketAddress() { + if (storage_.addr.sa_family == AF_UNIX) { + storage_.un.free(); + } + } + + bool isInitialized() const { + return (storage_.addr.sa_family != AF_UNSPEC); + } + + /** + * Return whether this address is within private network. + * + * According to RFC1918, the 10/8 prefix, 172.16/12 prefix, and 192.168/16 + * prefix are reserved for private networks. + * fc00::/7 is the IPv6 version, defined in RFC4139. IPv6 link-local + * addresses (fe80::/10) are also considered private addresses. + * + * The loopback addresses 127/8 and ::1 are also regarded as private networks + * for the purpose of this function. + * + * Returns true if this is a private network address, and false otherwise. + */ + bool isPrivateAddress() const; + + /** + * Return whether this address is a loopback address. + */ + bool isLoopbackAddress() const; + + void reset() { + prepFamilyChange(AF_UNSPEC); + storage_.addr.sa_family = AF_UNSPEC; + } + + /** + * Initialize this TSocketAddress from a hostname and port. + * + * Note: If the host parameter is not a numeric IP address, hostname + * resolution will be performed, which can be quite slow. + * + * If the hostname resolves to multiple addresses, only the first will be + * returned. + * + * Raises TTransportException on error. + * + * @param host The hostname or IP address + * @param port The port (in host byte order) + */ + void setFromHostPort(const char* host, uint16_t port); + + void setFromHostPort(const std::string& host, uint16_t port) { + setFromHostPort(host.c_str(), port); + } + + /** + * Initialize this TSocketAddress from an IP address and port. + * + * This is similar to setFromHostPort(), but only accepts numeric IP + * addresses. If the IP string does not look like an IP address, it throws a + * TTransportException rather than trying to perform a hostname resolution. + * + * Raises TTransportException on error. + * + * @param ip The IP address, as a human-readable string. + * @param port The port (in host byte order) + */ + void setFromIpPort(const char* ip, uint16_t port); + + void setFromIpPort(const std::string& ip, uint16_t port) { + setFromIpPort(ip.c_str(), port); + } + + /** + * Initialize this TSocketAddress from a local port number. + * + * This is intended to be used by server code to determine the address to + * listen on. + * + * If the current machine has any IPv6 addresses configured, an IPv6 address + * will be returned (since connections from IPv4 clients can be mapped to the + * IPv6 address). If the machine does not have any IPv6 addresses, an IPv4 + * address will be returned. + */ + void setFromLocalPort(uint16_t port); + + /** + * Initialize this TSocketAddress from a local port number. + * + * This version of setFromLocalPort() accepts the port as a string. A + * TTransportException will be raised if the string does not refer to a port + * number. Non-numeric service port names are not accepted. + */ + void setFromLocalPort(const char* port); + void setFromLocalPort(const std::string& port) { + return setFromLocalPort(port.c_str()); + } + + /** + * Initialize this TSocketAddress from a local port number and optional IP + * address. + * + * The addressAndPort string may be specified either as ":", or + * just as "". If the IP is not specified, the address will be + * initialized to 0, so that a server socket bound to this address will + * accept connections on all local IP addresses. + * + * Both the IP address and port number must be numeric. DNS host names and + * non-numeric service port names are not accepted. + */ + void setFromLocalIpPort(const char* addressAndPort); + void setFromLocalIpPort(const std::string& addressAndPort) { + return setFromLocalIpPort(addressAndPort.c_str()); + } + + /** + * Initialize this TSocketAddress from an IP address and port number. + * + * The addressAndPort string must be of the form ":". E.g., + * "10.0.0.1:1234". + * + * Both the IP address and port number must be numeric. DNS host names and + * non-numeric service port names are not accepted. + */ + void setFromIpPort(const char* addressAndPort); + void setFromIpPort(const std::string& addressAndPort) { + return setFromIpPort(addressAndPort.c_str()); + } + + /** + * Initialize this TSocketAddress from a host name and port number. + * + * The addressAndPort string must be of the form ":". E.g., + * "www.facebook.com:443". + * + * If the host name is not a numeric IP address, a DNS lookup will be + * performed. Beware that the DNS lookup may be very slow. The port number + * must be numeric; non-numeric service port names are not accepted. + */ + void setFromHostPort(const char* hostAndPort); + void setFromHostPort(const std::string& hostAndPort) { + return setFromHostPort(hostAndPort.c_str()); + } + + /** + * Initialize this TSocketAddress from a local unix path. + * + * Raises TTransportException on error. + */ + void setFromPath(const char* path) { + setFromPath(path, strlen(path)); + } + + void setFromPath(const std::string& path) { + setFromPath(path.data(), path.length()); + } + + void setFromPath(const char* path, size_t length); + + /** + * Initialize this TSocketAddress from a socket's peer address. + * + * Raises TTransportException on error. + */ + void setFromPeerAddress(int socket); + + /** + * Initialize this TSocketAddress from a socket's local address. + * + * Raises TTransportException on error. + */ + void setFromLocalAddress(int socket); + + /** + * Initialize this TSocketAddress from a struct sockaddr. + * + * Raises TTransportException on error. + * + * This method is not supported for AF_UNIX addresses. For unix addresses, + * the address length must be explicitly specified. + * + * @param address A struct sockaddr. The size of the address is implied + * from address->sa_family. + */ + void setFromSockaddr(const struct sockaddr* address); + + /** + * Initialize this TSocketAddress from a struct sockaddr. + * + * Raises TTransportException on error. + * + * @param address A struct sockaddr. + * @param addrlen The length of address data available. This must be long + * enough for the full address type required by + * address->sa_family. + */ + void setFromSockaddr(const struct sockaddr* address, + socklen_t addrlen); + + /** + * Initialize this TSocketAddress from a struct sockaddr_in. + */ + void setFromSockaddr(const struct sockaddr_in* address); + + /** + * Initialize this TSocketAddress from a struct sockaddr_in6. + */ + void setFromSockaddr(const struct sockaddr_in6* address); + + /** + * Initialize this TSocketAddress from a struct sockaddr_un. + * + * Note that the addrlen parameter is necessary to properly detect anonymous + * addresses, which have 0 valid path bytes, and may not even have a NUL + * character at the start of the path. + * + * @param address A struct sockaddr_un. + * @param addrlen The length of address data. This should include all of + * the valid bytes of sun_path, not including any NUL + * terminator. + */ + void setFromSockaddr(const struct sockaddr_un* address, + socklen_t addrlen); + + /** + * Get a pointer to the struct sockaddr data that can be used for manually + * modifying the data. + * + * addressUpdated() must be called after you finish modifying the socket data + * before you perform any other operations on the TSocketAddress. + * + * For example, to use this to store the address returned by an accept() + * call: + * + * socklen_t addrlen; + * struct sockaddr *storage = addr.getMutableAddress(AF_INET, &addrlen); + * int newSock = accept(sock, storage, &addrlen); + * if (newSock < 0) { + * // error handling + * } + * addr.addressUpdated(AF_INET, addrlen); + * + * @param family The type of address data you plan to put in the + * sockaddr. This is necessary since some address families + * require more storage than others. + * @param sizeReturn The length of the returned sockaddr will be returned via + * this argument. + */ + struct sockaddr* getMutableAddress(sa_family_t family, + socklen_t *sizeReturn); + + /** + * Indicate that the address data was updated after a call to + * getMutableAddress(). + * + * @param expectedFamily This must be the same value that you passed to + * the getMutableAddress() call. This is used to + * verify that the address data written into the + * sockaddr is actually of the same type that you + * specified when you called getMutableAddress(). + * @param addrlen The length of the new address data written into the + * sockaddr. + */ + void addressUpdated(sa_family_t expectedFamily, socklen_t addrlen) { + if (getFamily() != expectedFamily) { + // This should pretty much never happen. + addressUpdateFailure(expectedFamily); + } + if (getFamily() == AF_UNIX) { + updateUnixAddressLength(addrlen); + } + } + + const struct sockaddr* getAddress() const { + if (getFamily() != AF_UNIX) { + return &storage_.addr; + } else { + return reinterpret_cast(storage_.un.addr); + } + } + + /** + * Return the total number of bytes available for address storage. + */ + socklen_t getStorageSize() const { + if (getFamily() != AF_UNIX) { + return sizeof(storage_); + } else { + return sizeof(*storage_.un.addr); + } + } + + /** + * Return the number of bytes actually used for this address. + * + * For an uninitialized socket, this returns sizeof(struct sockaddr), + * even though some of those bytes may not be initialized. + */ + socklen_t getActualSize() const; + + sa_family_t getFamily() const { + return storage_.addr.sa_family; + } + + /** + * Get a string representation of the IPv4 or IPv6 address. + * + * Raises TTransportException if an error occurs (for example, if the address + * is not an IPv4 or IPv6 address). + */ + std::string getAddressStr() const; + + /** + * Get a string representation of the IPv4 or IPv6 address. + * + * Raises TTransportException if an error occurs (for example, if the address + * is not an IPv4 or IPv6 address). + */ + void getAddressStr(char* buf, size_t buflen) const; + + /** + * Get the IPv4 or IPv6 port for this address. + * + * Raises TTransportException if this is not an IPv4 or IPv6 address. + * + * @return Returns the port, in host byte order. + */ + uint16_t getPort() const; + + /** + * Set the IPv4 or IPv6 port for this address. + * + * Raises TTransportException if this is not an IPv4 or IPv6 address. + */ + void setPort(uint16_t port); + + /** + * Return true if this is an IPv4-mapped IPv6 address. + */ + bool isIPv4Mapped() const { + return (storage_.addr.sa_family == AF_INET6 && + IN6_IS_ADDR_V4MAPPED(&storage_.ipv6.sin6_addr)); + } + + /** + * Convert an IPv4-mapped IPv6 address to an IPv4 address. + * + * Raises TTransportException if this is not an IPv4-mapped IPv6 address. + */ + void convertToIPv4(); + + /** + * Try to convert an address to IPv4. + * + * This attempts to convert an address to an IPv4 address if possible. + * If the address is an IPv4-mapped IPv6 address, it is converted to an IPv4 + * address and true is returned. Otherwise nothing is done, and false is + * returned. + */ + bool tryConvertToIPv4(); + + /** + * Get string representation of the host name (or IP address if the host name + * cannot be resolved). + * + * Warning: Using this method is strongly discouraged. It performs a + * DNS lookup, which may block for many seconds. + * + * Raises TTransportException if an error occurs. + */ + std::string getHostStr() const; + + /** + * Get the path name for a Unix domain socket. + * + * Returns a std::string containing the path. For anonymous sockets, an + * empty string is returned. + * + * For addresses in the abstract namespace (Linux-specific), a std::string + * containing binary data is returned. In this case the first character will + * always be a NUL character. + * + * Raises TTransportException if called on a non-Unix domain socket. + */ + std::string getPath() const; + + /** + * Get human-readable string representation of the address. + * + * This prints a string representation of the address, for human consumption. + * For IP addresses, the string is of the form ":". + */ + std::string describe() const; + + bool operator==(const TSocketAddress& other) const; + bool operator!=(const TSocketAddress& other) const { + return !(*this == other); + } + + /** + * Check whether the first N bits of this address match the first N + * bits of another address. + * @note returns false if the addresses are not from the same + * address family or if the family is neither IPv4 nor IPv6 + */ + bool prefixMatch(const TSocketAddress& other, unsigned prefixLength) const; + + /** + * Use this operator for storing maps based on TSocketAddress. + */ + bool operator<(const TSocketAddress& other) const; + + /** + * Compuate a hash of a TSocketAddress. + */ + size_t hash() const; + + private: + /** + * Unix socket addresses require more storage than IPv4 and IPv6 addresses, + * and are comparatively little-used. + * + * Therefore TSocketAddress' internal storage_ member variable doesn't + * contain room for a full unix address, to avoid wasting space in the common + * case. When we do need to store a Unix socket address, we use this + * ExternalUnixAddr structure to allocate a struct sockaddr_un separately on + * the heap. + */ + struct ExternalUnixAddr { + sa_family_t family; + struct sockaddr_un *addr; + socklen_t len; + + socklen_t pathLength() const { + return len - offsetof(struct sockaddr_un, sun_path); + } + + void init() { + family = AF_UNIX; + addr = new sockaddr_un; + addr->sun_family = AF_UNIX; + len = 0; + } + void init(const ExternalUnixAddr &other) { + family = AF_UNIX; + addr = new sockaddr_un; + len = other.len; + memcpy(addr, other.addr, len); + // Fill the rest with 0s, just for safety + memset(reinterpret_cast(addr) + len, 0, + sizeof(struct sockaddr_un) - len); + } + void copy(const ExternalUnixAddr &other) { + len = other.len; + memcpy(addr, other.addr, len); + } + void free() { + family = AF_UNSPEC; + delete addr; + } + }; + + struct addrinfo* getAddrInfo(const char* host, uint16_t port, int flags); + struct addrinfo* getAddrInfo(const char* host, const char* port, int flags); + void setFromAddrInfo(const struct addrinfo* results); + void setFromLocalAddr(const struct addrinfo* results); + int setFromSocket(int socket, int (*fn)(int, struct sockaddr*, socklen_t*)); + std::string getIpString(int flags) const; + void getIpString(char *buf, size_t buflen, int flags) const; + + void addressUpdateFailure(sa_family_t expectedFamily); + void updateUnixAddressLength(socklen_t addrlen); + + void prepFamilyChange(sa_family_t newFamily) { + if (newFamily != AF_UNIX) { + if (getFamily() == AF_UNIX) { + storage_.un.free(); + } + } else { + if (getFamily() != AF_UNIX) { + storage_.un.init(); + } + } + } + + /* + * storage_ contains room for a full IPv4 or IPv6 address, so they can be + * stored inline without a separate allocation on the heap. + * + * If we need to store a Unix socket address, ExternalUnixAddr is a shim to + * track a struct sockaddr_un allocated separately on the heap. + */ + union { + sockaddr addr; + sockaddr_in ipv4; + sockaddr_in6 ipv6; + ExternalUnixAddr un; + } storage_; +}; + +/** + * Hash a TSocketAddress object. + * + * boost::hash uses hash_value(), so this allows boost::hash to automatically + * work for TSocketAddress. + */ +size_t hash_value(const TSocketAddress& address); + +std::ostream& operator<<(std::ostream& os, const TSocketAddress& addr); + +}}} // apache::thrift::transport + +namespace std { + +// Provide an implementation for std::hash +template<> +struct hash { + size_t operator()( + const apache::thrift::transport::TSocketAddress& addr) const { + return addr.hash(); + } +}; + +} + +#endif // THRIFT_TRANSPORT_TSOCKETADDRESS_H_ diff --git a/thrift/lib/cpp/transport/TSocketPool.h b/thrift/lib/cpp/transport/TSocketPool.h new file mode 100644 index 00000000..b2f9ee79 --- /dev/null +++ b/thrift/lib/cpp/transport/TSocketPool.h @@ -0,0 +1,218 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_TRANSPORT_TSOCKETPOOL_H_ +#define THRIFT_TRANSPORT_TSOCKETPOOL_H_ 1 + +#include +#include +#include "thrift/lib/cpp/transport/TSocket.h" + +namespace apache { namespace thrift { namespace transport { + + /** + * Class to hold server information for TSocketPool + * + */ +class TSocketPoolServer { + + public: + /** + * Default constructor for server info + */ + TSocketPoolServer(); + + /** + * Constructor for TSocketPool server + */ + TSocketPoolServer(const std::string &host, int port); + + // Host name + std::string host_; + + // Port to connect on + int port_; + + // Socket for the server + int socket_; + + // Last time connecting to this server failed + int lastFailTime_; + + // Number of consecutive times connecting to this server failed + int consecutiveFailures_; +}; + +/** + * TCP Socket implementation of the TTransport interface. + * + */ +class TSocketPool : public TSocket { + + public: + + /** + * Socket pool constructor + */ + TSocketPool(); + + /** + * Socket pool constructor + * + * @param hosts list of host names + * @param ports list of port names + */ + TSocketPool(const std::vector &hosts, + const std::vector &ports); + + /** + * Socket pool constructor + * + * @param servers list of pairs of host name and port + */ + /* implicit */ + TSocketPool(const std::vector >& servers); + + /** + * Socket pool constructor + * + * @param servers list of TSocketPoolServers + */ + /* implicit */ + TSocketPool(const + std::vector< boost::shared_ptr >& servers); + + /** + * Socket pool constructor + * + * @param host single host + * @param port single port + */ + TSocketPool(const std::string& host, int port); + + /** + * Destroys the socket object, closing it if necessary. + */ + virtual ~TSocketPool(); + + /** + * Add a server to the pool + */ + void addServer(const std::string& host, int port); + + /** + * Add a server to the pool + */ + void addServer(boost::shared_ptr &server); + + /** + * Set list of servers in this pool + */ + void setServers(const std::vector< boost::shared_ptr >& servers); + + /** + * Get list of servers in this pool + */ + void getServers(std::vector< boost::shared_ptr >& servers); + + /** + * Get port of the current server + */ + int getCurrentServerPort(); + + /** + * Get host of the current server + */ + std::string getCurrentServerHost(); + + /** + * Sets how many times to keep retrying a host in the connect function. + */ + void setNumRetries(int numRetries); + + /** + * Sets how long to wait until retrying a host if it was marked down + */ + void setRetryInterval(int retryInterval); + + /** + * Sets how many times to keep retrying a host before marking it as down. + */ + void setMaxConsecutiveFailures(int maxConsecutiveFailures); + + /** + * Turns randomization in connect order on or off. + */ + void setRandomize(bool randomize); + + /** + * Whether to always try the last server. + */ + void setAlwaysTryLast(bool alwaysTryLast); + + /** + * Sets the max number of servers to try in open + */ + void setMaxServersToTry(unsigned int maxServersToTry); + + /** + * Creates and opens the UNIX socket. + */ + void open(); + + /* + * Closes the UNIX socket + */ + void close(); + + protected: + + void setCurrentServer(const boost::shared_ptr &server); + + /** List of servers to connect to */ + std::vector< boost::shared_ptr > servers_; + + /** Current server */ + boost::shared_ptr currentServer_; + + /** How many times to retry each host in connect */ + int numRetries_; + + /** Retry interval in seconds, how long to not try a host if it has been + * marked as down. + */ + int retryInterval_; + + /** Max consecutive failures before marking a host down. */ + int maxConsecutiveFailures_; + + /** Try hosts in order? or Randomized? */ + bool randomize_; + + /** Always try last host, even if marked down? */ + bool alwaysTryLast_; + + /** Number of servers to try in open(), default is UINT_MAX */ + unsigned int maxServersToTry_; +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TSOCKETPOOL_H_ + diff --git a/thrift/lib/cpp/transport/TTransport.h b/thrift/lib/cpp/transport/TTransport.h new file mode 100644 index 00000000..5dadfda2 --- /dev/null +++ b/thrift/lib/cpp/transport/TTransport.h @@ -0,0 +1,353 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_TRANSPORT_TTRANSPORT_H +#define THRIFT_TRANSPORT_TTRANSPORT_H 1 + +#include "thrift/lib/cpp/Thrift.h" +#include +#include "thrift/lib/cpp/transport/TTransportException.h" +#include + +namespace apache { namespace thrift { namespace transport { + +/** + * Helper template to hoist readAll implementation out of TTransport + */ +template +uint32_t readAll(Transport_ &trans, uint8_t* buf, uint32_t len) { + uint32_t have = 0; + uint32_t get = 0; + + while (have < len) { + get = trans.read(buf+have, len-have); + if (get <= 0) { + throw TTransportException(TTransportException::END_OF_FILE, + "No more data to read."); + } + have += get; + } + + return have; +} + + +/** + * Generic interface for a method of transporting data. A TTransport may be + * capable of either reading or writing, but not necessarily both. + * + */ +class TTransport { + public: + /** + * Virtual deconstructor. + */ + virtual ~TTransport() {} + + /** + * Whether this transport is open. + */ + virtual bool isOpen() { + return false; + } + + /** + * Tests whether there is more data to read or if the remote side is + * still open. By default this is true whenever the transport is open, + * but implementations should add logic to test for this condition where + * possible (i.e. on a socket). + * This is used by a server to check if it should listen for another + * request. + */ + virtual bool peek() { + return isOpen(); + } + + /** + * Opens the transport for communications. + * + * @return bool Whether the transport was successfully opened + * @throws TTransportException if opening failed + */ + virtual void open() { + throw TTransportException(TTransportException::NOT_OPEN, "Cannot open base TTransport."); + } + + /** + * Closes the transport. + */ + virtual void close() { + throw TTransportException(TTransportException::NOT_OPEN, "Cannot close base TTransport."); + } + + /** + * Attempt to read up to the specified number of bytes into the string. + * + * @param buf Reference to the location to write the data + * @param len How many bytes to read + * @return How many bytes were actually read + * @throws TTransportException If an error occurs + */ + uint32_t read(uint8_t* buf, uint32_t len) { + T_VIRTUAL_CALL(); + return read_virt(buf, len); + } + virtual uint32_t read_virt(uint8_t* /* buf */, uint32_t /* len */) { + throw TTransportException(TTransportException::NOT_OPEN, + "Base TTransport cannot read."); + } + + /** + * Reads the given amount of data in its entirety no matter what. + * + * @param s Reference to location for read data + * @param len How many bytes to read + * @return How many bytes read, which must be equal to size + * @throws TTransportException If insufficient data was read + */ + uint32_t readAll(uint8_t* buf, uint32_t len) { + T_VIRTUAL_CALL(); + return readAll_virt(buf, len); + } + virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len) { + return apache::thrift::transport::readAll(*this, buf, len); + } + + /** + * Called when read is completed. + * This can be over-ridden to perform a transport-specific action + * e.g. logging the request to a file + * + * @return number of bytes read if available, 0 otherwise. + */ + virtual uint32_t readEnd() { + // default behavior is to do nothing + return 0; + } + + /** + * Writes the string in its entirety to the buffer. + * + * Note: You must call flush() to ensure the data is actually written, + * and available to be read back in the future. Destroying a TTransport + * object does not automatically flush pending data--if you destroy a + * TTransport object with written but unflushed data, that data may be + * discarded. + * + * @param buf The data to write out + * @throws TTransportException if an error occurs + */ + void write(const uint8_t* buf, uint32_t len) { + T_VIRTUAL_CALL(); + write_virt(buf, len); + } + virtual void write_virt(const uint8_t* /* buf */, uint32_t /* len */) { + throw TTransportException(TTransportException::NOT_OPEN, + "Base TTransport cannot write."); + } + + /** + * Called when write is completed. + * This can be over-ridden to perform a transport-specific action + * at the end of a request. + * + * @return number of bytes written if available, 0 otherwise + */ + virtual uint32_t writeEnd() { + // default behaviour is to do nothing + return 0; + } + + /** + * Flushes any pending data to be written. Typically used with buffered + * transport mechanisms. + * + * @throws TTransportException if an error occurs + */ + virtual void flush() { + // default behaviour is to do nothing + } + + /** + * Attempts to return a pointer to \c len bytes, possibly copied into \c buf. + * Does not consume the bytes read (i.e.: a later read will return the same + * data). This method is meant to support protocols that need to read + * variable-length fields. They can attempt to borrow the maximum amount of + * data that they will need, then consume (see next method) what they + * actually use. Some transports will not support this method and others + * will fail occasionally, so protocols must be prepared to use read if + * borrow fails. + * + * @oaram buf A buffer where the data can be stored if needed. + * If borrow doesn't return buf, then the contents of + * buf after the call are undefined. This parameter may be + * NULL to indicate that the caller is not supplying storage, + * but would like a pointer into an internal buffer, if + * available. + * @param len *len should initially contain the number of bytes to borrow. + * If borrow succeeds, *len will contain the number of bytes + * available in the returned pointer. This will be at least + * what was requested, but may be more if borrow returns + * a pointer to an internal buffer, rather than buf. + * If borrow fails, the contents of *len are undefined. + * @return If the borrow succeeds, return a pointer to the borrowed data. + * This might be equal to \c buf, or it might be a pointer into + * the transport's internal buffers. + * @throws TTransportException if an error occurs + */ + const uint8_t* borrow(uint8_t* buf, uint32_t* len) { + T_VIRTUAL_CALL(); + return borrow_virt(buf, len); + } + virtual const uint8_t* borrow_virt(uint8_t* /* buf */, uint32_t* /* len */) { + return NULL; + } + + /** + * Remove len bytes from the transport. This should always follow a borrow + * of at least len bytes, and should always succeed. + * TODO(dreiss): Is there any transport that could borrow but fail to + * consume, or that would require a buffer to dump the consumed data? + * + * @param len How many bytes to consume + * @throws TTransportException If an error occurs + */ + void consume(uint32_t len) { + T_VIRTUAL_CALL(); + consume_virt(len); + } + virtual void consume_virt(uint32_t /* len */) { + throw TTransportException(TTransportException::NOT_OPEN, + "Base TTransport cannot consume."); + } + + protected: + /** + * Simple constructor. + */ + TTransport() {} +}; + +/** + * Generic factory class to make an input and output transport out of a + * source transport. Commonly used inside servers to make input and output + * streams out of raw clients. + * + */ +class TTransportFactory { + public: + TTransportFactory() {} + + virtual ~TTransportFactory() {} + + /** + * Default implementation does nothing, just returns the transport given. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr trans) { + return trans; + } + +}; + +/** + * A duplex transport factory used to make input and output transports in a + * single call. This can be used to ensure the input and output transports + * are the pointers to the same object, for example. + * + * TTransportPair.first = Input Transport + * TTransportPair.second = Output Transport + */ +typedef std::pair, + boost::shared_ptr > TTransportPair; + +class TDuplexTransportFactory { + public: + TDuplexTransportFactory() {} + + virtual ~TDuplexTransportFactory() {} + + virtual TTransportPair getTransport(boost::shared_ptr trans) { + return std::make_pair(trans, trans); + } + + virtual TTransportPair getTransport(TTransportPair transports) { + return std::make_pair(transports.first, transports.second); + } + +}; + +/** + * Adapts a TTransportFactory to a TDuplexTransportFactory that returns + * a new transport object for both input and output + */ +template +class TSingleTransportFactory : public TDuplexTransportFactory { + public: + TSingleTransportFactory() { + factory_.reset(new Factory_()); + } + + explicit TSingleTransportFactory( + boost::shared_ptr factory) : + factory_(factory) {} + + virtual TTransportPair getTransport(boost::shared_ptr trans) { + return std::make_pair(factory_->getTransport(trans), + factory_->getTransport(trans)); + } + + virtual TTransportPair getTransport(TTransportPair transports) { + return std::make_pair(factory_->getTransport(transports.first), + factory_->getTransport(transports.second)); + } + private: + + boost::shared_ptr factory_; +}; + +/** + * Use TDualTransportFactory to construct input and output transports from + * different factories. + */ +class TDualTransportFactory : public TDuplexTransportFactory { + public: + TDualTransportFactory( + boost::shared_ptr inputFactory, + boost::shared_ptr outputFactory) : + inputFactory_(inputFactory), + outputFactory_(outputFactory) {} + + virtual TTransportPair getTransport(boost::shared_ptr trans) { + return std::make_pair(inputFactory_->getTransport(trans), + outputFactory_->getTransport(trans)); + } + + virtual TTransportPair getTransport(TTransportPair transports) { + return std::make_pair(inputFactory_->getTransport(transports.first), + outputFactory_->getTransport(transports.second)); + } + private: + + boost::shared_ptr inputFactory_; + boost::shared_ptr outputFactory_; +}; + +}}} // apache::thrift::transport + +#endif // #ifndef THRIFT_TRANSPORT_TTRANSPORT_H diff --git a/thrift/lib/cpp/transport/TTransportException.h b/thrift/lib/cpp/transport/TTransportException.h new file mode 100644 index 00000000..28f5d195 --- /dev/null +++ b/thrift/lib/cpp/transport/TTransportException.h @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_ +#define _THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_ 1 + +#include +#include "thrift/lib/cpp/Thrift.h" + +namespace apache { namespace thrift { namespace transport { + +/** + * Class to encapsulate all the possible types of transport errors that may + * occur in various transport systems. This provides a sort of generic + * wrapper around the shitty UNIX E_ error codes that lets a common code + * base of error handling to be used for various types of transports, i.e. + * pipes etc. + * + */ +class TTransportException : public apache::thrift::TLibraryException { + public: + /** + * Error codes for the various types of exceptions. + */ + enum TTransportExceptionType + { UNKNOWN = 0 + , NOT_OPEN = 1 + , ALREADY_OPEN = 2 + , TIMED_OUT = 3 + , END_OF_FILE = 4 + , INTERRUPTED = 5 + , BAD_ARGS = 6 + , CORRUPTED_DATA = 7 + , INTERNAL_ERROR = 8 + , NOT_SUPPORTED = 9 + , INVALID_STATE = 10 + , INVALID_FRAME_SIZE = 11 + , SSL_ERROR = 12 + }; + + TTransportException() : + apache::thrift::TLibraryException(), + type_(UNKNOWN), errno_(0) {} + + TTransportException(TTransportExceptionType type) : + apache::thrift::TLibraryException(), + type_(type), errno_(0) {} + + TTransportException(const std::string& message) : + apache::thrift::TLibraryException(message), + type_(UNKNOWN), errno_(0) {} + + TTransportException(TTransportExceptionType type, const std::string& message) : + apache::thrift::TLibraryException(message), + type_(type), errno_(0) {} + + TTransportException(TTransportExceptionType type, + const std::string& message, + int errno_copy) : + apache::thrift::TLibraryException(getMessage(message, errno_copy)), + type_(type), errno_(errno_copy) {} + + virtual ~TTransportException() throw() {} + + /** + * Returns an error code that provides information about the type of error + * that has occurred. + * + * @return Error code + */ + TTransportExceptionType getType() const throw() { + return type_; + } + + virtual const char* what() const throw() { + if (message_.empty()) { + switch (type_) { + case UNKNOWN : return "TTransportException: Unknown transport exception"; + case NOT_OPEN : return "TTransportException: Transport not open"; + case ALREADY_OPEN : return "TTransportException: Transport already open"; + case TIMED_OUT : return "TTransportException: Timed out"; + case END_OF_FILE : return "TTransportException: End of file"; + case INTERRUPTED : return "TTransportException: Interrupted"; + case BAD_ARGS : return "TTransportException: Invalid arguments"; + case CORRUPTED_DATA : return "TTransportException: Corrupted Data"; + case INTERNAL_ERROR : return "TTransportException: Internal error"; + case NOT_SUPPORTED : return "TTransportException: Not supported"; + case INVALID_STATE : return "TTransportException: Invalid state"; + case INVALID_FRAME_SIZE: + return "TTransportException: Invalid frame size"; + case SSL_ERROR : return "TTransportException: SSL error"; + default : return "TTransportException: (Invalid exception type)"; + } + } else { + return message_.c_str(); + } + } + + int getErrno() const { return errno_; } + + protected: + /** Just like strerror_r but returns a C++ string object. */ + std::string strerror_s(int errno_copy); + + /** Return a message based on the input. */ + static std::string getMessage(const std::string &message, + int errno_copy) { + if (errno_copy != 0) { + return message + ": " + TOutput::strerror_s(errno_copy); + } else { + return message; + } + } + + /** Error code */ + TTransportExceptionType type_; + + /** A copy of the errno. */ + int errno_; +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_ diff --git a/thrift/lib/cpp/transport/TTransportUtils.h b/thrift/lib/cpp/transport/TTransportUtils.h new file mode 100644 index 00000000..8dfa4919 --- /dev/null +++ b/thrift/lib/cpp/transport/TTransportUtils.h @@ -0,0 +1,330 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TTRANSPORTUTILS_H_ +#define _THRIFT_TRANSPORT_TTRANSPORTUTILS_H_ 1 + +#include +#include +#include +#include +#include "thrift/lib/cpp/transport/TTransport.h" +// Include the buffered transports that used to be defined here. +#include "thrift/lib/cpp/transport/TBufferTransports.h" +#include "thrift/lib/cpp/transport/TFileTransport.h" + +namespace apache { namespace thrift { namespace transport { + +/** + * The null transport is a dummy transport that doesn't actually do anything. + * It's sort of an analogy to /dev/null, you can never read anything from it + * and it will let you write anything you want to it, though it won't actually + * go anywhere. + * + */ +class TNullTransport : public TVirtualTransport { + public: + TNullTransport() {} + + ~TNullTransport() {} + + bool isOpen() { + return true; + } + + void open() {} + + void write(const uint8_t* /* buf */, uint32_t /* len */) { + return; + } + +}; + + +/** + * TPipedTransport. This transport allows piping of a request from one + * transport to another either when readEnd() or writeEnd(). The typical + * use case for this is to log a request or a reply to disk. + * The underlying buffer expands to a keep a copy of the entire + * request/response. + * + */ +class TPipedTransport : virtual public TTransport { + public: + TPipedTransport(boost::shared_ptr srcTrans, + boost::shared_ptr dstTrans) : + srcTrans_(srcTrans), + dstTrans_(dstTrans), + rBufSize_(512), rPos_(0), rLen_(0), + wBufSize_(512), wLen_(0) { + + // default is to to pipe the request when readEnd() is called + pipeOnRead_ = true; + pipeOnWrite_ = false; + + rBuf_ = (uint8_t*) std::malloc(sizeof(uint8_t) * rBufSize_); + if (rBuf_ == NULL) { + throw std::bad_alloc(); + } + wBuf_ = (uint8_t*) std::malloc(sizeof(uint8_t) * wBufSize_); + if (wBuf_ == NULL) { + throw std::bad_alloc(); + } + } + + TPipedTransport(boost::shared_ptr srcTrans, + boost::shared_ptr dstTrans, + uint32_t sz) : + srcTrans_(srcTrans), + dstTrans_(dstTrans), + rBufSize_(512), rPos_(0), rLen_(0), + wBufSize_(sz), wLen_(0) { + + rBuf_ = (uint8_t*) std::malloc(sizeof(uint8_t) * rBufSize_); + if (rBuf_ == NULL) { + throw std::bad_alloc(); + } + wBuf_ = (uint8_t*) std::malloc(sizeof(uint8_t) * wBufSize_); + if (wBuf_ == NULL) { + throw std::bad_alloc(); + } + } + + ~TPipedTransport() { + std::free(rBuf_); + std::free(wBuf_); + } + + bool isOpen() { + return srcTrans_->isOpen(); + } + + bool peek() { + if (rPos_ >= rLen_) { + // Double the size of the underlying buffer if it is full + if (rLen_ == rBufSize_) { + rBufSize_ *=2; + rBuf_ = (uint8_t *)std::realloc(rBuf_, sizeof(uint8_t) * rBufSize_); + } + + // try to fill up the buffer + rLen_ += srcTrans_->read(rBuf_+rPos_, rBufSize_ - rPos_); + } + return (rLen_ > rPos_); + } + + + void open() { + srcTrans_->open(); + } + + void close() { + srcTrans_->close(); + } + + void setPipeOnRead(bool pipeVal) { + pipeOnRead_ = pipeVal; + } + + void setPipeOnWrite(bool pipeVal) { + pipeOnWrite_ = pipeVal; + } + + uint32_t read(uint8_t* buf, uint32_t len); + + uint32_t readEnd() { + + if (pipeOnRead_) { + dstTrans_->write(rBuf_, rPos_); + dstTrans_->flush(); + } + + srcTrans_->readEnd(); + + // If requests are being pipelined, copy down our read-ahead data, + // then reset our state. + int read_ahead = rLen_ - rPos_; + uint32_t bytes = rPos_; + memcpy(rBuf_, rBuf_ + rPos_, read_ahead); + rPos_ = 0; + rLen_ = read_ahead; + + return bytes; + } + + void write(const uint8_t* buf, uint32_t len); + + uint32_t writeEnd() { + if (pipeOnWrite_) { + dstTrans_->write(wBuf_, wLen_); + dstTrans_->flush(); + } + return wLen_; + } + + void flush(); + + boost::shared_ptr getTargetTransport() { + return dstTrans_; + } + + /* + * Override TTransport *_virt() functions to invoke our implementations. + * We cannot use TVirtualTransport to provide these, since we need to inherit + * virtually from TTransport. + */ + virtual uint32_t read_virt(uint8_t* buf, uint32_t len) { + return this->read(buf, len); + } + virtual void write_virt(const uint8_t* buf, uint32_t len) { + this->write(buf, len); + } + + protected: + boost::shared_ptr srcTrans_; + boost::shared_ptr dstTrans_; + + uint8_t* rBuf_; + uint32_t rBufSize_; + uint32_t rPos_; + uint32_t rLen_; + + uint8_t* wBuf_; + uint32_t wBufSize_; + uint32_t wLen_; + + bool pipeOnRead_; + bool pipeOnWrite_; +}; + + +/** + * Wraps a transport into a pipedTransport instance. + * + */ +class TPipedTransportFactory : public TTransportFactory { + public: + TPipedTransportFactory() {} + TPipedTransportFactory(boost::shared_ptr dstTrans) { + initializeTargetTransport(dstTrans); + } + virtual ~TPipedTransportFactory() {} + + /** + * Wraps the base transport into a piped transport. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr srcTrans) { + return boost::shared_ptr(new TPipedTransport(srcTrans, dstTrans_)); + } + + virtual void initializeTargetTransport(boost::shared_ptr dstTrans) { + if (dstTrans_.get() == NULL) { + dstTrans_ = dstTrans; + } else { + throw TLibraryException("Target transport already initialized"); + } + } + + protected: + boost::shared_ptr dstTrans_; +}; + +/** + * TPipedFileTransport. This is just like a TTransport, except that + * it is a templatized class, so that clients who rely on a specific + * TTransport can still access the original transport. + * + */ +class TPipedFileReaderTransport : public TPipedTransport, + public TFileReaderTransport { + public: + TPipedFileReaderTransport(boost::shared_ptr srcTrans, boost::shared_ptr dstTrans); + + ~TPipedFileReaderTransport(); + + // TTransport functions + bool isOpen(); + bool peek(); + void open(); + void close(); + uint32_t read(uint8_t* buf, uint32_t len); + uint32_t readAll(uint8_t* buf, uint32_t len); + uint32_t readEnd(); + void write(const uint8_t* buf, uint32_t len); + uint32_t writeEnd(); + void flush(); + + // TFileReaderTransport functions + int32_t getReadTimeout(); + void setReadTimeout(int32_t readTimeout); + uint32_t getNumChunks(); + uint32_t getCurChunk(); + void seekToChunk(int32_t chunk); + void seekToEnd(); + + /* + * Override TTransport *_virt() functions to invoke our implementations. + * We cannot use TVirtualTransport to provide these, since we need to inherit + * virtually from TTransport. + */ + virtual uint32_t read_virt(uint8_t* buf, uint32_t len) { + return this->read(buf, len); + } + virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len) { + return this->readAll(buf, len); + } + virtual void write_virt(const uint8_t* buf, uint32_t len) { + this->write(buf, len); + } + + protected: + // shouldn't be used + TPipedFileReaderTransport(); + boost::shared_ptr srcTrans_; +}; + +/** + * Creates a TPipedFileReaderTransport from a filepath and a destination transport + * + */ +class TPipedFileReaderTransportFactory : public TPipedTransportFactory { + public: + TPipedFileReaderTransportFactory() {} + TPipedFileReaderTransportFactory(boost::shared_ptr dstTrans) + : TPipedTransportFactory(dstTrans) + {} + virtual ~TPipedFileReaderTransportFactory() {} + + boost::shared_ptr getTransport(boost::shared_ptr srcTrans) { + boost::shared_ptr pFileReaderTransport = boost::dynamic_pointer_cast(srcTrans); + if (pFileReaderTransport.get() != NULL) { + return getFileReaderTransport(pFileReaderTransport); + } else { + return boost::shared_ptr(); + } + } + + boost::shared_ptr getFileReaderTransport(boost::shared_ptr srcTrans) { + return boost::shared_ptr(new TPipedFileReaderTransport(srcTrans, dstTrans_)); + } +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TTRANSPORTUTILS_H_ diff --git a/thrift/lib/cpp/transport/TVirtualTransport.h b/thrift/lib/cpp/transport/TVirtualTransport.h new file mode 100644 index 00000000..26ab13a8 --- /dev/null +++ b/thrift/lib/cpp/transport/TVirtualTransport.h @@ -0,0 +1,134 @@ +// Copyright (c) 2006- Facebook +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +#ifndef _THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_ +#define _THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_ 1 + +#include "thrift/lib/cpp/transport/TTransport.h" + +namespace apache { namespace thrift { namespace transport { + + +/** + * Helper class that provides default implementations of TTransport methods. + * + * This class provides default implementations of read(), readAll(), write(), + * borrow() and consume(). + * + * In the TTransport base class, each of these methods simply invokes its + * virtual counterpart. This class overrides them to always perform the + * default behavior, without a virtual function call. + * + * The primary purpose of this class is to serve as a base class for + * TVirtualTransport, and prevent infinite recursion if one of its subclasses + * does not override the TTransport implementation of these methods. (Since + * TVirtualTransport::read_virt() calls read(), and TTransport::read() calls + * read_virt().) + */ +template +class TTransportDefaults : public Super_ { + public: + /* + * TTransport *_virt() methods provide reasonable default implementations. + * Invoke them non-virtually. + */ + uint32_t read(uint8_t* buf, uint32_t len) { + return this->TTransport::read_virt(buf, len); + } + uint32_t readAll(uint8_t* buf, uint32_t len) { + return this->TTransport::readAll_virt(buf, len); + } + void write(const uint8_t* buf, uint32_t len) { + this->TTransport::write_virt(buf, len); + } + const uint8_t* borrow(uint8_t* buf, uint32_t* len) { + return this->TTransport::borrow_virt(buf, len); + } + void consume(uint32_t len) { + this->TTransport::consume_virt(len); + } + + protected: + TTransportDefaults() {} +}; + +/** + * Helper class to provide polymorphism for subclasses of TTransport. + * + * This class implements *_virt() methods of TTransport, to call the + * non-virtual versions of these functions in the proper subclass. + * + * To define your own transport class using TVirtualTransport: + * 1) Derive your subclass from TVirtualTransport + * e.g: class MyTransport : public TVirtualTransport { + * 2) Provide your own implementations of read(), readAll(), etc. + * These methods should be non-virtual. + * + * Transport implementations that need to use virtual inheritance when + * inheriting from TTransport cannot use TVirtualTransport. + * + * @author Chad Walters + */ +template < class Transport_, class Super_=TTransportDefaults > +class TVirtualTransport : public Super_ { + public: + /* + * Implementations of the *_virt() functions, to call the subclass's + * non-virtual implementation function. + */ + virtual uint32_t read_virt(uint8_t* buf, uint32_t len) { + return static_cast(this)->read(buf, len); + } + + virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len) { + return static_cast(this)->readAll(buf, len); + } + + virtual void write_virt(const uint8_t* buf, uint32_t len) { + static_cast(this)->write(buf, len); + } + + virtual const uint8_t* borrow_virt(uint8_t* buf, uint32_t* len) { + return static_cast(this)->borrow(buf, len); + } + + virtual void consume_virt(uint32_t len) { + static_cast(this)->consume(len); + } + + /* + * Provide a default readAll() implementation that invokes + * read() non-virtually. + * + * Note: subclasses that use TVirtualTransport to derive from another + * transport implementation (i.e., not TTransportDefaults) should beware that + * this may override any non-default readAll() implementation provided by + * the parent transport class. They may need to redefine readAll() to call + * the correct parent implementation, if desired. + */ + uint32_t readAll(uint8_t* buf, uint32_t len) { + Transport_* trans = static_cast(this); + return ::apache::thrift::transport::readAll(*trans, buf, len); + } + + protected: + TVirtualTransport() {} + + /* + * Templatized constructors, to allow arguments to be passed to the Super_ + * constructor. Currently we only support 0, 1, or 2 arguments, but + * additional versions can be added as needed. + */ + template + TVirtualTransport(Arg_ const& arg) : Super_(arg) { } + + template + TVirtualTransport(Arg1_ const& a1, Arg2_ const& a2) : Super_(a1, a2) { } +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_ diff --git a/thrift/lib/cpp/transport/TZlibTransport.h b/thrift/lib/cpp/transport/TZlibTransport.h new file mode 100644 index 00000000..01cfb38b --- /dev/null +++ b/thrift/lib/cpp/transport/TZlibTransport.h @@ -0,0 +1,292 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TZLIBTRANSPORT_H_ +#define _THRIFT_TRANSPORT_TZLIBTRANSPORT_H_ 1 + +#include +#include "thrift/lib/cpp/transport/TBufferTransports.h" +#include "thrift/lib/cpp/transport/TVirtualTransport.h" + +struct z_stream_s; + +namespace apache { namespace thrift { namespace transport { + +class TZlibTransportException : public TTransportException { + public: + TZlibTransportException(int status, const char* msg) : + TTransportException(TTransportException::INTERNAL_ERROR, + errorMessage(status, msg)), + zlib_status_(status), + zlib_msg_(msg == NULL ? "(null)" : msg) {} + + virtual ~TZlibTransportException() throw() {} + + int getZlibStatus() { return zlib_status_; } + std::string getZlibMessage() { return zlib_msg_; } + + static std::string errorMessage(int status, const char* msg) { + std::string rv = "zlib error: "; + if (msg) { + rv += msg; + } else { + rv += "(no message)"; + } + rv += " (status = "; + rv += boost::lexical_cast(status); + rv += ")"; + return rv; + } + + int zlib_status_; + std::string zlib_msg_; +}; + +/** + * This transport uses zlib's compressed format on the "far" side. + * + * There are two kinds of TZlibTransport objects: + * - Standalone objects are used to encode self-contained chunks of data + * (like structures). They include checksums. + * - Non-standalone transports are used for RPC. They are not implemented yet. + * + * TODO(dreiss): Don't do an extra copy of the compressed data if + * the underlying transport is TBuffered or TMemory. + * + */ +class TZlibTransport : public TVirtualTransport { + public: + + /** + * @param transport The transport to read compressed data from + * and write compressed data to. + * @param urbuf_size Uncompressed buffer size for reading. + * @param crbuf_size Compressed buffer size for reading. + * @param uwbuf_size Uncompressed buffer size for writing. + * @param cwbuf_size Compressed buffer size for writing. + * + * TODO(dreiss): Write a constructor that isn't a pain. + */ + TZlibTransport(boost::shared_ptr transport, + int urbuf_size = DEFAULT_URBUF_SIZE, + int crbuf_size = DEFAULT_CRBUF_SIZE, + int uwbuf_size = DEFAULT_UWBUF_SIZE, + int cwbuf_size = DEFAULT_CWBUF_SIZE) : + transport_(transport), + urpos_(0), + uwpos_(0), + input_ended_(false), + output_finished_(false), + urbuf_size_(urbuf_size), + crbuf_size_(crbuf_size), + uwbuf_size_(uwbuf_size), + cwbuf_size_(cwbuf_size), + urbuf_(NULL), + crbuf_(NULL), + uwbuf_(NULL), + cwbuf_(NULL), + rstream_(NULL), + wstream_(NULL) + { + if (uwbuf_size_ < MIN_DIRECT_DEFLATE_SIZE) { + // Have to copy this into a local because of a linking issue. + int minimum = MIN_DIRECT_DEFLATE_SIZE; + throw TTransportException( + TTransportException::BAD_ARGS, + "TZLibTransport: uncompressed write buffer must be at least" + + boost::lexical_cast(minimum) + "."); + } + + try { + urbuf_ = new uint8_t[urbuf_size]; + crbuf_ = new uint8_t[crbuf_size]; + uwbuf_ = new uint8_t[uwbuf_size]; + cwbuf_ = new uint8_t[cwbuf_size]; + + // Don't call this outside of the constructor. + initZlib(); + + } catch (...) { + delete[] urbuf_; + delete[] crbuf_; + delete[] uwbuf_; + delete[] cwbuf_; + throw; + } + } + + // Don't call this outside of the constructor. + void initZlib(); + + /** + * TZlibTransport destructor. + * + * Warning: Destroying a TZlibTransport object may discard any written but + * unflushed data. You must explicitly call flush() or finish() to ensure + * that data is actually written and flushed to the underlying transport. + */ + ~TZlibTransport(); + + bool isOpen(); + bool peek(); + + void open() { + transport_->open(); + } + + void close() { + transport_->close(); + } + + uint32_t read(uint8_t* buf, uint32_t len); + + void write(const uint8_t* buf, uint32_t len); + + void flush(); + + /** + * Finalize the zlib stream. + * + * This causes zlib to flush any pending write data and write end-of-stream + * information, including the checksum. Once finish() has been called, no + * new data can be written to the stream. + */ + void finish(); + + const uint8_t* borrow(uint8_t* buf, uint32_t* len); + + void consume(uint32_t len); + + /** + * Verify the checksum at the end of the zlib stream. + * + * This may only be called after all data has been read. + * It verifies the checksum that was written by the finish() call. + */ + void verifyChecksum(); + + /** + * TODO(someone_smart): Choose smart defaults. + */ + static const int DEFAULT_URBUF_SIZE = 128; + static const int DEFAULT_CRBUF_SIZE = 1024; + static const int DEFAULT_UWBUF_SIZE = 128; + static const int DEFAULT_CWBUF_SIZE = 1024; + + protected: + + inline void checkZlibRv(int status, const char* msg); + inline void checkZlibRvNothrow(int status, const char* msg); + inline int readAvail(); + void flushToTransport(int flush); + void flushToZlib(const uint8_t* buf, int len, int flush); + bool readFromZlib(); + + private: + // Deprecated constructor signature. + // + // This used to be the constructor signature. If you are getting a compile + // error because you are trying to use this constructor, you need to update + // your code as follows: + // - Remove the use_for_rpc argument in the constructur. + // There is no longer any distinction between RPC and standalone zlib + // transports. (Previously, only standalone was allowed, anyway.) + // - Replace TZlibTransport::flush() calls with TZlibTransport::finish() + // in your code. Previously, flush() used to finish the zlib stream. + // Now flush() only flushes out pending data, so more writes can be + // performed after a flush(). The finish() method can be used to finalize + // the zlib stream. + // + // If we don't declare this constructor, old code written as + // TZlibTransport(trans, false) still compiles but behaves incorrectly. + // The second bool argument is converted to an integer and used as the + // urbuf_size. + TZlibTransport(boost::shared_ptr transport, + bool use_for_rpc, + int urbuf_size = DEFAULT_URBUF_SIZE, + int crbuf_size = DEFAULT_CRBUF_SIZE, + int uwbuf_size = DEFAULT_UWBUF_SIZE, + int cwbuf_size = DEFAULT_CWBUF_SIZE); + + protected: + // Writes smaller than this are buffered up. + // Larger (or equal) writes are dumped straight to zlib. + static const int MIN_DIRECT_DEFLATE_SIZE = 32; + + boost::shared_ptr transport_; + + int urpos_; + int uwpos_; + + /// True iff zlib has reached the end of the input stream. + bool input_ended_; + /// True iff we have finished the output stream. + bool output_finished_; + + int urbuf_size_; + int crbuf_size_; + int uwbuf_size_; + int cwbuf_size_; + + uint8_t* urbuf_; + uint8_t* crbuf_; + uint8_t* uwbuf_; + uint8_t* cwbuf_; + + struct z_stream_s* rstream_; + struct z_stream_s* wstream_; +}; + + +/** + * Wraps a transport into a zlibbed one. + * + */ +class TZlibTransportFactory : public TTransportFactory { + public: + TZlibTransportFactory() {} + + virtual ~TZlibTransportFactory() {} + + virtual boost::shared_ptr getTransport( + boost::shared_ptr trans) { + return boost::shared_ptr(new TZlibTransport(trans)); + } +}; + +/** + * Wraps a transport into a framed, zlibbed one. + */ +class TFramedZlibTransportFactory : public TTransportFactory { + public: + TFramedZlibTransportFactory() {} + + virtual ~TFramedZlibTransportFactory() {} + + virtual boost::shared_ptr getTransport( + boost::shared_ptr trans) { + boost::shared_ptr framedTransport(new TFramedTransport(trans)); + return boost::shared_ptr(new TZlibTransport(framedTransport)); + } +}; + + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TZLIBTRANSPORT_H_ diff --git a/thrift/lib/cpp/util/AsyncClientUtil.h b/thrift/lib/cpp/util/AsyncClientUtil.h new file mode 100644 index 00000000..9cd68bb7 --- /dev/null +++ b/thrift/lib/cpp/util/AsyncClientUtil.h @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_UTIL_ASYNCCLIENTUTIL_H_ +#define THRIFT_UTIL_ASYNCCLIENTUTIL_H_ 1 + +#include "thrift/lib/cpp/async/TAsyncSocket.h" +#include "thrift/lib/cpp/async/TFramedAsyncChannel.h" +#include "thrift/lib/cpp/protocol/TBinaryProtocol.h" +#include "thrift/lib/cpp/transport/TBufferTransports.h" + +namespace apache { namespace thrift { namespace util { + +/* + * Create an async client from a TSocketAddress + */ +template, + typename ChannelT = async::TFramedAsyncChannel> +ClientT* createClient(async::TEventBase* eventBase, + const transport::TSocketAddress& address) { + boost::shared_ptr transport( + async::TAsyncSocket::newSocket(eventBase, address)); + boost::shared_ptr channel( + ChannelT::newChannel(transport)); + + ProtocolFactoryT protocolFactory; + return new ClientT(channel, &protocolFactory); +} + +/* + * Create an async client from an IP and port + */ +template, + typename ChannelT = async::TFramedAsyncChannel> +ClientT* createClient(async::TEventBase* eventBase, + const std::string& ip, uint16_t port) { + // Note that we intentionally use setFromIpPort() and not setFromHostPort() + // here. If users want asynchronous operation they almost certainly don't + // want us to perform a blocking DNS lookup operation that may take a long + // time. + transport::TSocketAddress address; + address.setFromIpPort(ip, port); + return createClient( + eventBase, address); +} + +}}} // apache::thrift::util + +#endif // THRIFT_UTIL_ASYNCCLIENTUTIL_H_ diff --git a/thrift/lib/cpp/util/BitwiseCast.h b/thrift/lib/cpp/util/BitwiseCast.h new file mode 100644 index 00000000..0c9461fc --- /dev/null +++ b/thrift/lib/cpp/util/BitwiseCast.h @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef THRIFT_UTIL_BITWISECAST_H_ +#define THRIFT_UTIL_BITWISECAST_H_ + +#include + +// Use this to get around strict aliasing rules. +// For example, uint64_t i = bitwise_cast(returns_double()); +// The most obvious implementation is to just cast a pointer, +// but that doesn't work. +// For a pretty in-depth explanation of the problem, see +// http://cellperformance.beyond3d.com/articles/2006/06/ (...) +// understanding-strict-aliasing.html +template +static inline To bitwise_cast(From from) { + BOOST_STATIC_ASSERT(sizeof(From) == sizeof(To)); + + // BAD!!! These are all broken with -O2. + //return *reinterpret_cast(&from); // BAD!!! + //return *static_cast(static_cast(&from)); // BAD!!! + //return *(To*)(void*)&from; // BAD!!! + + // Super clean and partially blessed by section 3.9 of the standard. + //unsigned char c[sizeof(from)]; + //memcpy(c, &from, sizeof(from)); + //To to; + //memcpy(&to, c, sizeof(c)); + //return to; + + // Slightly more questionable. + // Same code emitted by GCC. + //To to; + //memcpy(&to, &from, sizeof(from)); + //return to; + + // Technically undefined, but almost universally supported, + // and the most efficient implementation. + union { + From f; + To t; + } u; + u.f = from; + return u.t; +} + +#endif diff --git a/thrift/lib/cpp/util/EnumUtils.h b/thrift/lib/cpp/util/EnumUtils.h new file mode 100644 index 00000000..0bf43afb --- /dev/null +++ b/thrift/lib/cpp/util/EnumUtils.h @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_UTIL_ENUMUTILS_H_ +#define THRIFT_UTIL_ENUMUTILS_H_ 1 + +namespace apache { namespace thrift { + +namespace util { + +/** + * Parses an enum name to the enum type + */ +template +bool tryParseEnum(const String& name, EnumType* out) { + return TEnumTraits::findValue(name.c_str(), out); +}; + +template +bool tryParseEnum(const char* name, EnumType* out) { + return TEnumTraits::findValue(name, out); +}; + +/** + * Returns the human-readable name for an Enum type. + */ +template +const char* enumName(EnumType value, + const char* defaultName = nullptr) { + const char* name = TEnumTraits::findName(value); + if (name) { + return name; + } else { + return defaultName; + } +}; + +}}} // apache::thrift::util + +#endif // THRIFT_UTIL_ENUMUTILS_H_ 1 diff --git a/thrift/lib/cpp/util/ScopedServerThread.h b/thrift/lib/cpp/util/ScopedServerThread.h new file mode 100644 index 00000000..fe537bd3 --- /dev/null +++ b/thrift/lib/cpp/util/ScopedServerThread.h @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_UTIL_SCOPEDSERVERTHREAD_H_ +#define THRIFT_UTIL_SCOPEDSERVERTHREAD_H_ 1 + +#include +#include + +namespace apache { namespace thrift { + +namespace concurrency { +class Thread; +} +namespace server { +class TServer; +} +namespace transport { +class TSocketAddress; +} + +namespace util { + +class ServerCreator; + +/** + * ScopedServerThread spawns a thrift server in a new thread. + * + * The server is stopped automatically when the ScopedServerThread is + * destroyed. + */ +class ScopedServerThread : public boost::noncopyable { + public: + /** + * Create a new, unstarted ScopedServerThread object. + */ + ScopedServerThread(); + + /** + * Create a ScopedServerThread object and automatically start it. + */ + ScopedServerThread(ServerCreator* serverCreator); + + /** + * Create a ScopedServerThread object and automatically start it. + */ + ScopedServerThread(const boost::shared_ptr& server); + + virtual ~ScopedServerThread(); + + /** + * Start the server thread. + * + * This method does not return until the server has successfully started. + * + * @param serverCreator The ServerCreator object to use to create the server. + */ + void start(ServerCreator* serverCreator); + + /** + * Start the server thread. + * + * This method does not return until the server has successfully started. + * + * @param server The server to run in the new thread. + */ + void start(const boost::shared_ptr& server); + + /** + * Stop the server thread. + */ + void stop(); + + /** + * Get the address on which the server is listening. + */ + const transport::TSocketAddress* getAddress() const; + + private: + class Helper; + + boost::shared_ptr helper_; + boost::shared_ptr thread_; +}; + +}}} // apache::thrift::util + +#endif // THRIFT_UTIL_SCOPEDSERVERTHREAD_H_ diff --git a/thrift/lib/cpp/util/ServerCreator.h b/thrift/lib/cpp/util/ServerCreator.h new file mode 100644 index 00000000..b573f084 --- /dev/null +++ b/thrift/lib/cpp/util/ServerCreator.h @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_UTIL_SERVERCREATOR_H_ +#define THRIFT_UTIL_SERVERCREATOR_H_ 1 + +#include + +namespace apache { namespace thrift { + +namespace server { +class TServer; +} + +namespace util { + +/** + * ServerCreator is an abstract class for creating a thrift server. + */ +class ServerCreator { + public: + virtual ~ServerCreator() {} + + /** + * Create a new server. + */ + virtual boost::shared_ptr createServer() = 0; + + protected: + ServerCreator() {} +}; + +}}} // apache::thrift::util + +#endif // THRIFT_UTIL_SERVERCREATOR_H_ diff --git a/thrift/lib/cpp/util/ServerCreatorBase.h b/thrift/lib/cpp/util/ServerCreatorBase.h new file mode 100644 index 00000000..98f0fb4b --- /dev/null +++ b/thrift/lib/cpp/util/ServerCreatorBase.h @@ -0,0 +1,184 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_UTIL_SERVERCREATORBASE_H_ +#define THRIFT_UTIL_SERVERCREATORBASE_H_ 1 + +#include "thrift/lib/cpp/util/ServerCreator.h" + +namespace apache { namespace thrift { + +namespace protocol { +class TProtocolFactory; +class TDuplexProtocolFactory; +} +namespace server { +class TServerEventHandler; +} + +namespace util { + +/** + * ServerCreatorBase is a helper class for subclass that wish to implement the + * ServerCreator interface. + * + * ServerCreatorBase provides functionality that pretty much all ServerCreators + * need. It provides default protocol settings, and also + * setServerEventHandler(). + */ +class ServerCreatorBase : public ServerCreator { + public: + /** + * Use strict read by default. + * + * We should always use strict read and strict write for all new code. + * Only legacy services should allow requests without a thrift ID. + */ + static const bool DEFAULT_STRICT_READ = true; + + /** + * Use strict write by default. + */ + static const bool DEFAULT_STRICT_WRITE = true; + + /** + * Default string limit. Set a reasonably small value so that servers won't + * fall over when sent garbage data. + */ + static const int32_t DEFAULT_STRING_LIMIT = 256*1024*1024; + + /** + * Default container limit. Set a reasonably small value so that servers + * won't fall over when sent garbage data. + */ + static const int32_t DEFAULT_CONTAINER_LIMIT = 256*1024*1024; + + /** + * Set the TServerEventHandler to use with the new server. + * + * This event handler will be set on servers created by this ServerCreator. + */ + void setServerEventHandler( + const boost::shared_ptr& eventHandler) { + serverEventHandler_ = eventHandler; + } + + /** + * Set whether or not TBinaryProtocol should include an identifier field. + * + * This field helps verify that incoming data is a valid thrift request, + * rather than random garbage data. + * + * This setting is ignored if you explicitly specify a TProtocolFactory to + * use. It is only honored if you let the ServerCreator create a new + * TBinaryProtocol for you. + * + * If unspecified, it defaults to true for both strictRead and strictWrite. + * + * @param strictRead Reject incoming requests that don't include a thrift + * identifier. + * @param strictWrite Send a thrift identifier in outgoing responses. + */ + void setStrictProtocol(bool strictRead, bool strictWrite); + + /** + * Set the maximum string size allowed by TBinaryProtocol. + * + * This setting helps prevent TBinaryProtocol from trying to allocate an + * extremely large buffer if a request contains a bogus string length field. + * + * This setting is ignored if you explicitly specify a TProtocolFactory to + * use. It is only honored if you let the ServerCreator create a new + * TBinaryProtocol for you. + * + * If unspecified, it defaults to 256MB. + */ + void setStringSizeLimit(int32_t stringLimit); + + /** + * Set the maximum container size allowed by TBinaryProtocol. + * + * This setting helps prevent TBinaryProtocol from trying to allocate an + * extremely large buffer if a request contains a bogus container length + * field. (e.g., for list, map, and set fields.) + * + * This setting is ignored if you explicitly specify a TProtocolFactory to + * use. It is only honored if you let the ServerCreator create a new + * TBinaryProtocol for you. + * + * If unspecified, it defaults to 256MB. + */ + void setContainerSizeLimit(int32_t containerLimit); + + /** + * Set the protocol factory to use. + * + * This causes the ServerCreator to use the specified protocol factory. + * This overrides the TBinaryProtocol-related settings that would normally be + * used by the ServerCreator. + */ + void setProtocolFactory(const boost::shared_ptr&); + + /** + * Set the protocol factory to use. + * + * This causes the ServerCreator to use the specified protocol factory + * to construct custom input and output protocols. This overrides the + * TBinaryProtocol-related settings that would normally be used by the + * ServerCreator. + */ + void setDuplexProtocolFactory( + const boost::shared_ptr&); + + /** + * Create a new server. + */ + virtual boost::shared_ptr createServer() = 0; + + protected: + ServerCreatorBase(); + + /** + * Configure the TServer as desired. + * + * Subclasses should call this method in createServer(). + */ + virtual void configureServer(const boost::shared_ptr& srv); + + /** + * Get the TProtocolFactory to use for the server. + * + * Subclasses should call this method in createServer(). + */ + virtual boost::shared_ptr getProtocolFactory(); + + virtual boost::shared_ptr + getDuplexProtocolFactory(); + + bool strictRead_; + bool strictWrite_; + int32_t stringLimit_; + int32_t containerLimit_; + boost::shared_ptr serverEventHandler_; + boost::shared_ptr protocolFactory_; + boost::shared_ptr duplexProtocolFactory_; +}; + +}}} // apache::thrift::util + +#endif // THRIFT_UTIL_SERVERCREATORBASE_H_ diff --git a/thrift/lib/cpp/util/SyncServerCreator.h b/thrift/lib/cpp/util/SyncServerCreator.h new file mode 100644 index 00000000..bf988017 --- /dev/null +++ b/thrift/lib/cpp/util/SyncServerCreator.h @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_UTIL_SYNCSERVERCREATOR_H_ +#define THRIFT_UTIL_SYNCSERVERCREATOR_H_ 1 + +#include "thrift/lib/cpp/util/ServerCreatorBase.h" + +#include + +namespace apache { namespace thrift { + +class TProcessor; + +namespace transport { +class TTransportFactory; +class TDuplexTransportFactory; +class TServerSocket; +} + +namespace util { + +/** + * Helper class for the standard synchronous server types (TSimpleServer, + * TThreadedServer, TThreadPoolServer) + */ +class SyncServerCreator : public ServerCreatorBase { + public: + /** + * Default to a 30 second receive timeout. + * + * Almost everyone should use a receive timeout, to avoid tracking connection + * state indefinitely if a client drops of the network without closing the + * connection. + */ + static const int DEFAULT_RECEIVE_TIMEOUT = 30000; + + /** + * Default to a 5 second send timeout. + * + * This is still a fairly large value. Some users may want to decrease this. + */ + static const int DEFAULT_SEND_TIMEOUT = 5000; + + /** + * Don't use an accept timeout by default. + * + * Almost everyone wants this. With a timeout, serve() will raise an + * exception if a new connection doesn't arrive within the timeout interval. + */ + static const int DEFAULT_ACCEPT_TIMEOUT = -1; + + /** + * By default, don't mess with the kernel's default TCP send buffer size. + */ + static const int DEFAULT_TCP_SEND_BUFFER = -1; + + /** + * By default, don't mess with the kernel's default TCP receive buffer size. + */ + static const int DEFAULT_TCP_RECEIVE_BUFFER = -1; + + /** + * Create a new SyncServerCreator + */ + SyncServerCreator(const boost::shared_ptr& processor, + uint16_t port, bool framed = true); + + /** + * Create a new SyncServerCreator + */ + SyncServerCreator(const boost::shared_ptr& processor, + uint16_t port, + boost::shared_ptr& tf, + boost::shared_ptr& pf); + + /** + * Set the send timeout. + * + * Connections will be dropped if no progress is made sending a response + * for this many milliseconds. + */ + void setSendTimeout(int milliseconds); + + /** + * Set the receive timeout. + * + * Connections will be dropped if there are no requests for this many + * milliseconds. + */ + void setRecvTimeout(int milliseconds); + + /** + * Set the accept timeout. + * + * serve() will raise an exception if no new connections are received for + * this many milliseconds. + */ + void setAcceptTimeout(int milliseconds); + + /** + * Set the TCP send buffer size. + */ + void setTcpSendBuffer(int tcpSendBuffer); + + /** + * Set the TCP receive buffer size. + */ + void setTcpRecvBuffer(int tcpRecvBuffer); + + /** + * Set the transport factory + */ + void setTransportFactory( + const boost::shared_ptr& tf) { + transportFactory_ = tf; + } + + /** + * Set the duplex transport factory. This overrides the base + * transportFactory_ if one was specified + */ + void setDuplexTransportFactory( + const boost::shared_ptr& tf) { + duplexTransportFactory_ = tf; + } + + /** + * Get the duplex transport factory, instantiating one from the base + * transportFactory_ if needed + */ + boost::shared_ptr getDuplexTransportFactory(); + /** + * Create a new server. + */ + virtual boost::shared_ptr createServer() = 0; + + protected: + void init(const boost::shared_ptr& processor, uint16_t port); + + boost::shared_ptr createServerSocket(); + + uint16_t port_; + int sendTimeout_; + int recvTimeout_; + int acceptTimeout_; + int tcpSendBuffer_; + int tcpRecvBuffer_; + boost::shared_ptr processor_; + boost::shared_ptr transportFactory_; + boost::shared_ptr duplexTransportFactory_; +}; + +}}} // apache::thrift::util + +#endif // THRIFT_UTIL_SYNCSERVERCREATOR_H_ diff --git a/thrift/lib/cpp/util/TEventServerCreator.h b/thrift/lib/cpp/util/TEventServerCreator.h new file mode 100644 index 00000000..d8c32d8b --- /dev/null +++ b/thrift/lib/cpp/util/TEventServerCreator.h @@ -0,0 +1,234 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_UTIL_TEVENTSERVERCREATOR_H_ +#define THRIFT_UTIL_TEVENTSERVERCREATOR_H_ 1 + +#include "thrift/lib/cpp/util/ServerCreatorBase.h" + +#include + +namespace apache { namespace thrift { + +class TProcessor; + +namespace concurrency { +class ThreadManager; +} + +namespace async { +class TAsyncProcessor; +class TEventServer; +} + +namespace util { + +class TEventServerCreator : public ServerCreatorBase { + public: + typedef async::TEventServer ServerType; + + /// Use 8 IO worker threads by default. + static const size_t DEFAULT_NUM_IO_THREADS = 8; + + /// Use 8 task worker threads by default. + static const size_t DEFAULT_NUM_TASK_THREADS = 8; + + /// Default limit on the size of each worker's idle connection pool + static const uint32_t DEFAULT_CONN_POOL_SIZE = 64; + + /// By default, close connections after they have are idle for 60 seconds + static const int DEFAULT_RECV_TIMEOUT = 60000; + + /** + * By default, reject requests over 64MB. + * + * This avoids allocating giant buffers if a client sends a bogus frame + * length. + */ + static const size_t DEFAULT_MAX_FRAME_SIZE = 64 * 1024 * 1024; + + /** + * Start dropping connections to reduce load if a worker's event loop begins + * taking longer than 2 seconds to process a single event loop. + */ + static const int64_t DEFAULT_WORKER_LATENCY = 2000; + + /// Default size of each connection's write buffer + static const size_t DEFAULT_WRITE_BUFFER_SIZE = 1024; + + /// Default size of each connection's read buffer + static const size_t DEFAULT_READ_BUFFER_SIZE = 1024; + + /// Maximum size of read buffer allocated to each idle connection + static const size_t DEFAULT_IDLE_READ_BUF_LIMIT = 8192; + + /// Maximum size of write buffer allocated to each idle connection + static const size_t DEFAULT_IDLE_WRITE_BUF_LIMIT = 8192; + + /** + * By check to see if we should shrink oversized read/write buffers after + * every 64 calls on connection. + */ + static const int DEFAULT_RESIZE_EVERY_N = 64; + + /** + * Create a new TEventServerCreator to be used for building a native-mode + * TEventServer. + */ + TEventServerCreator( + const boost::shared_ptr& asyncProcessor, + uint16_t port, + size_t numIoThreads = DEFAULT_NUM_IO_THREADS); + + /** + * Create a new TEventServerCreator to be used for building a queuing-mode + * TEventServer. + */ + TEventServerCreator( + const boost::shared_ptr& syncProcessor, + uint16_t port, + size_t numIoThreads = DEFAULT_NUM_IO_THREADS, + size_t numTaskThreads = DEFAULT_NUM_TASK_THREADS); + + /** + * Set the number of IO threads to use. + */ + void setNumIoThreads(size_t numIoThreads) { + numIoThreads_ = numIoThreads; + } + + /** + * Set the number of task threads to use. + */ + void setNumTaskThreads(size_t numTaskThreads) { + numTaskThreads_ = numTaskThreads; + } + + /** + * Set the thread manager to use for task queue threads. + */ + void setTaskQueueThreadManager( + const boost::shared_ptr& threadManager) { + taskQueueThreadManager_ = threadManager; + } + + /** + * Set the maximum number of TEventConnection objects to cache in each worker + * thread. + * + * By default, when a connection is closed the worker thread caches the + * TEventConnection object and re-uses it when a new connection comes in, + * instead of deleting it and allocating a new one for the next connection. + * This value caps the number of unused TEventConnection objects that will be + * cached. + */ + void setMaxConnectionPoolSize(uint32_t size) { + maxConnPoolSize_ = size; + } + + /** + * Set the maximum amount of time a connection may be idle before it is + * closed. + */ + void setRecvTimeout(int milliseconds) { + recvTimeout_ = milliseconds; + } + + /// Set the maximum allowed request frame size. + void setMaxFrameSize(uint32_t maxFrameSize) { + maxFrameSize_ = maxFrameSize; + } + + /// Set the default write buffer size for new connections + void setReadBufferDefaultSize(size_t size) { + defaultReadBufferSize_ = size; + } + + /// Set the default write buffer size for new connections + void setWriteBufferDefaultSize(size_t size) { + defaultWriteBufferSize_ = size; + } + + /** + * Set the maximum read buffer size for idle connections. + * + * This value is checked when the connection is closed, and also every N + * connections if setResizeBufferEveryN() has been set. If the read buffer + * is larger than the allowed limit, free it. + * + * This prevents a single large request on a connection from continuing to + * taking up a lot of buffer space. + */ + void setIdleReadBufferLimit(size_t limit) { + idleReadBufferLimit_ = limit; + } + + /** + * Set the maximum write buffer size for idle connections. + * + * This value is checked when the connection is closed, and also every N + * connections if setResizeBufferEveryN() has been set. If the write buffer + * is larger than the allowed limit, free it. + * + * This prevents a single large response on a connection from continuing to + * taking up a lot of buffer space. + */ + void setIdleWriteBufferLimit(size_t limit) { + idleWriteBufferLimit_ = limit; + } + + /// Check a connection's buffer size limits every count requests. + void setResizeBufferEveryN(int32_t count) { + resizeBufferEveryN_ = count; + } + + /** + * Set the worker latency limit. + * + * Begin taking overload actions when it takes longer than this amount of + * time to process a single iteration of the event loop. + */ + void setWorkerLatencyLimit(int64_t milliseconds) { + workerLatencyLimit_ = milliseconds; + } + + virtual boost::shared_ptr createServer(); + + boost::shared_ptr createEventServer(); + + private: + boost::shared_ptr syncProcessor_; + boost::shared_ptr asyncProcessor_; + boost::shared_ptr taskQueueThreadManager_; + uint16_t port_; + size_t numIoThreads_; + size_t numTaskThreads_; + uint32_t maxConnPoolSize_; + int recvTimeout_; + uint32_t maxFrameSize_; + size_t defaultReadBufferSize_; + size_t defaultWriteBufferSize_; + size_t idleReadBufferLimit_; + size_t idleWriteBufferLimit_; + int32_t resizeBufferEveryN_; + int32_t workerLatencyLimit_; +}; + +}}} // apache::thrift::util + +#endif // THRIFT_UTIL_TEVENTSERVERCREATOR_H_ diff --git a/thrift/lib/cpp/util/THttpParser.h b/thrift/lib/cpp/util/THttpParser.h new file mode 100644 index 00000000..de953f51 --- /dev/null +++ b/thrift/lib/cpp/util/THttpParser.h @@ -0,0 +1,130 @@ +#ifndef THRIFT_TRANSPORT_THTTPPARSER_H_ +#define THRIFT_TRANSPORT_THTTPPARSER_H_ 1 + +#include + +namespace apache { namespace thrift { namespace util { + +class THttpParser { + protected: + enum HttpParseState { + HTTP_PARSE_START = 0, + HTTP_PARSE_HEADER, + HTTP_PARSE_CHUNK, + HTTP_PARSE_CONTENT, + HTTP_PARSE_CHUNKFOOTER, + HTTP_PARSE_TRAILING + }; + + enum HttpParseResult { + HTTP_PARSE_RESULT_CONTINUE, + HTTP_PARSE_RESULT_BLOCK + }; + + public: + THttpParser(); + ~THttpParser(); + + void getReadBuffer(void** bufReturn, size_t* lenReturn); + bool readDataAvailable(size_t len); + void setDataBuffer(apache::thrift::transport::TMemoryBuffer* buffer) { + dataBuf_ = buffer; + } + void unsetDataBuffer() { + dataBuf_ = NULL; + } + void setMaxSize(uint32_t size) { + maxSize_ = size; + } + uint32_t getMaxSize() { + return maxSize_; + } + bool hasReadAheadData() { + return (state_ == HTTP_PARSE_START) && (httpBufLen_ > httpPos_); + } + bool hasPartialMessage() { + return partialMessageSize_ > 0; + } + virtual int constructHeader(iovec* ops, + int opsLen, + int contentLength, + char* contentLengthBuf) = 0; + + protected: + HttpParseResult parseStart(); + HttpParseResult parseHeader(); + HttpParseResult parseContent(); + HttpParseResult parseChunk(); + HttpParseResult parseChunkFooter(); + HttpParseResult parseTrailing(); + + virtual bool parseStatusLine(const char* status) = 0; + virtual void parseHeaderLine(const char* header) = 0; + + void shift(); + char* readLine(); + void checkMessageSize(uint32_t more, bool added); + + char* httpBuf_; + uint32_t httpPos_; + uint32_t httpBufLen_; + uint32_t httpBufSize_; + + HttpParseState state_; + + // for read header + bool statusLine_; + bool finished_; + bool chunked_; + + size_t contentLength_; + + // max http message size + uint32_t maxSize_; + uint32_t partialMessageSize_; + + apache::thrift::transport::TMemoryBuffer* dataBuf_; + + static const char* CRLF; + static const int CRLF_LEN; +}; + +class THttpClientParser : public THttpParser { + public: + THttpClientParser(std::string host, std::string path) { + host_ = host; + path_ = path; + userAgent_ = "C++/THttpClient"; + } + void setHost(const std::string& host) { host_ = host; } + void setPath(const std::string& path) { path_ = path; } + void resetConnectClosedByServer(); + bool isConnectClosedByServer(); + void setUserAgent(std::string userAgent) { + userAgent_ = userAgent; + } + virtual int constructHeader(iovec* ops, + int opsLen, + int contentLength, + char* contentLengthBuf); + + protected: + virtual void parseHeaderLine(const char* header); + virtual bool parseStatusLine(const char* status); + void setiovec(iovec* ops, const char* data, int size) { + ops->iov_base = (void*)data; + ops->iov_len = size; + } + + private: + bool connectionClosedByServer_; + std::string host_; + std::string path_; + std::string userAgent_; +}; + + +}}} // apache::thrift::util + +#endif // #ifndef THRIFT_TRANSPORT_THTTPPARSER_H_ + diff --git a/thrift/lib/cpp/util/TNonblockingServerCreator.h b/thrift/lib/cpp/util/TNonblockingServerCreator.h new file mode 100644 index 00000000..4bd96285 --- /dev/null +++ b/thrift/lib/cpp/util/TNonblockingServerCreator.h @@ -0,0 +1,275 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_UTIL_TNONBLOCKINGSERVERCREATOR_H_ +#define THRIFT_UTIL_TNONBLOCKINGSERVERCREATOR_H_ 1 + +#include "thrift/lib/cpp/util/ServerCreatorBase.h" + +#include "thrift/lib/cpp/server/TNonblockingServer.h" +#include "thrift/lib/cpp/transport/TSocket.h" + +namespace apache { namespace thrift { + +class TProcessor; + +namespace util { + +class TNonblockingServerCreator : public ServerCreatorBase { + public: + typedef server::TNonblockingServer ServerType; + + /// Use 8 task threads by default. + static const size_t DEFAULT_NUM_TASK_THREADS = 8; + + /// Use 1 I/O thread by default. + static const size_t DEFAULT_NUM_IO_THREADS = 1; + + /** + * By default, just run the I/O threads with the same priority as other + * threads. + */ + static const bool DEFAULT_HI_PRI_IO_THREADS = false; + + /// Default limit on the size of the idle connection pool + static const size_t DEFAULT_CONN_STACK_LIMIT = 1024; + + /// Default limit on the total number of connected sockets + static const size_t DEFAULT_MAX_CONNECTIONS = INT_MAX; + + /// Default limit on the number of outstanding requests + static const size_t DEFAULT_MAX_ACTIVE_PROCESSORS = INT_MAX; + + /** + * By default, reject requests over 256MB. + * + * This avoids allocating giant buffers if a client sends a bogus frame + * length. + */ + static const size_t DEFAULT_MAX_FRAME_SIZE = 256 * 1024 * 1024; + + /// Default overload hysteresis fraction + static const double DEFAULT_HYSTERESIS_FRACTION; + + /** + * Default overload action. + * + * TODO: None of the TNonblockingServer OverloadAction behaviors seem like + * reasonable defaults. If the overload is occurring because we hit the + * maxConnections limit, it seems like the best behavior is to try and close + * idle connections. If the overload is occurring due to the + * maxActiveProcessors limit, it seems like the best behavior may be to stop + * calling accept() and stop reading on sockets until the # of active + * processors drops to a reasonable limit. + */ + static const server::TOverloadAction DEFAULT_OVERLOAD_ACTION = + server::T_OVERLOAD_NO_ACTION; + + /** + * By default, give up on a request if we can't find a thread to process it + * within 30 seconds. + */ + static const int64_t DEFAULT_TASK_EXPIRE_TIME = 30000; + + /// Default size of write buffer + static const size_t DEFAULT_WRITE_BUFFER_SIZE = 1024; + + /// Maximum size of read buffer allocated to each idle connection + static const size_t DEFAULT_IDLE_READ_BUF_LIMIT = 8192; + + /// Maximum size of write buffer allocated to each idle connection + static const size_t DEFAULT_IDLE_WRITE_BUF_LIMIT = 8192; + + /** + * By check to see if we should shrink oversized read/write buffers after + * every 64 calls on connection. + */ + static const int DEFAULT_RESIZE_EVERY_N = 64; + + /// listen backlog + static const size_t DEFAULT_LISTEN_BACKLOG = 1024; + + /** + * Create a new TNonblockingServerCreator. + */ + TNonblockingServerCreator(const boost::shared_ptr& processor, + uint16_t port, + size_t numTaskThreads = DEFAULT_NUM_TASK_THREADS); + + /** + * Set the number of threads to use for processing requests. + * + * Setting this to 0 causes all requests to be processed in the I/O + * thread(s). You should only set this to 0 if the handler responds to all + * requests immediately, without ever blocking. + */ + void setNumTaskThreads(size_t numThreads) { + numTaskThreads_ = numThreads; + } + + /** + * Set the ThreadFactory to use for creating the task threads. + */ + void setTaskThreadFactory( + const boost::shared_ptr& threadFactory) { + taskThreadFactory_ = threadFactory; + } + + /** + * Set the number of threads to use for performing I/O. + */ + void setNumIOThreads(size_t numThreads) { + numIOThreads_ = numThreads; + } + + /** + * Set whether or not the I/O threads should be given a higher scheduling + * priority. + */ + void setUseHighPriorityIOThreads(bool useHiPri) { + useHiPriIOThreads_ = useHiPri; + } + + /** + * Set the maximum number of TConnection objects to cache. + * + * By default, when a connection is closed TNonblockingServer caches the + * TConnection object and re-uses it when a new connection comes in, instead + * of deleting it and allocating a new one for the next connection. This + * value caps the number of unused TConnection objects that will be cached. + */ + void setConnectionStackLimit(size_t limit) { + connectionStackLimit_ = limit; + } + + /// Set the maximum number of open connections + void setMaxConnections(size_t maxConnections) { + maxConnections_ = maxConnections; + } + + /// Set the maximum number of active requests + void setMaxActiveProcessors(size_t maxActiveProcessors) { + maxActiveProcessors_ = maxActiveProcessors; + } + + /// Set the maximum allowed request frame size. + void setMaxFrameSize(size_t maxFrameSize) { + maxFrameSize_ = maxFrameSize; + } + + /// Set the overload hysteresis fraction + void setOverloadHysteresis(double hysteresisFraction) { + hysteresisFraction_ = hysteresisFraction; + } + + /// Set the overload action + void setOverloadAction(server::TOverloadAction action) { + overloadAction_ = action; + } + + /** + * Set the task expiration time. + * + * If no task thread is available to process a request within taskExpireTime + * milliseconds, close the connection rather than continuing to wait for a + * thread. If the server is overloaded, this prevents it from processing + * old requests that the client has already given up on. + */ + void setTaskExpireTime(int64_t taskExpireTime) { + taskExpireTime_ = taskExpireTime; + } + + /** + * Set the socket options to use for accepted connections + */ + void setSocketOptions(const transport::TSocket::Options& options) { + socketOptions_ = options; + } + + /// Set the default write buffer size for new connections + void setWriteBufferDefaultSize(size_t size) { + defaultWriteBufferSize_ = size; + } + + /** + * Set the maximum read buffer size for idle connections. + * + * This value is checked when the connection is closed, and also every N + * connections if setResizeBufferEveryN() has been set. If the read buffer + * is larger than the allowed limit, free it. + * + * This prevents a single large request on a connection from continuing to + * taking up a lot of buffer space. + */ + void setIdleReadBufferLimit(size_t limit) { + idleReadBufferLimit_ = limit; + } + + /** + * Set the maximum write buffer size for idle connections. + * + * This value is checked when the connection is closed, and also every N + * connections if setResizeBufferEveryN() has been set. If the write buffer + * is larger than the allowed limit, free it. + * + * This prevents a single large response on a connection from continuing to + * taking up a lot of buffer space. + */ + void setIdleWriteBufferLimit(size_t limit) { + idleWriteBufferLimit_ = limit; + } + + /// Check a connection's buffer size limits every count requests. + void setResizeBufferEveryN(int32_t count) { + resizeBufferEveryN_ = count; + } + + /// listen backlog + void setListenBacklog(int32_t listenBacklog) { + listenBacklog_ = listenBacklog; + } + + virtual boost::shared_ptr createServer(); + + boost::shared_ptr createNonblockingServer(); + + private: + boost::shared_ptr processor_; + uint16_t port_; + size_t numTaskThreads_; + size_t numIOThreads_; + bool useHiPriIOThreads_; + size_t connectionStackLimit_; + size_t maxConnections_; + size_t maxActiveProcessors_; + size_t maxFrameSize_; + double hysteresisFraction_; + server::TOverloadAction overloadAction_; + int64_t taskExpireTime_; + size_t defaultWriteBufferSize_; + size_t idleReadBufferLimit_; + size_t idleWriteBufferLimit_; + int32_t resizeBufferEveryN_; + int32_t listenBacklog_; + transport::TSocket::Options socketOptions_; + boost::shared_ptr taskThreadFactory_; +}; + +}}} // apache::thrift::util + +#endif // THRIFT_UTIL_TNONBLOCKINGSERVERCREATOR_H_ diff --git a/thrift/lib/cpp/util/TSimpleServerCreator.h b/thrift/lib/cpp/util/TSimpleServerCreator.h new file mode 100644 index 00000000..8204eecf --- /dev/null +++ b/thrift/lib/cpp/util/TSimpleServerCreator.h @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_UTIL_TSIMPLESERVERCREATOR_H_ +#define THRIFT_UTIL_TSIMPLESERVERCREATOR_H_ 1 + +#include "thrift/lib/cpp/util/SyncServerCreator.h" + +namespace apache { namespace thrift { + +namespace server { +class TSimpleServer; +} + +namespace util { + +class TSimpleServerCreator : public SyncServerCreator { + public: + typedef server::TSimpleServer ServerType; + + /** + * Create a new TSimpleServerCreator. + */ + TSimpleServerCreator(const boost::shared_ptr& processor, + uint16_t port, + bool framed = true) + : SyncServerCreator(processor, port, framed) {} + + /** + * Create a new TSimpleServerCreator. + */ + TSimpleServerCreator(const boost::shared_ptr& processor, + uint16_t port, + boost::shared_ptr& tf, + boost::shared_ptr& pf) + : SyncServerCreator(processor, port, tf, pf) {} + + virtual boost::shared_ptr createServer(); + + boost::shared_ptr createSimpleServer(); +}; + +}}} // apache::thrift::util + +#endif // THRIFT_UTIL_TSIMPLESERVERCREATOR_H_ diff --git a/thrift/lib/cpp/util/TThreadPoolServerCreator.h b/thrift/lib/cpp/util/TThreadPoolServerCreator.h new file mode 100644 index 00000000..9732e3b6 --- /dev/null +++ b/thrift/lib/cpp/util/TThreadPoolServerCreator.h @@ -0,0 +1,134 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_UTIL_TTHREADPOOLSERVERCREATOR_H_ +#define THRIFT_UTIL_TTHREADPOOLSERVERCREATOR_H_ 1 + +#include "thrift/lib/cpp/util/SyncServerCreator.h" + +namespace apache { namespace thrift { + +namespace concurrency { +class ThreadFactory; +} +namespace server { +class TThreadPoolServer; +} + +namespace util { + +class TThreadPoolServerCreator : public SyncServerCreator { + public: + typedef server::TThreadPoolServer ServerType; + + enum OverloadAction { + OVERLOAD_STOP_ACCEPTING, + OVERLOAD_ACCEPT_AND_CLOSE, + }; + + /** + * By default, stop calling accept() once we reach the maximum number pending + * tasks. + */ + static const OverloadAction DEFAULT_OVERLOAD_ACTION = + OVERLOAD_STOP_ACCEPTING; + + /** + * Use 30 threads by default. + * + * Make sure to set this number large enough for your service. If there are + * more active connections than number of threads, new connections will + * block until one of the existing connections is closed! Typically you + * should also use a small receive timeout with TThreadPoolServer, to + * quickly expire idle connections. + */ + static const size_t DEFAULT_NUM_THREADS = 30; + + /** + * By default, only allow up to 30 pending connections waiting for a thread + * to run. + * + * Once all threads are in use, at most this many additional tasks may be + * queued before the server starts taking the OverloadAction. + */ + static const size_t DEFAULT_MAX_PENDING_TASKS = 30; + + /** + * Create a new TThreadPoolServerCreator. + */ + TThreadPoolServerCreator(const boost::shared_ptr& processor, + uint16_t port, + bool framed = true); + + /** + * Create a new TThreadPoolServerCreator. + */ + TThreadPoolServerCreator(const boost::shared_ptr& processor, + uint16_t port, + int numThreads, + bool framed = true); + + /** + * Create a new TThreadPoolServerCreator. + */ + TThreadPoolServerCreator(const boost::shared_ptr& processor, + uint16_t port, + boost::shared_ptr& tf, + boost::shared_ptr& pf); + + /** + * Set the action to take once all threads are in use and the pending task + * queue is full. + */ + void setOverloadAction(OverloadAction action) { + overloadAction_ = action; + } + + /** + * Set the number of threads to use for the thread pool + */ + void setNumThreads(size_t numThreads) { + numThreads_ = numThreads; + } + + /** + * Set the maximum number of pending tasks. + */ + void setMaxPendingTasks(size_t numTasks) { + maxPendingTasks_ = numTasks; + } + + /** + * Set the thread factory + */ + void setThreadFactory(const boost::shared_ptr&); + + virtual boost::shared_ptr createServer(); + + boost::shared_ptr createThreadPoolServer(); + + private: + OverloadAction overloadAction_; + size_t numThreads_; + size_t maxPendingTasks_; + boost::shared_ptr threadFactory_; +}; + +}}} // apache::thrift::util + +#endif // THRIFT_UTIL_TTHREADPOOLSERVERCREATOR_H_ diff --git a/thrift/lib/cpp/util/TThreadedServerCreator.h b/thrift/lib/cpp/util/TThreadedServerCreator.h new file mode 100644 index 00000000..6155a23b --- /dev/null +++ b/thrift/lib/cpp/util/TThreadedServerCreator.h @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_UTIL_TTHREADEDSERVERCREATOR_H_ +#define THRIFT_UTIL_TTHREADEDSERVERCREATOR_H_ 1 + +#include "thrift/lib/cpp/util/SyncServerCreator.h" + +namespace apache { namespace thrift { + +namespace concurrency { +class ThreadFactory; +} +namespace server { +class TThreadedServer; +} + +namespace util { + +class TThreadedServerCreator : public SyncServerCreator { + public: + typedef server::TThreadedServer ServerType; + + /** + * Create a new TThreadedServerCreator. + */ + TThreadedServerCreator(const boost::shared_ptr& processor, + uint16_t port, + bool framed = true) + : SyncServerCreator(processor, port, framed) {} + + /** + * Create a new TThreadedServerCreator. + */ + TThreadedServerCreator(const boost::shared_ptr& processor, + uint16_t port, + boost::shared_ptr& tf, + boost::shared_ptr& pf) + : SyncServerCreator(processor, port, tf, pf) {} + + /** + * Set the thread factory + */ + void setThreadFactory(const boost::shared_ptr&); + + virtual boost::shared_ptr createServer(); + + boost::shared_ptr createThreadedServer(); + + private: + boost::shared_ptr threadFactory_; +}; + +}}} // apache::thrift::util + +#endif // THRIFT_UTIL_TTHREADEDSERVERCREATOR_H_ diff --git a/thrift/lib/cpp/util/ThriftSerializer-inl.h b/thrift/lib/cpp/util/ThriftSerializer-inl.h new file mode 100644 index 00000000..fac416d3 --- /dev/null +++ b/thrift/lib/cpp/util/ThriftSerializer-inl.h @@ -0,0 +1,191 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// @author Karl Voskuil (karl@facebook.com) +// @author Mark Rabkin (mrabkin@facebook.com) +// + +#ifndef COMMON_STRINGS_THRIFT_SERIALIZER_INL_H +#define COMMON_STRINGS_THRIFT_SERIALIZER_INL_H + +#include +#include +#include "common/logging/logging.h" +#include "thrift/lib/cpp/util/ThriftSerializer.h" + +namespace apache { namespace thrift { namespace util { + +template +template +void +ThriftSerializer::serialize(const T& fields, String* serialized) +{ + // prepare or reset buffer + // + // note: Three cases: + // + // 1) The buffer has never been prepared. Call prepare(). + // + // 2) The buffer was last used for a deserialize() call. In this + // case, the buffer is pointing to a now-invalid constant + // string, and the buffer should be reallocated. + // + // 3) The buffer was last used for a serialize() call. In this + // case, the buffer is still pointing to a valid buffer, but it + // contains the serialization from the last serialize(), and + // the buffer just needs to be reset. + // + // This would be a little simpler if we allocated separate buffers + // and protocols for serialization and deserialization, but it + // seemed to me that this fit the common use cases better. The case + // that performs poorly (20% slower) is doing many alternating + // serializations and deserializations. + if (!prepared_ || lastDeserialized_) { + prepare(); + } else { + buffer_->resetBuffer(); + } + lastDeserialized_ = false; + + // serialize fields into buffer + fields.write(protocol_.get()); + + // assign buffer to string + uint8_t *byteBuffer; + uint32_t byteBufferSize; + buffer_->getBuffer(&byteBuffer, &byteBufferSize); + serialized->assign((const char*)byteBuffer, byteBufferSize); +} + +template +void +ThriftSerializer::serialize(const T& fields, + const uint8_t** serializedBuffer, + size_t* serializedLen) { + CHECK(serializedBuffer); + CHECK(serializedLen); + + // prepare or reset buffer + if (!prepared_ || lastDeserialized_) { + prepare(); + } else { + buffer_->resetBuffer(); + } + lastDeserialized_ = false; + + // serialize fields into buffer + fields.write(protocol_.get()); + + // assign buffer to string + uint8_t *byteBuffer; + uint32_t byteBufferSize; + buffer_->getBuffer(&byteBuffer, &byteBufferSize); + *serializedBuffer = byteBuffer; + *serializedLen = byteBufferSize; +} + + +// Deserializes a thrift object, but assumes that the object passed in the +// fields argument is "clean". If your thrift class contains optional fields, +// you should use deserialize() instead (see below), otherwise optional fields +// that were previously set by other calls to this function won't get reset, +// and will appear to have been desearialized along with the other fields. +template +template +uint32_t +ThriftSerializer::deserializeClean(const String& serialized, T* fields) +{ + // prepare buffer if necessary + if (!prepared_) { + prepare(); + } + lastDeserialized_ = true; + + // reset buffer transport to passed string + buffer_->resetBuffer((uint8_t*)serialized.data(), serialized.size()); + + // deserialize buffer into fields + return fields->read(protocol_.get()); +} + +template +uint32_t +ThriftSerializer::deserialize(const uint8_t* serializedBuffer, + size_t length, + T* fields) +{ + // prepare buffer if necessary + if (!prepared_) { + prepare(); + } + lastDeserialized_ = true; + + // reset buffer transport to passed string + buffer_->resetBuffer((uint8_t*)serializedBuffer, length); + + // need to clean the existing structure, as fields->read() will not overwrite + // the optional fields that were not set in the serialized object. + T emptyFields; + swap(emptyFields, *fields); + + // deserialize buffer into fields + return fields->read(protocol_.get()); +} + +template +void +ThriftSerializer::setVersion(int8_t version) +{ + version_ = version; + setVersion_ = true; +} + +template +void +ThriftSerializer::prepare() +{ + // create memory buffer to use as transport + // + // note: TMemoryBuffer won't write to the buffer unless it is the + // owner of it, which means that we can't pass in our own local + // buffer. Either must malloc a buffer which TMemoryBuffer will + // free, or else just let it malloc its own. This has the added + // benefit that TMemoryBuffer will grow the buffer size as + // necessary. + // + // The initial allocation of the memory buffer might seem + // unnecessary in case of parsing (since the memory buffer will be + // reset to point to the string passed to parseSerializer()), but + // it's apparently necessary for some protocols. + buffer_.reset(new TMemoryBuffer()); + + // create a protocol for the memory buffer transport + protocol_.reset(new Protocol(buffer_)); + if (setVersion_) { + protocol_->setVersion(version_); + } + + prepared_ = true; +} + + +}}} // namespace apache::thrift::util + + +#endif diff --git a/thrift/lib/cpp/util/ThriftSerializer.h b/thrift/lib/cpp/util/ThriftSerializer.h new file mode 100644 index 00000000..80099b9a --- /dev/null +++ b/thrift/lib/cpp/util/ThriftSerializer.h @@ -0,0 +1,224 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// @author Karl Voskuil (karl@facebook.com) +// @author Mark Rabkin (mrabkin@facebook.com) +// + +#ifndef COMMON_STRINGS_THRIFT_SERIALIZER_H +#define COMMON_STRINGS_THRIFT_SERIALIZER_H + +#include +#include + +#include "thrift/lib/cpp/protocol/TBinaryProtocol.h" // for serialization +#include "thrift/lib/cpp/protocol/TCompactProtocol.h" // for serialization +#include "thrift/lib/cpp/protocol/TJSONProtocol.h" // for serialization +#include "thrift/lib/cpp/protocol/TSimpleJSONProtocol.h" // for serialization +#include "thrift/lib/cpp/transport/TTransportUtils.h" // for serialization + +namespace apache { namespace thrift { namespace util { + +using apache::thrift::protocol::TBinaryProtocolT; +using apache::thrift::protocol::TCompactProtocolT; +using apache::thrift::protocol::TCompactProtocol; +using apache::thrift::protocol::TSimpleJSONProtocol; +using apache::thrift::protocol::TJSONProtocol; +using apache::thrift::transport::TBufferBase; +using apache::thrift::transport::TTransport; +using apache::thrift::transport::TMemoryBuffer; +using boost::shared_ptr; + +/** + * Encapsulates methods to serialize or deserialize a code-gen-ed + * Thrift class to and from a string. For example: + * + * extern StatsMcValue data; + * + * ThriftSerializerBinary serializer; + * string serialized; + * serializer.serialize(data, &serizalied); + * + * StatsMcValue result; + * try { + * if (serializer.deserialize(serialized, &result) != + * serialized.length()) { + * // Handle deserialization error, not all data consumed. + * } + * } catch (TProtocolException& tpe) { + * // Handle deserialization error, underlying protocol threw. + * } + * // Use deserialized thrift object. + * ... + * + * @author Karl Voskuil + */ + +template +class ThriftSerializer { + public: + ThriftSerializer() + : prepared_(false) + , lastDeserialized_(false) + , setVersion_(false) {} + + /** + * Serializes the passed type into the passed string. + * + * @author Karl Voskuil + */ + template + void serialize(const T& fields, String* serialized); + + /** + * Serializes the passed type into the internal buffer + * and returns a pointer to the internal buffer and its size. + * + * @author Yuri Putivsky + */ + void serialize(const T& fields, const uint8_t** serializedBuffer, + size_t* serializedLen); + + /** + * Deserializes the passed string into the passed type, returns the number of + * bytes that have been consumed from the passed string. + * + * The return value can be used to verify if the deserialization is successful + * or not. When a type is serialized then deserialized back, the number of + * consumed bytes must equal to the size of serialized string. But please + * note, equality of these two values doesn't guarantee the serialized string + * isn't corrupt. It's up to the underlying implementation of the type and + * thrift protocol to detect and handle invalid serialized string, they may + * throw exception or just ignore the unrecognized data. + * @author Karl Voskuil + */ + template + uint32_t deserialize(const String& serialized, T* fields) + { + return deserialize((const uint8_t*)serialized.data(), + serialized.size(), + fields); + } + + /** + * Deserializes the passed char array into the passed type, returns the number + * of bytes that have been consumed from the passed string. + * + * See notes on return value for: + * deserilize(const String* serialized, T* fields) + */ + uint32_t deserialize(const uint8_t* serializedBuffer, + size_t length, + T* fields); + + /** + * Same as deserialize() above, but won't touch/reset any optional fields + * that are not present in 'serialized'. So, if T has any optional fields, + * the caller is responsible for resetting those (or somehow handling the + * potentially dirty data.) + * + * Use this method if: + * 1) your thrift class doesn't contain any optional fields, and + * 2) you are trying to avoid memory allocations/fragmentation during + * deserialization of thift objects + * + * @author Rafael Sagula + */ + template + uint32_t deserializeClean(const String& serialized, T* fields); + + /** + * Set version of protocol data to read/write. This is only necessary + * for data that will be saved to disk between protocol versions! + * You probably don't need to use this unless you know what you are doing + * + * @author davejwatson + */ + void setVersion(int8_t version); + + private: + void prepare(); + + private: + typedef P Protocol; + + bool prepared_; + bool lastDeserialized_; + shared_ptr buffer_; + shared_ptr protocol_; + int8_t version_; + bool setVersion_; +}; + +template +struct ThriftSerializerBinary + : public ThriftSerializer > +{ }; + +template +struct ThriftSerializerCompact + : public ThriftSerializer > +{ }; + +/** + * This version is deprecated. Please do not use it anymore, + * unless you have data already serialized to disk in this format. + * Doubles are not serialized in correct network order, so making RPC + * calls with this data will not work. + */ +template +struct ThriftSerializerCompactDeprecated + : public ThriftSerializer > +{ + public: + ThriftSerializerCompactDeprecated() { + this->setVersion(TCompactProtocol::VERSION_LOW); + } +}; + +template +struct ThriftSerializerJson + : public ThriftSerializer +{ }; + +template +struct ThriftSerializerSimpleJson + : public ThriftSerializer +{ }; + +}}} // namespace apache::thrift:util + +namespace apache { namespace thrift { + +template + std::string ThriftJSONString(const ThriftStruct& ts) { + using namespace apache::thrift::protocol; + using namespace apache::thrift::util; + ThriftSerializer serializer; + std::string serialized; + serializer.serialize(ts, &serialized); + return serialized; +} + +}} // apache::thrift + + +#include "thrift/lib/cpp/util/ThriftSerializer-inl.h" + +#endif diff --git a/thrift/lib/cpp/util/ThriftSerializerTest.thrift b/thrift/lib/cpp/util/ThriftSerializerTest.thrift new file mode 100644 index 00000000..0f7d11d3 --- /dev/null +++ b/thrift/lib/cpp/util/ThriftSerializerTest.thrift @@ -0,0 +1,29 @@ +struct TestValue { + 1: i64 legalClicks, + 2: i64 rawImpressions, + 3: i64 lastLegalClickTime, + 4: i64 lastLegalImpressionTime, + 5: i64 socialClicks, + 6: i64 socialImpressions, + 7: double throttle, + 8: i64 pageOtherImpressions, + 9: i64 pageCanvasImpressions, + 10: i64 pageProfileImpressions, + 11: i64 pageSearchImpressions, + 12: i64 pageEventImpressions, + 13: i64 pageGroupImpressions, + 14: i64 pagePhotoImpressions, + 15: i64 pageHomeImpressions, + 16: i64 position1Impressions, + 17: i64 position2Impressions, + 18: i64 position3Impressions, + 19: i64 feedbackLegalLikes, + 20: i64 feedbackLegalDislikes, + 21: list rollingWindowLegalClicks, + 22: list rollingWindowRawImpressions, + 23: list rollingWindowFeedbackLegalLikes, + 24: list rollingWindowFeedbackLegalDislikes, + 25: i64 pageAlbumImpressions, + 26: i64 pageAdBoardImpressions, + 27: string text, +} diff --git a/thrift/lib/cpp/util/VarintUtils.h b/thrift/lib/cpp/util/VarintUtils.h new file mode 100644 index 00000000..a12b8fc0 --- /dev/null +++ b/thrift/lib/cpp/util/VarintUtils.h @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_UTIL_VARINTUTILS_H_ +#define THRIFT_UTIL_VARINTUTILS_H_ 1 + +#include + +namespace apache { namespace thrift { + +namespace util { + +/** + * Read an i16 from the wire as a varint. The MSB of each byte is set + * if there is another byte to follow. This can read up to 3 bytes. + */ +uint32_t readVarint16(uint8_t const* ptr, int16_t* i16, + uint8_t const* boundary); + +/** + * Read an i32 from the wire as a varint. The MSB of each byte is set + * if there is another byte to follow. This can read up to 5 bytes. + */ +uint32_t readVarint32(uint8_t const* ptr, int32_t* i32, + uint8_t const* boundary); + +/** + * Read an i64 from the wire as a proper varint. The MSB of each byte is set + * if there is another byte to follow. This can read up to 10 bytes. + * Caller is responsible for advancing ptr after call. + */ +uint32_t readVarint64(uint8_t const* ptr, int64_t* i64, + uint8_t const* boundary); + +/** + * Write an i32 as a varint. Results in 1-5 bytes on the wire. + */ +uint32_t writeVarint32(uint32_t n, uint8_t* pkt); + +/** + * Write an i16 as a varint. Results in 1-3 bytes on the wire. + */ +uint32_t writeVarint16(uint16_t n, uint8_t* pkt); + +}}} // apache::thrift::util + +#include "VarintUtils.tcc" + +#endif // THRIFT_UTIL_VARINTUTILS_H_ diff --git a/thrift/lib/cpp/util/VarintUtils.tcc b/thrift/lib/cpp/util/VarintUtils.tcc new file mode 100644 index 00000000..c4d9217b --- /dev/null +++ b/thrift/lib/cpp/util/VarintUtils.tcc @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "folly/experimental/io/Cursor.h" + +namespace apache { namespace thrift { + +namespace util { + +template ::value, + bool>::type = false> +T readVarint(CursorT& c) { + T retVal = 0; + uint8_t shift = 0; + uint8_t rsize = 0; + while (true) { + uint8_t byte; + c.pull(&byte, sizeof(byte)); + rsize++; + retVal |= (uint64_t)(byte & 0x7f) << shift; + shift += 7; + if (!(byte & 0x80)) { + return retVal; + } + if (rsize > sizeof(T)) { + // Too big for return type + throw std::out_of_range("invalid varint read"); + } + } +} + +template +void writeVarint(folly::io::RWPrivateCursor& c, T value) { + while (true) { + if ((value & ~0x7F) == 0) { + c.write((int8_t)value); + break; + } else { + c.write((int8_t)((value & 0x7F) | 0x80)); + value = (unsigned)value >> 7; + } + } +} + +}}} // apache::thrift::util diff --git a/thrift/lib/cpp/util/shared_ptr_util.h b/thrift/lib/cpp/util/shared_ptr_util.h new file mode 100644 index 00000000..282deb0a --- /dev/null +++ b/thrift/lib/cpp/util/shared_ptr_util.h @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef THRIFT_UTIL_SHARED_PTR_UTIL_H_ +#define THRIFT_UTIL_SHARED_PTR_UTIL_H_ 1 + +#include +#include +#include + +/** + * Helper macros to allow function overloading even when using + * boost::shared_ptr. + * + * shared_ptr makes overloading really annoying, since shared_ptr defines + * constructor methods to allow one shared_ptr type to be constructed from any + * other shared_ptr type. (Even if it would be a compile error to actually try + * to instantiate the constructor.) These macros add an extra argument to the + * function to cause it to only be instantiated if a pointer of type T is + * convertible to a pointer of type U. + * + * THRIFT_OVERLOAD_IF should be used in function declarations. + * THRIFT_OVERLOAD_IF_DEFN should be used in the function definition, if it is + * defined separately from where it is declared. + */ +#define THRIFT_OVERLOAD_IF_DEFN(T, Y) \ + typename ::boost::enable_if::type, \ + void*>::type + +#define THRIFT_OVERLOAD_IF(T, Y) \ + THRIFT_OVERLOAD_IF_DEFN(T, Y) = NULL + +namespace apache { namespace thrift { + +/** + * A helper functor that can be used as a shared_ptr destructor, but that does + * nothing at all. + * + * This can be used to create a shared_ptr to an object that shouldn't really + * be destroyed when the last shared_ptr to it goes away. This is useful in + * some situations to call thrift APIs that require a shared_ptr argument when + * you have an object on the stack or otherwise owned by some other part of the + * code. + * + * WARNING: If at all possible, please avoid using this class to create + * shared_ptr. Attempting to use shared_ptrs with manually managed objects is + * generally a bad idea. This class should only be used in a few rare cases + * where a temporary shared_ptr is needed, and you can guarantee that all + * shared_ptrs to the object will be destroyed before the object itself is + * destroyed. + */ +template +class NoopPtrDestructor { + public: + void operator()(T* obj) {}; +}; + +}} // apache::thrift + +#endif // THRIFT_UTIL_SHARED_PTR_UTIL_H_ diff --git a/thrift/libs/libasync.a b/thrift/libs/libasync.a new file mode 100644 index 00000000..9685e47a Binary files /dev/null and b/thrift/libs/libasync.a differ diff --git a/thrift/libs/libasync_base.a b/thrift/libs/libasync_base.a new file mode 100644 index 00000000..60f21db9 Binary files /dev/null and b/thrift/libs/libasync_base.a differ diff --git a/thrift/libs/libasync_ssl.a b/thrift/libs/libasync_ssl.a new file mode 100644 index 00000000..0a9798ce Binary files /dev/null and b/thrift/libs/libasync_ssl.a differ diff --git a/thrift/libs/libconcurrency.a b/thrift/libs/libconcurrency.a new file mode 100644 index 00000000..13b72719 Binary files /dev/null and b/thrift/libs/libconcurrency.a differ diff --git a/thrift/libs/libexample.a b/thrift/libs/libexample.a new file mode 100644 index 00000000..b63d8889 Binary files /dev/null and b/thrift/libs/libexample.a differ diff --git a/thrift/libs/libheader.a b/thrift/libs/libheader.a new file mode 100644 index 00000000..1a06dfc2 Binary files /dev/null and b/thrift/libs/libheader.a differ diff --git a/thrift/libs/libhttpparser.a b/thrift/libs/libhttpparser.a new file mode 100644 index 00000000..497f40f4 Binary files /dev/null and b/thrift/libs/libhttpparser.a differ diff --git a/thrift/libs/libinternal_util.a b/thrift/libs/libinternal_util.a new file mode 100644 index 00000000..8b48f3a0 Binary files /dev/null and b/thrift/libs/libinternal_util.a differ diff --git a/thrift/libs/libprocessor.a b/thrift/libs/libprocessor.a new file mode 100644 index 00000000..10abbe56 Binary files /dev/null and b/thrift/libs/libprocessor.a differ diff --git a/thrift/libs/libprotocol.a b/thrift/libs/libprotocol.a new file mode 100644 index 00000000..e7f47ce6 Binary files /dev/null and b/thrift/libs/libprotocol.a differ diff --git a/thrift/libs/libreflection.a b/thrift/libs/libreflection.a new file mode 100644 index 00000000..8b277f0d --- /dev/null +++ b/thrift/libs/libreflection.a @@ -0,0 +1 @@ +! diff --git a/thrift/libs/libserver.a b/thrift/libs/libserver.a new file mode 100644 index 00000000..b2770bbd Binary files /dev/null and b/thrift/libs/libserver.a differ diff --git a/thrift/libs/libthrift.a b/thrift/libs/libthrift.a new file mode 100644 index 00000000..a3ba64e7 Binary files /dev/null and b/thrift/libs/libthrift.a differ diff --git a/thrift/libs/libthrift_base.a b/thrift/libs/libthrift_base.a new file mode 100644 index 00000000..0983d02e Binary files /dev/null and b/thrift/libs/libthrift_base.a differ diff --git a/thrift/libs/libthrift_exception.a b/thrift/libs/libthrift_exception.a new file mode 100644 index 00000000..da9b990c Binary files /dev/null and b/thrift/libs/libthrift_exception.a differ diff --git a/thrift/libs/libtransport.a b/thrift/libs/libtransport.a new file mode 100644 index 00000000..3e2c21e2 Binary files /dev/null and b/thrift/libs/libtransport.a differ diff --git a/thrift/libs/libtransport_ssl.a b/thrift/libs/libtransport_ssl.a new file mode 100644 index 00000000..b2167533 Binary files /dev/null and b/thrift/libs/libtransport_ssl.a differ diff --git a/thrift/libs/libutil.a b/thrift/libs/libutil.a new file mode 100644 index 00000000..3f081c7b Binary files /dev/null and b/thrift/libs/libutil.a differ diff --git a/thrift/openhandles.h b/thrift/openhandles.h new file mode 100644 index 00000000..a406eca0 --- /dev/null +++ b/thrift/openhandles.h @@ -0,0 +1,220 @@ +/** + * Thrift server for leveldb + * @author Dhruba Borthakur (dhruba@gmail.com) + * Copyright 2012 Facebook + */ + +#ifndef THRIFT_LEVELDB_SERVER_H_ +#define THRIFT_LEVELDB_SERVER_H_ + +#include +#include +#include "DB.h" +#include +#include +#include +#include +#include + +#include "leveldb/db.h" +#include "util/random.h" + +using boost::shared_ptr; +using std::unordered_map; + +using namespace ::Tleveldb; + +// List of snapshots. Each entry has a unique snapshot id. +struct snapshotEntry { + int64_t snapshotid; + const leveldb::Snapshot* lsnap; + + snapshotEntry() : snapshotid(-1), lsnap(NULL) { + } + + private: + snapshotEntry(const snapshotEntry&); + snapshotEntry& operator= (const snapshotEntry&); +}; + +// List of iterators. Each entry has a unique iterator id. +struct iteratorEntry { + int64_t iteratorid; + leveldb::Iterator* liter; + + iteratorEntry() : iteratorid(-1), liter(NULL) { + } + + private: + iteratorEntry(const iteratorEntry&); + iteratorEntry& operator= (const iteratorEntry&); +}; + + +// +// This is the information stored for each open database. Each open instance +// of the database has a list of snapshots and a list of iterators that are +// currenty open +// +struct onehandle { + Text name; + leveldb::DB* onedb; // locate the localleveldb instance + int refcount; // currently not used + std::atomic currentSnapshotId; // valid snapshotids > 0 + std::atomic currentIteratorId; // valid iterators > 0 + unordered_map snaplist; + // list of snapshots for this database + unordered_map iterlist; + // list of iterators for this database + + onehandle() : onedb(NULL), + refcount(0), currentSnapshotId(1), currentIteratorId(1) { + } + + // stores a new leveldb snapshot and returns an unique id + int64_t addSnapshot(const leveldb::Snapshot* l) { + struct snapshotEntry* news = new snapshotEntry; + news->snapshotid = currentSnapshotId++; + news->lsnap = l; + snaplist[news->snapshotid] = news; + return news->snapshotid; + } + + // lookup a snapshot from its ids + const leveldb::Snapshot* lookupSnapshot(int64_t id) { + auto p = snaplist.find(id); + if (p == snaplist.end()) { + fprintf(stderr, "get:No snaphot with id %ld\n", id); + return NULL; + } + return p->second->lsnap; + } + + // remove a snapshot from this database + const leveldb::Snapshot* removeSnapshot(int64_t id) { + const leveldb::Snapshot* l = lookupSnapshot(id); + if (l != NULL) { + int numRemoved = snaplist.erase(id); + assert(numRemoved == 1); + return l; + } + return NULL; // not found + } + + // stores a new leveldb iterator and returns an unique id + int64_t addIterator(leveldb::Iterator* l) { + struct iteratorEntry* news = new iteratorEntry; + news->iteratorid = currentIteratorId++; + news->liter = l; + iterlist[news->iteratorid] = news; + return news->iteratorid; + } + + // lookup a iterator from its ids + leveldb::Iterator* lookupIterator(int64_t id) { + auto p = iterlist.find(id); + if (p == iterlist.end()) { + fprintf(stderr, "lookupIterator:No iterator with id %ld\n", id); + return NULL; + } + return p->second->liter; + } + + // remove a iterator from this database + leveldb::Iterator* removeIterator(int64_t id) { + leveldb::Iterator* i = lookupIterator(id); + if (i != NULL) { + int numRemoved = iterlist.erase(id); + assert(numRemoved == 1); + return i; + } + return NULL; // not found + } + + private: + onehandle(const onehandle&); + onehandle& operator= (const onehandle&); +}; + +class OpenHandles { + public: + + OpenHandles() { + } + + // Inserts a new database into the list. + // If the database is already open, increase refcount. + // If the database is not already open, open and insert into list. + void add(leveldb::Options& options, Text dbname, std::string dbdir) { + struct onehandle* found = head_[dbname]; + if (found == NULL) { + found = new onehandle; + found->name = dbname; + fprintf(stderr, "openhandle.add: Opening leveldb DB %s\n", + dbname.c_str()); + leveldb::Status status = leveldb::DB::Open(options, dbdir, &found->onedb); + if (!status.ok()) { + LeveldbException e; + e.errorCode = Code::kIOError; + e.message = "Unable to open database"; + fprintf(stderr, "openhandle.add: Unable to open database %s\n", + dbname.c_str()); + throw e; + } + assert(found->onedb != NULL); + head_[dbname] = found; + } + found->refcount++; + } + + leveldb::DB* get(Text dbname, struct onehandle** f) { + auto p = head_.find(dbname); + if (p == head_.end()) { + fprintf(stderr, "get:No db with name\n"); + return NULL; + } + struct onehandle* found = p->second; + if (found->refcount <= 0) { + fprintf(stderr, "get:bad refcount\n."); + return NULL; + } + // returns the onehandle if asked to do so + if (f != NULL) { + *f = found; + } + return found->onedb; + } + + bool remove(Text dbname) { + auto p = head_.find(dbname); + if (p == head_.end()) { + fprintf(stderr, "get:No db with name\n"); + return false; + } + struct onehandle* found = p->second; + if (found->refcount == 1) { + delete found->onedb; // close database + int numRemoved = head_.erase(dbname); + assert (numRemoved == 1); + } else { + found->refcount--; // decrement refcount + } + return true; + } + + private: + unordered_map head_; // all open databases + + struct onehandle* lookup(Text dbname) { + auto p = head_.find(dbname); + if (p == head_.end()) { + fprintf(stderr, "get:No db with name\n"); + return NULL; + } + return p->second; + } +}; + +#endif // THRIFT_LEVELDB_SERVER_H_ + + diff --git a/thrift/server.cpp b/thrift/server.cpp new file mode 100644 index 00000000..5e590d8c --- /dev/null +++ b/thrift/server.cpp @@ -0,0 +1,47 @@ +/** + * Thrift server for leveldb + * @author Dhruba Borthakur (dhruba@gmail.com) + * Copyright 2012 Facebook + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "openhandles.h" +#include "server_options.h" + +#include "leveldb/db.h" +#include "leveldb/write_batch.h" + +using namespace apache::thrift; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; +using namespace apache::thrift::server; +using namespace Tleveldb; +using boost::shared_ptr; + +extern "C" void startServer(int argc, char** argv); +extern "C" void stopServer(int port); +extern ServerOptions server_options; + +void signal_handler(int sig) { + switch (sig) { + case SIGINT: + fprintf(stderr, "Received SIGINT, stopping leveldb server"); + stopServer(server_options.getPort()); + break; + } +} + +int main(int argc, char **argv) { + signal(SIGINT, signal_handler); + startServer(argc, argv); + sleep(100000000L); + return 0; +} + diff --git a/thrift/server_options.h b/thrift/server_options.h new file mode 100644 index 00000000..797c9a56 --- /dev/null +++ b/thrift/server_options.h @@ -0,0 +1,214 @@ +/** + * Options for the Thrift leveldb server. + * @author Dhruba Borthakur (dhruba@gmail.com) + * Copyright 2012 Facebook + */ + +#ifndef THRIFT_LEVELDB_SERVER_OPTIONS_ +#define THRIFT_LEVELDB_SERVER_OPTIONS_ + +#include +#include + +#include "leveldb/db.h" +#include "leveldb/cache.h" + +// +// These are configuration options for the entire server. +// +class ServerOptions { + private: + int num_threads_; // number of thrift server threads + int cache_numshardbits_; // cache shards + long cache_size_; // cache size in bytes + int port_; // port number + std::string hostname_; // host name of this machine + std::string rootdir_; // root directory of all DBs + leveldb::Cache* cache_; // the block cache + + // Number of concurrent threads to run. + const static int DEFAULT_threads = 1; + + // Number of bytes to use as a cache of uncompressed data. + // Default setting of 100 MB + const static long DEFAULT_cache_size = 100 * 1024 * 1024; + + // Number of shards for the block cache is 2 ** DEFAULT_cache_numshardbits. + // Negative means use default settings. This is applied only + // if DEFAULT_cache_size is non-negative. + const static int DEFAULT_cache_numshardbits = 6; + + // default port + const static int DEFAULT_PORT = 6666; + +public: + ServerOptions() : num_threads_(DEFAULT_threads), + cache_numshardbits_(DEFAULT_cache_numshardbits), + cache_size_(DEFAULT_cache_size), + port_(DEFAULT_PORT), + cache_(NULL) { + char* buf = new char[HOST_NAME_MAX]; + if (gethostname(buf, HOST_NAME_MAX) == 0) { + hostname_ = buf; + } else { + hostname_ = "unknownhost"; + delete buf; + } + rootdir_ = "/tmp"; // default rootdir + } + + // + // Returns succes if all command line options are parsed successfully, + // otherwise returns false. + bool parseOptions(int argc, char** argv) { + int n; + uint64_t l; + char junk; + for (int i = 1; i < argc; i++) { + if (sscanf(argv[i], "--port=%d%c", &n, &junk) == 1) { + port_ = n; + } else if (sscanf(argv[i], "--threads=%d%c", &n, &junk) == 1) { + num_threads_ = n; + } else if (sscanf(argv[i], "--cache_size=%ld%c", &l, &junk) == 1) { + cache_size_ = l; + } else if (sscanf(argv[i], "--cache_numshardbits=%d%c", &n, &junk) == 1) { + cache_numshardbits_ = n; + } else if (strncmp(argv[i], "--hostname=", 11) == 0) { + hostname_ = argv[i] + 11; + } else if (strncmp(argv[i], "--rootdir=", 10) == 0) { + rootdir_ = argv[i] + 10; + } else { + fprintf(stderr, "Invalid flag '%s'\n", argv[i]); + return false; + } + } + return true; + } + + // Create the directory format on disk. + // Returns true on success, false on failure + bool createDirectories() { + mode_t mode = 0755; + const char* dir = getRootDirectory().c_str(); + if (mkpath(dir, mode) < 0) { + fprintf(stderr, "Unable to create root directory %s\n", dir); + return false; + } + dir = getDataDirectory().c_str();; + if (mkpath(dir, mode) < 0) { + fprintf(stderr, "Unable to create data directory %s\n", dir); + return false; + } + dir = getConfigDirectory().c_str();; + if (mkpath(dir, mode) < 0) { + fprintf(stderr, "Unable to create config directory %s\n", dir); + return false; + } + return true; + } + + // create a cache instance that is shared by all DBs served by this server + void createCache() { + if (cache_numshardbits_ >= 1) { + cache_ = leveldb::NewLRUCache(cache_size_, cache_numshardbits_); + } else { + cache_ = leveldb::NewLRUCache(cache_size_); + } + } + + // Returns the base server port + int getPort() { + return port_; + } + + // Returns the assoc server port. Currently, it is one more than the base + // server port. In fiture, the assoc service would be supported on multiple + // ports, each port serving a distinct range of keys. + int getAssocPort() { + return port_ + 1; + } + + // Returns the cache + leveldb::Cache* getCache() { + return cache_; + } + + // Returns the configured number of server threads + int getNumThreads() { + return num_threads_; + } + + // Returns the root directory where the server is rooted. + // The hostname is appended to the rootdir to arrive at the directory name. + std::string getRootDirectory() { + return rootdir_ + "/" + hostname_; + } + + // Returns the directory where the server stores all users's DBs. + std::string getDataDirectory() { + return getRootDirectory() + "/userdata/"; + } + + // Returns the directory where the server stores all its configurations + std::string getConfigDirectory() { + return getRootDirectory() + "/config/"; + } + + // Returns the data directory for the specified DB + std::string getDataDirectory(const std::string& dbname) { + return getDataDirectory() + dbname; + } + + // Returns true if the DB name is valid, otherwise return false + bool isValidName(const std::string& dbname) { + // The DB name cannot have '/' in the name + if (dbname.find('/') < dbname.size()) { + return false; + } + return true; + } + + private: + static int do_mkdir(const char *path, mode_t mode) { + struct stat st; + int status = 0; + + if (stat(path, &st) != 0) { + if (mkdir(path, mode) != 0) { + status = -1; + } + } else if (!S_ISDIR(st.st_mode)) { + errno = ENOTDIR; + status = -1; + } + return(status); + } + + // mkpath - ensure all directories in path exist + static int mkpath(const char *path, mode_t mode) + { + char *pp; + char *sp; + int status; + char *newpath = strdup(path); + + status = 0; + pp = newpath; + while (status == 0 && (sp = strchr(pp, '/')) != 0) { + if (sp != pp) { + /* Neither root nor double slash in path */ + *sp = '\0'; + status = do_mkdir(newpath, mode); + *sp = '/'; + } + pp = sp + 1; + } + if (status == 0) { + status = do_mkdir(path, mode); + } + free(newpath); + return (status); + } +}; + +#endif // THRIFT_LEVELDB_SERVER_OPTIONS_ diff --git a/thrift/server_utils.cpp b/thrift/server_utils.cpp new file mode 100644 index 00000000..120737f8 --- /dev/null +++ b/thrift/server_utils.cpp @@ -0,0 +1,491 @@ +/** + * Thrift server for leveldb + * @author Dhruba Borthakur (dhruba@gmail.com) + * Copyright 2012 Facebook + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "openhandles.h" +#include "server_options.h" +#include "assoc.h" + +#include "leveldb/db.h" +#include "leveldb/write_batch.h" + +using namespace apache::thrift; +using namespace apache::thrift::util; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; +using namespace apache::thrift::server; +using namespace apache::thrift::async; +using namespace Tleveldb; +using boost::shared_ptr; + +extern "C" void startServer(int argc, char** argv); +extern "C" void stopServer(int port); + +static boost::shared_ptr baseServer; +static boost::shared_ptr assocServer; + +// The global object that stores the default configuration of the server +ServerOptions server_options; + +class DBHandler : virtual public DBIf { + public: + DBHandler(OpenHandles* oh) { + openHandles = oh; + } + + void Open(DBHandle& _return, const Text& dbname, + const DBOptions& dboptions) { + printf("Open %s\n", dbname.c_str()); + if (!server_options.isValidName(dbname)) { + LeveldbException e; + e.errorCode = Code::kInvalidArgument; + e.message = "Bad DB name"; + fprintf(stderr, "Bad DB name %s\n", dbname.c_str()); + throw e; + } + std::string dbdir = server_options.getDataDirectory(dbname); + leveldb::Options options; + + // fill up per-server options + options.block_cache = server_options.getCache(); + + // fill up per-DB options + options.create_if_missing = dboptions.create_if_missing; + options.error_if_exists = dboptions.error_if_exists; + options.write_buffer_size = dboptions.write_buffer_size; + options.max_open_files = dboptions.max_open_files; + options.block_size = dboptions.block_size; + options.block_restart_interval = dboptions.block_restart_interval; + if (dboptions.compression == kNoCompression) { + options.compression = leveldb::kNoCompression; + } else if (dboptions.compression == kSnappyCompression) { + options.compression = leveldb::kSnappyCompression; + } + if (dboptions.num_levels > 0) + options.num_levels = dboptions.num_levels; + if (dboptions.level0_file_num_compaction_trigger > 0) + options.level0_file_num_compaction_trigger = dboptions.level0_file_num_compaction_trigger; + if (dboptions.level0_slowdown_writes_trigger > 0) + options.level0_slowdown_writes_trigger = dboptions.level0_slowdown_writes_trigger; + if (dboptions.level0_stop_writes_trigger) + options.level0_stop_writes_trigger = dboptions.level0_stop_writes_trigger; + if (dboptions.target_file_size_base > 0) + options.target_file_size_base = dboptions.target_file_size_base; + if (dboptions.target_file_size_multiplier > 0) + options.target_file_size_multiplier = dboptions.target_file_size_multiplier; + if (dboptions.max_bytes_for_level_base) + options.max_bytes_for_level_base = dboptions.max_bytes_for_level_base; + if (dboptions.max_bytes_for_level_multiplier) + options.max_bytes_for_level_multiplier = dboptions.max_bytes_for_level_multiplier; + if (dboptions.max_grandparent_overlap_factor) + options.max_grandparent_overlap_factor = dboptions.max_grandparent_overlap_factor; + if (dboptions.disableDataSync) + options.disableDataSync = dboptions.disableDataSync; + openHandles->add(options, dbname, dbdir); + _return.dbname = dbname; + } + + Code Close(const DBHandle& dbhandle, const Text& dbname) { + // + // We do not close any handles for now, otherwise we have to do + // some locking that will degrade performance in the normal case. + // + return Code::kNotSupported; + } + + Code Put(const DBHandle& dbhandle, const kv& kv, + const WriteOptions& options) { + leveldb::WriteOptions woptions; + woptions.sync = options.sync; + woptions.disableWAL = options.disableWAL; + leveldb::Slice key, value; + key.data_ = kv.key.data.data(); + key.size_ = kv.key.size; + value.data_ = kv.value.data.data(); + value.size_ = kv.value.size; + leveldb::DB* db = openHandles->get(dbhandle.dbname, NULL); + if (db == NULL) { + return Code::kNotFound; + } + leveldb::Status status = db->Put(woptions, key, value); + if (status.ok()) { + return Code::kOk; + } + return Code::kIOError; + } + + Code Delete(const DBHandle& dbhandle, const Slice& kv, + const WriteOptions& options) { + leveldb::WriteOptions woptions; + woptions.sync = options.sync; + woptions.disableWAL = options.disableWAL; + leveldb::Slice key; + key.data_ = kv.data.data(); + key.size_ = kv.size; + leveldb::DB* db = openHandles->get(dbhandle.dbname, NULL); + if (db == NULL) { + return Code::kNotFound; + } + leveldb::Status status = db->Delete(woptions, key); + if (status.ok()) { + return Code::kOk; + } + return Code::kIOError; + } + + Code Write(const DBHandle& dbhandle, const std::vector & batch, + const WriteOptions& options) { + leveldb::WriteOptions woptions; + leveldb::WriteBatch lbatch; + woptions.sync = options.sync; + woptions.disableWAL = options.disableWAL; + leveldb::Slice key, value; + for (unsigned int i = 0; i < batch.size(); i++) { + kv one = batch[i]; + key.data_ = one.key.data.data(); + key.size_ = one.key.size; + value.data_ = one.value.data.data(); + value.size_ = one.value.size; + lbatch.Put(key, value); + } + leveldb::DB* db = openHandles->get(dbhandle.dbname, NULL); + if (db == NULL) { + return Code::kNotFound; + } + leveldb::Status status = db->Write(woptions, &lbatch); + if (status.ok()) { + return Code::kOk; + } + return Code::kIOError; + } + + void Get(ResultItem& _return, const DBHandle& dbhandle, const Slice& inputkey, + const ReadOptions& options) { + struct onehandle* thishandle; + _return.status = Code::kNotFound; + std::string ret; + leveldb::Slice ikey; + ikey.data_ = inputkey.data.data(); + ikey.size_ = inputkey.size; + leveldb::DB* db = openHandles->get(dbhandle.dbname, &thishandle); + if (db == NULL) { + return; + } + assert(thishandle != NULL); + const leveldb::Snapshot* s = NULL; + if (options.snapshot.snapshotid > 0) { + s = thishandle->lookupSnapshot(options.snapshot.snapshotid); + assert(s != NULL); + if (s == NULL) { + return; + } + } + leveldb::ReadOptions roptions; + roptions.verify_checksums = options.verify_checksums; + roptions.fill_cache = options.fill_cache; + roptions.snapshot = s; + + leveldb::Status status = db->Get(roptions, ikey, &ret); + if (status.ok()) { + _return.value.data = ret.data(); + _return.value.size = ret.size(); + _return.status = Code::kOk; + } + } + + void NewIterator(ResultIterator& _return, const DBHandle& dbhandle, + const ReadOptions& options, IteratorType iteratorType, + const Slice& target) { + struct onehandle* thishandle; + _return.status = Code::kNotFound; + leveldb::DB* db = openHandles->get(dbhandle.dbname, &thishandle); + if (db == NULL) { + return; + } + assert(thishandle != NULL); + + // check to see if snapshot is specified + const leveldb::Snapshot* s = NULL; + if (options.snapshot.snapshotid > 0) { + s = thishandle->lookupSnapshot(options.snapshot.snapshotid); + assert(s != NULL); + if (s == NULL) { + return; + } + } + + // create leveldb iterator + leveldb::ReadOptions roptions; + roptions.verify_checksums = options.verify_checksums; + roptions.fill_cache = options.fill_cache; + roptions.snapshot = s; + leveldb::Iterator* iter = db->NewIterator(roptions); + if (iter == NULL) { + return; + } + + // position iterator at right place + if (iteratorType == IteratorType::seekToFirst) { + iter->SeekToFirst(); + } else if (iteratorType == IteratorType::seekToLast) { + iter->SeekToLast(); + } else if (iteratorType == IteratorType::seekToKey) { + leveldb::Slice key; + key.data_ = target.data.data(); + key.size_ = target.size; + iter->Seek(key); + } else { + delete iter; + _return.status = Code::kInvalidArgument; + return; + } + + // insert iterator into openhandle list, get unique id + int64_t id = thishandle->addIterator(iter); + _return.iterator.iteratorid = id; + _return.status = kOk; + } + + // Delete existing iterator + Code DeleteIterator(const DBHandle& dbhandle, const Iterator& iterator) { + // find the db + struct onehandle* thishandle; + leveldb::DB* db = openHandles->get(dbhandle.dbname, &thishandle); + if (db == NULL) { + return kNotFound; + } + assert(thishandle != NULL); + + // find the leveldb iterator for this db + leveldb::Iterator* it = + thishandle->lookupIterator(iterator.iteratorid); + if (it == NULL) { + // this must have been cleaned up by the last call to GetNext + return kOk; + } + thishandle->removeIterator(iterator.iteratorid); + delete it; // cleanup + return kOk; + } + + // read the next value from the iterator + void GetAnother(ResultPair& _return, const DBHandle& dbhandle, + const Iterator& iterator, const bool doNext) { + + // find the db + struct onehandle* thishandle; + _return.status = Code::kNotFound; + leveldb::DB* db = openHandles->get(dbhandle.dbname, &thishandle); + if (db == NULL) { + return; + } + assert(thishandle != NULL); + + // find the leveldb iterator for this db + leveldb::Iterator* it = + thishandle->lookupIterator(iterator.iteratorid); + assert(it != NULL); + if (it == NULL) { + return; + } + + // If the iterator has reached the end close it rightaway. + // There is no need for the application to make another thrift + // call to cleanup the iterator. + if (!it->Valid()) { + thishandle->removeIterator(iterator.iteratorid); + delete it; // cleanup + _return.status = Code::kEnd; // no more elements + return; + } + + // if iterator has encountered any corruption + if (!it->status().ok()) { + thishandle->removeIterator(iterator.iteratorid); + delete it; // cleanup + _return.status = Code::kIOError; // error in data + return; + } + + // find current key-value + leveldb::Slice key = it->key(); + leveldb::Slice value = it->value(); + + // pack results back to client + _return.keyvalue.key.data.assign(key.data_, key.size_); + _return.keyvalue.key.size = key.size_; + _return.keyvalue.value.data.assign(value.data_, value.size_); + _return.keyvalue.value.size = value.size_; + _return.status = Code::kOk; // success + + // move to next or previous value + if (doNext) { + it->Next(); + } else { + it->Prev(); + } + } + + // read the next value from the iterator + void GetNext(ResultPair& _return, const DBHandle& dbhandle, + const Iterator& iterator) { + GetAnother(_return, dbhandle, iterator, 1); + } + + // read the prev value from the iterator + void GetPrev(ResultPair& _return, const DBHandle& dbhandle, + const Iterator& iterator) { + GetAnother(_return, dbhandle, iterator, 0); + } + + void GetSnapshot(ResultSnapshot& _return, const DBHandle& dbhandle) { + _return.status = kIOError; + struct onehandle* thishandle; + leveldb::DB* db = openHandles->get(dbhandle.dbname, &thishandle); + if (db == NULL) { + return; + } + // create leveldb snapshot + const leveldb::Snapshot* s = db->GetSnapshot(); + + // store snapshot in dbhandle, get unique id. + int64_t id = thishandle->addSnapshot(s); + _return.snapshot.snapshotid = id; + _return.status = kOk; + } + + Code ReleaseSnapshot(const DBHandle& dbhandle, const Snapshot& snapshot) { + struct onehandle* thishandle; + leveldb::DB* db = openHandles->get(dbhandle.dbname, &thishandle); + if (db == NULL) { + return kNotFound; + } + const leveldb::Snapshot* s = thishandle->removeSnapshot(snapshot.snapshotid); + if (s == NULL) { + return Code::kNotFound; + } + db->ReleaseSnapshot(s); // release leveldb snapshot + return Code::kOk; + } + + Code CompactRange(const DBHandle& dbhandle, const Slice& begin, + const Slice& end) { + leveldb::DB* db = openHandles->get(dbhandle.dbname, NULL); + if (db == NULL) { + return Code::kNotFound; + } + leveldb::Slice k1, *start = &k1; + k1.data_ = begin.data.data(); + k1.size_ = begin.size; + leveldb::Slice k2, *stop = &k2; + k2.data_ = begin.data.data(); + k2.size_ = begin.size; + + // check special ranges. + if (start->size_ == 0) { + start = NULL; + } + if (stop->size_ == 0) { + stop = NULL; + } + db->CompactRange(start, stop); + return Code::kOk; + } + + private: + OpenHandles* openHandles; +}; + +// +// starts a service +static void* startOneService(void *arg) { + TSimpleServer* t = (TSimpleServer *)arg; + t->serve(); + return NULL; +} + + +// Starts a very simple thrift server +void startServer(int argc, char** argv) { + + // process command line options + if (!server_options.parseOptions(argc, argv)) { + exit(1); + } + + // create directories for server + if (!server_options.createDirectories()) { + exit(1); + } + // create the server's block cache + server_options.createCache(); + + // data structure to record ope databases + OpenHandles* openHandles = new OpenHandles(); + + shared_ptr transportFactory(new TBufferedTransportFactory()); + shared_ptr protocolFactory(new TBinaryProtocolFactory()); + + // create the service to process the normal get/put to leveldb. + int port = server_options.getPort(); + fprintf(stderr, "Server starting on port %d\n", port); + shared_ptr serverTransport(new TServerSocket(port)); + shared_ptr handler(new DBHandler(openHandles)); + shared_ptr processor(new DBProcessor(handler)); + TSimpleServer* baseServer = new TSimpleServer(processor, serverTransport, + transportFactory, protocolFactory); + pthread_t dbServerThread; + int rc = pthread_create(&dbServerThread, NULL, startOneService, + (void *)baseServer); + if (rc != 0) { + fprintf(stderr, "Unable to start DB server on port %d\n.", port); + exit(1); + } + + // create the service to process the assoc get/put to leveldb. + int assocport = server_options.getAssocPort(); + fprintf(stderr, "Assoc Service starting on port %d\n", assocport); + shared_ptr assocTransport(new TServerSocket(assocport)); + shared_ptr assocHandler(new AssocServiceHandler(openHandles)); + shared_ptr assocProcessor(new AssocServiceProcessor(assocHandler)); + TSimpleServer* assocServer = new TSimpleServer(assocProcessor, + assocTransport, transportFactory, protocolFactory); + pthread_t assocServerThread; + rc = pthread_create(&assocServerThread, NULL, startOneService, + (void *)assocServer); + if (rc != 0) { + fprintf(stderr, "Unable to start assoc server on port %d\n.", port); + exit(1); + } +} + +/** +void startEventServer(int port) { + shared_ptr handler(new DBHandler()); + shared_ptr processor(new DBProcessor(handler)); + shared_ptr asyncProcessor(new TSyncToAsyncProcessor(processor)); + TEventServerCreator creator(asyncProcessor, (uint16_t)port, 2); + tServer = creator.createServer(); + tServer.serve(); +} +**/ + +// Stops the thrift server +void stopServer(int port) { + baseServer->stop(); + assocServer->stop(); +} diff --git a/thrift/test/simpletest.cpp b/thrift/test/simpletest.cpp new file mode 100644 index 00000000..daf74edb --- /dev/null +++ b/thrift/test/simpletest.cpp @@ -0,0 +1,356 @@ +/** + * Tests for Thrift server for leveldb + * @author Dhruba Borthakur (dhruba@gmail.com) + * Copyright 2012 Facebook + */ +#include +#include +#include +#include +#include +#include +#include +#include "server_options.h" + +using namespace apache::thrift; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; +using boost::shared_ptr; +using namespace Tleveldb; + +extern "C" void startServer(int argc, char**argv); +extern "C" void stopServer(int port); +extern ServerOptions server_options; + +static DBHandle dbhandle; +static DBClient* dbclient; +static AssocServiceClient* aclient; +static const Text dbname = "test-dhruba"; +static int ARGC; +static char** ARGV; + +static void cleanupDir(std::string dir) { + // remove old data, if any + char* cleanup = new char[100]; + snprintf(cleanup, 100, "rm -rf %s", dir.c_str()); + system(cleanup); +} + +static void createDatabase() { + DBOptions options; + options.create_if_missing = true; // create + options.error_if_exists = false; // overwrite + options.write_buffer_size = (4<<20); // 4 MB + options.max_open_files = 1000; + options.block_size = 4096; + options.block_restart_interval = 16; + options.compression = kSnappyCompression; + + cleanupDir(server_options.getDataDirectory(dbname)); + + // create the database + dbclient->Open(dbhandle, dbname, options); +} + +static void initialize(int port) { + boost::shared_ptr socket1(new TSocket("localhost", port)); + boost::shared_ptr transport1(new TBufferedTransport(socket1)); + boost::shared_ptr protocol1(new TBinaryProtocol(transport1)); + + // open database + dbclient = new DBClient(protocol1); + transport1->open(); + + boost::shared_ptr socket2(new TSocket("localhost", port+1)); + boost::shared_ptr transport2(new TBufferedTransport(socket2)); + boost::shared_ptr protocol2(new TBinaryProtocol(transport2)); + aclient = new AssocServiceClient(protocol2); + transport2->open(); + + createDatabase(); + printf("Database created.\n"); +} + +// +// Run base leveldb thrift server get/put/iter/scan tests +// +static void testClient() { + WriteOptions writeOptions; + printf("Running base leveldb operations .................\n"); + + // insert record into leveldb + Slice key; + key.data = "Key1"; + key.size = 4; + Slice value; + value.data = "value1"; + value.size = 6; + kv keyvalue; + keyvalue.key = key; + keyvalue.value = value; + int ret = dbclient->Put(dbhandle, keyvalue, writeOptions); + ASSERT_TRUE(ret == Code::kOk); + printf("Put Key1 suceeded.\n"); + + //read it back + ReadOptions readOptions; + ResultItem rValue; + dbclient->Get(rValue, dbhandle, key, readOptions); + ASSERT_TRUE(rValue.status == Code::kOk); + ASSERT_TRUE(value.data.compare(rValue.value.data) == 0); + ASSERT_TRUE(value.size == rValue.value.size); + printf("Get suceeded.\n"); + + // get a snapshot + ResultSnapshot rsnap; + dbclient->GetSnapshot(rsnap, dbhandle); + ASSERT_TRUE(rsnap.status == Code::kOk); + ASSERT_TRUE(rsnap.snapshot.snapshotid > 0); + printf("Snapshot suceeded.\n"); + + // insert a new record into leveldb + Slice key2; + key2.data = "Key2"; + key2.size = 4; + Slice value2; + value2.data = "value2"; + value2.size = 6; + keyvalue.key = key2; + keyvalue.value = value2; + ret = dbclient->Put(dbhandle, keyvalue, writeOptions); + ASSERT_TRUE(ret == Code::kOk); + printf("Put Key2 suceeded.\n"); + + // verify that a get done with a previous snapshot does not find Key2 + readOptions.snapshot = rsnap.snapshot; + dbclient->Get(rValue, dbhandle, key2, readOptions); + ASSERT_TRUE(rValue.status == Code::kNotFound); + printf("Get with snapshot succeeded.\n"); + + // release snapshot + ret = dbclient->ReleaseSnapshot(dbhandle, rsnap.snapshot); + ASSERT_TRUE(ret == Code::kOk); + printf("Snapshot released.\n"); + + // if we try to re-release the same snapshot, it should fail + ret = dbclient->ReleaseSnapshot(dbhandle, rsnap.snapshot); + ASSERT_TRUE(ret == Code::kNotFound); + + // compact whole database + Slice range; + range.size = 0; + ret = dbclient->CompactRange(dbhandle, range, range); + ASSERT_TRUE(ret == Code::kOk); + printf("Compaction trigger suceeded.\n"); + + // create a new iterator to scan all keys from the start + Slice target; + ResultIterator ri; + readOptions.snapshot.snapshotid = 0; + dbclient->NewIterator(ri, dbhandle, readOptions, + IteratorType::seekToFirst, target); + ASSERT_TRUE(ri.status == Code::kOk); + int foundPairs = 0; + while (true) { + ResultPair pair; + dbclient->GetNext(pair, dbhandle, ri.iterator); + if (pair.status == Code::kOk) { + foundPairs++; + } else { + break; + } + } + ASSERT_TRUE(foundPairs == 2); + ret = dbclient->DeleteIterator(dbhandle, ri.iterator); + ASSERT_TRUE(ret == Code::kOk); + printf("Iterator scan-all forward passes.\n"); + + // create a new iterator, position at end and scan backwards + readOptions.snapshot.snapshotid = 0; + dbclient->NewIterator(ri, dbhandle, readOptions, + IteratorType::seekToLast, target); + ASSERT_TRUE(ri.status == Code::kOk); + foundPairs = 0; + while (true) { + ResultPair pair; + dbclient->GetPrev(pair, dbhandle, ri.iterator); + if (pair.status == Code::kOk) { + foundPairs++; + } else { + break; + } + } + ASSERT_TRUE(foundPairs == 2); + ret = dbclient->DeleteIterator(dbhandle, ri.iterator); + ASSERT_TRUE(ret == Code::kOk); + printf("Iterator scan-all backward passes.\n"); + + // create a new iterator, position at middle + readOptions.snapshot.snapshotid = 0; + target = key; + dbclient->NewIterator(ri, dbhandle, readOptions, + IteratorType::seekToKey, target); + ASSERT_TRUE(ri.status == Code::kOk); + foundPairs = 0; + while (true) { + ResultPair pair; + dbclient->GetPrev(pair, dbhandle, ri.iterator); + if (pair.status == Code::kOk) { + foundPairs++; + } else { + break; + } + } + ASSERT_TRUE(foundPairs == 1); + ret = dbclient->DeleteIterator(dbhandle, ri.iterator); + ASSERT_TRUE(ret == Code::kOk); + printf("Iterator scan-selective backward passes.\n"); +} + +// clean up all data that we inserted as part of this test +void clearDatabase() { + WriteOptions writeOptions; + ReadOptions readOptions; + readOptions.snapshot.snapshotid = 0; + printf("Clearing entire database.\n"); + + ResultIterator ri; + Slice dummy; + dbclient->NewIterator(ri, dbhandle, readOptions, + IteratorType::seekToFirst, dummy); + ASSERT_TRUE(ri.status == Code::kOk); + while (true) { + ResultPair pair; + dbclient->GetNext(pair, dbhandle, ri.iterator); + if (pair.status == Code::kOk) { + Slice key = pair.keyvalue.key; + Code code = dbclient->Delete(dbhandle, key, writeOptions); + ASSERT_EQ(code, Code::kOk); + } else { + break; + } + } + // no need to invoke DeleteIterator because we scanned + // till the end using the iterator and ist is auto-deleted + // by the server. +} + +// +// Run assoc tests +// +static void testAssocs() { + WriteOptions writeOptions; + printf("Running assoc leveldb operations ................\n"); + + // insert record into leveldb + int64_t assocType = 100; + int64_t id1 = 1; + int64_t id2 = 2; + int64_t id1Type = 101; + int64_t id2Type = 102; + int64_t ts =3333; + AssocVisibility vis = AssocVisibility::VISIBLE; + bool update_count = true; + int64_t dataVersion = 5; + const Text data = "data......"; + const Text wormhole_comments = "wormhole..."; + int64_t count = aclient->taoAssocPut(dbname, assocType, + id1, id2, id1Type, id2Type, + ts, vis, update_count, + dataVersion, data, wormhole_comments); + ASSERT_GE(count, 0); + printf("AssocPut first record suceeded.\n"); + + // verify assoc counts. + int64_t cnt = aclient->taoAssocCount(dbname, assocType, id1); + ASSERT_EQ(cnt, 1); + printf("AssocCount suceeded.\n"); + + // verify that we can read back what we inserted earlier + std::vector id2list(1); + id2list[0] = id2; + std::vector readback(1); + aclient->taoAssocGet(readback, dbname, + assocType, id1, id2list); + printf("AssocGet suceeded.\n"); + ASSERT_EQ((unsigned int)1, readback.size()); + ASSERT_EQ(id1Type, readback[0].id1Type); + ASSERT_EQ(id2Type, readback[0].id2Type); + ASSERT_EQ(ts, readback[0].time); + ASSERT_EQ(dataVersion, readback[0].dataVersion); + ASSERT_EQ(readback[0].data.compare(data), 0); + + // add one more assoc + const Text data1 = "data1......"; + count = aclient->taoAssocPut(dbname, assocType, + id1, id2+2, id1Type+1, id2Type+1, + ts+1, vis, update_count, + dataVersion+1, data1, wormhole_comments); + ASSERT_EQ(count, 2); + printf("AssocPut second record suceeded.\n"); + + // verify assoc count is 2 + cnt = aclient->taoAssocCount(dbname, assocType, id1); + ASSERT_EQ(cnt, 2); + + // do a range get for id1+type and verify that there + // are two assocs. + readback.clear(); + int64_t offset = 0; + int64_t limit = 1000; + aclient->taoAssocRangeGet(readback, dbname, assocType, + id1, LONG_MAX, 0, + offset, limit); + ASSERT_EQ((unsigned int)2, readback.size()); + + // Delete the most recent assoc + int c = aclient->taoAssocDelete(dbname, assocType, + id1, id2+2, AssocVisibility::HIDDEN, true, ""); + ASSERT_EQ(c, 1); + + // verify assoc falls back to 1. + cnt = aclient->taoAssocCount(dbname, assocType, id1); + ASSERT_EQ(cnt, 1); + printf("AssocCount suceeded.\n"); +} + +// +// close all resources +// +static void close() { + // close database + dbclient->Close(dbhandle, dbname); + // transport->close(); +} + + +int main(int argc, char **argv) { + + ARGC = argc; + ARGV = argv; + + // create a server + startServer(argc, argv); + printf("Server thread created.\n"); + + // give some time to the server to initialize itself + while (server_options.getPort() == 0) { + sleep(1); + } + + // test client + initialize(server_options.getPort()); + + // run all tests + testClient(); + clearDatabase(); + + testAssocs(); + clearDatabase(); + + // done all tests + close(); + + return 0; +} + diff --git a/tools/db_repl_stress.cc b/tools/db_repl_stress.cc new file mode 100644 index 00000000..012a3df0 --- /dev/null +++ b/tools/db_repl_stress.cc @@ -0,0 +1,143 @@ + +#include + +#include "db/write_batch_internal.h" +#include "leveldb/db.h" +#include "leveldb/types.h" +#include "port/atomic_pointer.h" +#include "util/testutil.h" + + +// Run a thread to perform Put's. +// Another thread uses GetUpdatesSince API to keep getting the updates. +// options : +// --num_inserts = the num of inserts the first thread should perform. +// --wal_ttl = the wal ttl for the run. + +using namespace leveldb; + +struct DataPumpThread { + size_t no_records; + DB* db; // Assumption DB is Open'ed already. + volatile bool is_running; +}; + +static std::string RandomString(Random* rnd, int len) { + std::string r; + test::RandomString(rnd, len, &r); + return r; +} + +static void DataPumpThreadBody(void* arg) { + DataPumpThread* t = reinterpret_cast(arg); + DB* db = t->db; + Random rnd(301); + size_t i = 0; + t->is_running = true; + while( i < t->no_records ) { + db->Put(WriteOptions(), + Slice(RandomString(&rnd, 50)), + Slice(RandomString(&rnd, 500))); + ++i; + } + t->is_running = false; +} + +struct ReplicationThread { + port::AtomicPointer stop; + DB* db; + volatile SequenceNumber latest; + volatile size_t no_read; + volatile bool has_more; +}; + +static void ReplicationThreadBody(void* arg) { + ReplicationThread* t = reinterpret_cast(arg); + DB* db = t->db; + unique_ptr iter; + SequenceNumber currentSeqNum = 0; + while (t->stop.Acquire_Load() != nullptr) { + if (!iter) { + db->GetUpdatesSince(currentSeqNum, &iter); + fprintf(stdout, "Refreshing iterator\n"); + iter->Next(); + while(iter->Valid()) { + BatchResult res = iter->GetBatch(); + if (res.sequence != currentSeqNum +1 + && res.sequence != currentSeqNum) { + fprintf(stderr, + "Missed a seq no. b/w %ld and %ld\n", + currentSeqNum, + res.sequence); + exit(1); + } + currentSeqNum = res.sequence; + t->latest = res.sequence; + iter->Next(); + t->no_read++; + } + } + iter.reset(); + } +} + + +int main(int argc, const char** argv) { + + long FLAGS_num_inserts = 1000; + long FLAGS_WAL_ttl_seconds = 1000; + char junk; + long l; + + for (int i = 1; i < argc; ++i) { + if (sscanf(argv[i], "--num_inserts=%ld%c", &l, &junk) == 1) { + FLAGS_num_inserts = l; + } else if (sscanf(argv[i], "--wal_ttl=%ld%c", &l, &junk) == 1) { + FLAGS_WAL_ttl_seconds = l; + } else { + fprintf(stderr, "Invalid Flag '%s'\n", argv[i]); + exit(1); + } + } + + Env* env = Env::Default(); + std::string default_db_path; + env->GetTestDirectory(&default_db_path); + default_db_path += "db_repl_stress"; + Options options; + options.create_if_missing = true; + options.WAL_ttl_seconds = FLAGS_WAL_ttl_seconds; + DB* db; + + Status s = DB::Open(options, default_db_path, &db); + + if (!s.ok()) { + fprintf(stderr, "Could not open DB due to %s\n", s.ToString().c_str()); + } + + DataPumpThread dataPump; + dataPump.no_records = FLAGS_num_inserts; + dataPump.db = db; + dataPump.is_running = true; + env->StartThread(DataPumpThreadBody, &dataPump); + + ReplicationThread replThread; + replThread.db = db; + replThread.no_read = 0; + replThread.has_more = true; + replThread.stop.Release_Store(env); // store something to make it non-null. + + env->StartThread(ReplicationThreadBody, &replThread); + while(dataPump.is_running) { + continue; + } + replThread.stop.Release_Store(nullptr); + if ( replThread.no_read < dataPump.no_records ) { + // no. read should be => than inserted. + fprintf(stderr, "No. of Record's written and read not same\nRead : %ld" + " Written : %ld", replThread.no_read, dataPump.no_records); + exit(1); + } + exit(0); + fprintf(stdout, "ALL IS FINE"); +} diff --git a/tools/db_stress.cc b/tools/db_stress.cc new file mode 100644 index 00000000..2725d4ca --- /dev/null +++ b/tools/db_stress.cc @@ -0,0 +1,1109 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +//The test uses an array to compare against values written to the database. +//Keys written to the array are in 1:1 correspondence to the actual values in +//the database according to the formula in the functino GenerateValue + +//Space is reserved in the array from 0 to FLAGS_max_key and values are randomly +//written/deleted/read from those positions. During verification we compare all +//the positions in the array. Therefore to shorten/elongate the amount of time +//that this test runs for, you should change the settings: +//FLAGS_max_key, FLAGS_ops_per_thread, (sometimes also FLAGS_threads) + +#include +#include +#include +#include "db/db_impl.h" +#include "db/version_set.h" +#include "db/db_statistics.h" +#include "leveldb/cache.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/write_batch.h" +#include "leveldb/statistics.h" +#include "port/port.h" +#include "util/crc32c.h" +#include "util/histogram.h" +#include "util/mutexlock.h" +#include "util/random.h" +#include "util/testutil.h" +#include "hdfs/env_hdfs.h" + +static const long KB = 1024; + +// Seed for PRNG +static uint32_t FLAGS_seed = 2341234; + +// Max number of key/values to place in database +static long FLAGS_max_key = 2 * KB * KB * KB; + +// If set, the test uses MultiGet, MultiPut and MultiDelete that +// do a different kind of validation during the test itself, +// rather than at the end. This is meant to solve the following +// problems at the expense of doing less degree of validation. +// (a) No need to acquire mutexes during writes (less cache flushes +// in multi-core leading to speed up) +// (b) No long validation at the end (more speed up) +// (c) Also test snapshot and atomicity of batch writes +static bool FLAGS_test_batches_snapshots = false; + +// Number of concurrent threads to run. +static int FLAGS_threads = 32; + +// Size of each value will be this number times rand_int(1,3) bytes +static int FLAGS_value_size_mult = 8; + +static bool FLAGS_verify_before_write = false; + +// Print histogram of operation timings +static bool FLAGS_histogram = false; + +static bool FLAGS_verbose = false; + +// Number of bytes to buffer in memtable before compacting +// (initialized to default value by "main") +static int FLAGS_write_buffer_size = 0; + +// The number of in-memory memtables. +// Each memtable is of size FLAGS_write_buffer_size. +// This is initialized to default value of 2 in "main" function. +static int FLAGS_max_write_buffer_number = 0; + +// The maximum number of concurrent background compactions +// that can occur in parallel. +// This is initialized to default value of 1 in "main" function. +static int FLAGS_max_background_compactions = 0; + +// Number of bytes to use as a cache of uncompressed data. +static long FLAGS_cache_size = 2 * KB * KB * KB; + +// Number of bytes in a block. +static int FLAGS_block_size = 4 * KB; + +// Number of times database reopens +static int FLAGS_reopen = 10; + +// Maximum number of files to keep open at the same time (use default if == 0) +static int FLAGS_open_files = 0; + +// Bloom filter bits per key. +// Negative means use default settings. +static int FLAGS_bloom_bits = 10; + +// Use the db with the following name. +static const char* FLAGS_db = nullptr; + +// Verify checksum for every block read from storage +static bool FLAGS_verify_checksum = false; + +// Database statistics +static class leveldb::DBStatistics* dbstats; + +// Sync all writes to disk +static bool FLAGS_sync = false; + +// If true, do not wait until data is synced to disk. +static bool FLAGS_disable_data_sync = false; + +// If true, issue fsync instead of fdatasync +static bool FLAGS_use_fsync = false; + +// If true, do not write WAL for write. +static bool FLAGS_disable_wal = false; + +// Target level-0 file size for compaction +static int FLAGS_target_file_size_base = 64 * KB; + +// A multiplier to compute targe level-N file size +static int FLAGS_target_file_size_multiplier = 1; + +// Max bytes for level-0 +static uint64_t FLAGS_max_bytes_for_level_base = 256 * KB; + +// A multiplier to compute max bytes for level-N +static int FLAGS_max_bytes_for_level_multiplier = 2; + +// Number of files in level-0 that will trigger put stop. +static int FLAGS_level0_stop_writes_trigger = 12; + +// Number of files in level-0 that will slow down writes. +static int FLAGS_level0_slowdown_writes_trigger = 8; + +// Ratio of reads to total workload (expressed as a percentage) +static unsigned int FLAGS_readpercent = 10; + +// Ratio of deletes to total workload (expressed as a percentage) +static unsigned int FLAGS_delpercent = 30; + +// Option to disable compation triggered by read. +static int FLAGS_disable_seek_compaction = false; + +// Option to delete obsolete files periodically +// Default: 0 which means that obsolete files are +// deleted after every compaction run. + static uint64_t FLAGS_delete_obsolete_files_period_micros = 0; + +// Algorithm to use to compress the database +static enum leveldb::CompressionType FLAGS_compression_type = + leveldb::kSnappyCompression; + +// posix or hdfs environment +static leveldb::Env* FLAGS_env = leveldb::Env::Default(); + +// Number of operations per thread. +static uint32_t FLAGS_ops_per_thread = 600000; + +// Log2 of number of keys per lock +static uint32_t FLAGS_log2_keys_per_lock = 2; // implies 2^2 keys per lock + +// Percentage of times we want to purge redundant keys in memory before flushing +static uint32_t FLAGS_purge_redundant_percent = 50; + +extern bool useOsBuffer; +extern bool useFsReadAhead; +extern bool useMmapRead; + +namespace leveldb { + +class StressTest; +namespace { + +class Stats { + private: + double start_; + double finish_; + double seconds_; + long done_; + long writes_; + long deletes_; + long founds_; + long errors_; + int next_report_; + size_t bytes_; + double last_op_finish_; + HistogramImpl hist_; + + public: + Stats() { } + + void Start() { + next_report_ = 100; + hist_.Clear(); + done_ = 0; + writes_ = 0; + deletes_ = 0; + founds_ = 0; + errors_ = 0; + bytes_ = 0; + seconds_ = 0; + start_ = FLAGS_env->NowMicros(); + last_op_finish_ = start_; + finish_ = start_; + } + + void Merge(const Stats& other) { + hist_.Merge(other.hist_); + done_ += other.done_; + writes_ += other.writes_; + deletes_ += other.deletes_; + bytes_ += other.bytes_; + seconds_ += other.seconds_; + if (other.start_ < start_) start_ = other.start_; + if (other.finish_ > finish_) finish_ = other.finish_; + } + + void Stop() { + finish_ = FLAGS_env->NowMicros(); + seconds_ = (finish_ - start_) * 1e-6; + } + + void FinishedSingleOp() { + if (FLAGS_histogram) { + double now = FLAGS_env->NowMicros(); + double micros = now - last_op_finish_; + hist_.Add(micros); + if (micros > 20000) { + fprintf(stderr, "long op: %.1f micros%30s\r", micros, ""); + fflush(stderr); + } + last_op_finish_ = now; + } + + done_++; + if (done_ >= next_report_) { + if (next_report_ < 1000) next_report_ += 100; + else if (next_report_ < 5000) next_report_ += 500; + else if (next_report_ < 10000) next_report_ += 1000; + else if (next_report_ < 50000) next_report_ += 5000; + else if (next_report_ < 100000) next_report_ += 10000; + else if (next_report_ < 500000) next_report_ += 50000; + else next_report_ += 100000; + fprintf(stderr, "... finished %ld ops%30s\r", done_, ""); + fflush(stderr); + } + } + + void AddBytesForWrites(int nwrites, size_t nbytes) { + writes_ += nwrites; + bytes_ += nbytes; + } + + void AddDeletes(int n) { + deletes_ += n; + } + + void AddFounds(int n) { + founds_ += n; + } + + void AddErrors(int n) { + errors_ += n; + } + + void Report(const char* name) { + std::string extra; + if (bytes_ < 1 || done_ < 1) { + fprintf(stderr, "No writes or ops?\n"); + return; + } + + double elapsed = (finish_ - start_) * 1e-6; + double bytes_mb = bytes_ / 1048576.0; + double rate = bytes_mb / elapsed; + double throughput = (double)done_/elapsed; + + fprintf(stdout, "%-12s: ", name); + fprintf(stdout, "%.3f micros/op %ld ops/sec\n", + seconds_ * 1e6 / done_, (long)throughput); + fprintf(stdout, "%-12s: Wrote %.2f MB (%.2f MB/sec) (%ld%% of %ld ops)\n", + "", bytes_mb, rate, (100*writes_)/done_, done_); + fprintf(stdout, "%-12s: Deleted %ld times\n", "", deletes_); + fprintf(stdout, "%-12s: Found lookups %ld times\n", "", founds_); + fprintf(stdout, "%-12s: Got errors %ld times\n", "", errors_); + + if (FLAGS_histogram) { + fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str()); + } + fflush(stdout); + } +}; + +// State shared by all concurrent executions of the same benchmark. +class SharedState { + public: + static const uint32_t SENTINEL = 0xffffffff; + + explicit SharedState(StressTest* stress_test) : + cv_(&mu_), + seed_(FLAGS_seed), + max_key_(FLAGS_max_key), + log2_keys_per_lock_(FLAGS_log2_keys_per_lock), + num_threads_(FLAGS_threads), + num_initialized_(0), + num_populated_(0), + vote_reopen_(0), + num_done_(0), + start_(false), + start_verify_(false), + stress_test_(stress_test) { + if (FLAGS_test_batches_snapshots) { + key_locks_ = nullptr; + values_ = nullptr; + fprintf(stdout, "No lock creation because test_batches_snapshots set\n"); + return; + } + values_ = new uint32_t[max_key_]; + for (long i = 0; i < max_key_; i++) { + values_[i] = SENTINEL; + } + + long num_locks = (max_key_ >> log2_keys_per_lock_); + if (max_key_ & ((1 << log2_keys_per_lock_) - 1)) { + num_locks ++; + } + fprintf(stdout, "Creating %ld locks\n", num_locks); + key_locks_ = new port::Mutex[num_locks]; + } + + ~SharedState() { + delete[] values_; + delete[] key_locks_; + } + + port::Mutex* GetMutex() { + return &mu_; + } + + port::CondVar* GetCondVar() { + return &cv_; + } + + StressTest* GetStressTest() const { + return stress_test_; + } + + long GetMaxKey() const { + return max_key_; + } + + uint32_t GetNumThreads() const { + return num_threads_; + } + + void IncInitialized() { + num_initialized_++; + } + + void IncOperated() { + num_populated_++; + } + + void IncDone() { + num_done_++; + } + + void IncVotedReopen() { + vote_reopen_ = (vote_reopen_ + 1) % num_threads_; + } + + bool AllInitialized() const { + return num_initialized_ >= num_threads_; + } + + bool AllOperated() const { + return num_populated_ >= num_threads_; + } + + bool AllDone() const { + return num_done_ >= num_threads_; + } + + bool AllVotedReopen() { + return (vote_reopen_ == 0); + } + + void SetStart() { + start_ = true; + } + + void SetStartVerify() { + start_verify_ = true; + } + + bool Started() const { + return start_; + } + + bool VerifyStarted() const { + return start_verify_; + } + + port::Mutex* GetMutexForKey(long key) { + return &key_locks_[key >> log2_keys_per_lock_]; + } + + void Put(long key, uint32_t value_base) { + values_[key] = value_base; + } + + uint32_t Get(long key) const { + return values_[key]; + } + + void Delete(long key) const { + values_[key] = SENTINEL; + } + + uint32_t GetSeed() const { + return seed_; + } + + private: + port::Mutex mu_; + port::CondVar cv_; + const uint32_t seed_; + const long max_key_; + const uint32_t log2_keys_per_lock_; + const int num_threads_; + long num_initialized_; + long num_populated_; + long vote_reopen_; + long num_done_; + bool start_; + bool start_verify_; + StressTest* stress_test_; + + uint32_t *values_; + port::Mutex *key_locks_; + +}; + +// Per-thread state for concurrent executions of the same benchmark. +struct ThreadState { + uint32_t tid; // 0..n-1 + Random rand; // Has different seeds for different threads + SharedState* shared; + Stats stats; + + ThreadState(uint32_t index, SharedState *shared) + : tid(index), + rand(1000 + index + shared->GetSeed()), + shared(shared) { + } +}; + +} // namespace + +class StressTest { + public: + StressTest() + : cache_(NewLRUCache(FLAGS_cache_size)), + filter_policy_(FLAGS_bloom_bits >= 0 + ? NewBloomFilterPolicy(FLAGS_bloom_bits) + : nullptr), + db_(nullptr), + num_times_reopened_(0) { + std::vector files; + FLAGS_env->GetChildren(FLAGS_db, &files); + for (unsigned int i = 0; i < files.size(); i++) { + if (Slice(files[i]).starts_with("heap-")) { + FLAGS_env->DeleteFile(std::string(FLAGS_db) + "/" + files[i]); + } + } + DestroyDB(FLAGS_db, Options()); + } + + ~StressTest() { + delete db_; + delete filter_policy_; + } + + void Run() { + PrintEnv(); + Open(); + SharedState shared(this); + uint32_t n = shared.GetNumThreads(); + + std::vector threads(n); + for (uint32_t i = 0; i < n; i++) { + threads[i] = new ThreadState(i, &shared); + FLAGS_env->StartThread(ThreadBody, threads[i]); + } + // Each thread goes through the following states: + // initializing -> wait for others to init -> read/populate/depopulate + // wait for others to operate -> verify -> done + + { + MutexLock l(shared.GetMutex()); + while (!shared.AllInitialized()) { + shared.GetCondVar()->Wait(); + } + + double now = FLAGS_env->NowMicros(); + fprintf(stdout, "%s Starting database operations\n", + FLAGS_env->TimeToString((uint64_t) now/1000000).c_str()); + + shared.SetStart(); + shared.GetCondVar()->SignalAll(); + while (!shared.AllOperated()) { + shared.GetCondVar()->Wait(); + } + + now = FLAGS_env->NowMicros(); + fprintf(stdout, "%s Starting verification\n", + FLAGS_env->TimeToString((uint64_t) now/1000000).c_str()); + + shared.SetStartVerify(); + shared.GetCondVar()->SignalAll(); + while (!shared.AllDone()) { + shared.GetCondVar()->Wait(); + } + } + + for (unsigned int i = 1; i < n; i++) { + threads[0]->stats.Merge(threads[i]->stats); + } + threads[0]->stats.Report("Stress Test"); + + for (unsigned int i = 0; i < n; i++) { + delete threads[i]; + threads[i] = nullptr; + } + double now = FLAGS_env->NowMicros(); + fprintf(stdout, "%s Verification successful\n", + FLAGS_env->TimeToString((uint64_t) now/1000000).c_str()); + + PrintStatistics(); + } + + private: + + static void ThreadBody(void* v) { + ThreadState* thread = reinterpret_cast(v); + SharedState* shared = thread->shared; + + { + MutexLock l(shared->GetMutex()); + shared->IncInitialized(); + if (shared->AllInitialized()) { + shared->GetCondVar()->SignalAll(); + } + while (!shared->Started()) { + shared->GetCondVar()->Wait(); + } + } + thread->shared->GetStressTest()->OperateDb(thread); + + { + MutexLock l(shared->GetMutex()); + shared->IncOperated(); + if (shared->AllOperated()) { + shared->GetCondVar()->SignalAll(); + } + while (!shared->VerifyStarted()) { + shared->GetCondVar()->Wait(); + } + } + + if (!FLAGS_test_batches_snapshots) { + thread->shared->GetStressTest()->VerifyDb(*(thread->shared), + thread->tid); + } + + { + MutexLock l(shared->GetMutex()); + shared->IncDone(); + if (shared->AllDone()) { + shared->GetCondVar()->SignalAll(); + } + } + + } + + // Given a key K and value V, this puts ("0"+K, "0"+V), ("1"+K, "1"+V), ... + // ("9"+K, "9"+V) in DB atomically i.e in a single batch. + // Also refer MultiGet. + Status MultiPut(ThreadState* thread, + const WriteOptions& writeoptions, + const Slice& key, const Slice& value, size_t sz) { + std::string keys[10] = {"9", "8", "7", "6", "5", + "4", "3", "2", "1", "0"}; + std::string values[10] = {"9", "8", "7", "6", "5", + "4", "3", "2", "1", "0"}; + Slice value_slices[10]; + WriteBatch batch; + Status s; + for (int i = 0; i < 10; i++) { + keys[i] += key.ToString(); + values[i] += value.ToString(); + value_slices[i] = values[i]; + batch.Put(keys[i], value_slices[i]); + } + + s = db_->Write(writeoptions, &batch); + if (!s.ok()) { + fprintf(stderr, "multiput error: %s\n", s.ToString().c_str()); + thread->stats.AddErrors(1); + } else { + // we did 10 writes each of size sz + 1 + thread->stats.AddBytesForWrites(10, (sz + 1) * 10); + } + + return s; + } + + + // Given a key K, this deletes ("0"+K), ("1"+K),... ("9"+K) + // in DB atomically i.e in a single batch. Also refer MultiGet. + Status MultiDelete(ThreadState* thread, + const WriteOptions& writeoptions, + const Slice& key) { + std::string keys[10] = {"9", "7", "5", "3", "1", + "8", "6", "4", "2", "0"}; + + WriteBatch batch; + Status s; + for (int i = 0; i < 10; i++) { + keys[i] += key.ToString(); + batch.Delete(keys[i]); + } + + s = db_->Write(writeoptions, &batch); + if (!s.ok()) { + fprintf(stderr, "multidelete error: %s\n", s.ToString().c_str()); + thread->stats.AddErrors(1); + } else { + thread->stats.AddDeletes(10); + } + + return s; + } + + // Given a key K, this gets values for "0"+K, "1"+K,..."9"+K + // in the same snapshot, and verifies that all the values are of the form + // "0"+V, "1"+V,..."9"+V. + // ASSUMES that MultiPut was used to put (K, V) into the DB. + Status MultiGet(ThreadState* thread, + const ReadOptions& readoptions, + const Slice& key, std::string* value) { + std::string keys[10] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; + Slice key_slices[10]; + std::string values[10]; + ReadOptions readoptionscopy = readoptions; + readoptionscopy.snapshot = db_->GetSnapshot(); + Status s; + for (int i = 0; i < 10; i++) { + keys[i] += key.ToString(); + key_slices[i] = keys[i]; + s = db_->Get(readoptionscopy, key_slices[i], value); + if (!s.ok() && !s.IsNotFound()) { + fprintf(stderr, "get error: %s\n", s.ToString().c_str()); + values[i] = ""; + thread->stats.AddErrors(1); + // we continue after error rather than exiting so that we can + // find more errors if any + } else if (s.IsNotFound()) { + values[i] = ""; + } else { + values[i] = *value; + + char expected_prefix = (keys[i])[0]; + char actual_prefix = (values[i])[0]; + if (actual_prefix != expected_prefix) { + fprintf(stderr, "expected prefix = %c actual = %c\n", + expected_prefix, actual_prefix); + } + (values[i])[0] = ' '; // blank out the differing character + thread->stats.AddFounds(1); + } + } + db_->ReleaseSnapshot(readoptionscopy.snapshot); + + // Now that we retrieved all values, check that they all match + for (int i = 1; i < 10; i++) { + if (values[i] != values[0]) { + fprintf(stderr, "inconsistent values for key %s: %s, %s\n", + key.ToString().c_str(), values[0].c_str(), + values[i].c_str()); + // we continue after error rather than exiting so that we can + // find more errors if any + } + } + + return s; + } + + void OperateDb(ThreadState* thread) { + ReadOptions read_opts(FLAGS_verify_checksum, true); + WriteOptions write_opts; + char value[100]; + long max_key = thread->shared->GetMaxKey(); + std::string from_db; + if (FLAGS_sync) { + write_opts.sync = true; + } + write_opts.disableWAL = FLAGS_disable_wal; + + thread->stats.Start(); + for (long i = 0; i < FLAGS_ops_per_thread; i++) { + if(i != 0 && (i % (FLAGS_ops_per_thread / (FLAGS_reopen + 1))) == 0) { + { + thread->stats.FinishedSingleOp(); + MutexLock l(thread->shared->GetMutex()); + thread->shared->IncVotedReopen(); + if (thread->shared->AllVotedReopen()) { + thread->shared->GetStressTest()->Reopen(); + thread->shared->GetCondVar()->SignalAll(); + } + else { + thread->shared->GetCondVar()->Wait(); + } + thread->stats.Start(); + } + } + + long rand_key = thread->rand.Next() % max_key; + Slice key((char*)&rand_key, sizeof(rand_key)); + //Read:10%;Delete:30%;Write:60% + unsigned int probability_operation = thread->rand.Uniform(100); + if (probability_operation < FLAGS_readpercent) { + // read load + FLAGS_test_batches_snapshots ? + MultiGet(thread, read_opts, key, &from_db) : + db_->Get(read_opts, key, &from_db); + } else if (probability_operation < FLAGS_delpercent + FLAGS_readpercent) { + //introduce delete load + if (!FLAGS_test_batches_snapshots) { + MutexLock l(thread->shared->GetMutexForKey(rand_key)); + thread->shared->Delete(rand_key); + db_->Delete(write_opts, key); + thread->stats.AddDeletes(1); + } else { + MultiDelete(thread, write_opts, key); + } + + } else { + // write load + uint32_t value_base = thread->rand.Next(); + size_t sz = GenerateValue(value_base, value, sizeof(value)); + Slice v(value, sz); + if (!FLAGS_test_batches_snapshots) { + MutexLock l(thread->shared->GetMutexForKey(rand_key)); + if (FLAGS_verify_before_write) { + VerifyValue(rand_key, read_opts, *(thread->shared), &from_db, true); + } + thread->shared->Put(rand_key, value_base); + db_->Put(write_opts, key, v); + thread->stats.AddBytesForWrites(1, sz); + } else { + MultiPut(thread, write_opts, key, v, sz); + } + + PrintKeyValue(rand_key, value, sz); + } + thread->stats.FinishedSingleOp(); + } + thread->stats.Stop(); + } + + void VerifyDb(const SharedState &shared, long start) const { + ReadOptions options(FLAGS_verify_checksum, true); + long max_key = shared.GetMaxKey(); + long step = shared.GetNumThreads(); + for (long i = start; i < max_key; i+= step) { + std::string from_db; + VerifyValue(i, options, shared, &from_db, true); + if (from_db.length()) { + PrintKeyValue(i, from_db.data(), from_db.length()); + } + } + } + + void VerificationAbort(std::string msg, long key) const { + fprintf(stderr, "Verification failed for key %ld: %s\n", + key, msg.c_str()); + exit(1); + } + + void VerifyValue(long key, const ReadOptions &opts, const SharedState &shared, + std::string *value_from_db, bool strict=false) const { + Slice k((char*)&key, sizeof(key)); + char value[100]; + uint32_t value_base = shared.Get(key); + if (value_base == SharedState::SENTINEL && !strict) { + return; + } + + if (db_->Get(opts, k, value_from_db).ok()) { + if (value_base == SharedState::SENTINEL) { + VerificationAbort("Unexpected value found", key); + } + size_t sz = GenerateValue(value_base, value, sizeof(value)); + if (value_from_db->length() != sz) { + VerificationAbort("Length of value read is not equal", key); + } + if (memcmp(value_from_db->data(), value, sz) != 0) { + VerificationAbort("Contents of value read don't match", key); + } + } else { + if (value_base != SharedState::SENTINEL) { + VerificationAbort("Value not found", key); + } + } + } + + static void PrintKeyValue(uint32_t key, const char *value, size_t sz) { + if (!FLAGS_verbose) return; + fprintf(stdout, "%u ==> (%u) ", key, (unsigned int)sz); + for (size_t i=0; i= sizeof(uint32_t)); + *((uint32_t*)v) = rand; + for (size_t i=sizeof(uint32_t); i < value_sz; i++) { + v[i] = (char)(rand ^ i); + } + return value_sz; // the size of the value set. + } + + void PrintEnv() const { + fprintf(stdout, "LevelDB version : %d.%d\n", + kMajorVersion, kMinorVersion); + fprintf(stdout, "Number of threads : %d\n", FLAGS_threads); + fprintf(stdout, "Ops per thread : %d\n", FLAGS_ops_per_thread); + fprintf(stdout, "Read percentage : %d\n", FLAGS_readpercent); + fprintf(stdout, "Delete percentage : %d\n", FLAGS_delpercent); + fprintf(stdout, "Max key : %ld\n", FLAGS_max_key); + fprintf(stdout, "Ratio #ops/#keys : %ld\n", + (FLAGS_ops_per_thread * FLAGS_threads)/FLAGS_max_key); + fprintf(stdout, "Num times DB reopens: %d\n", FLAGS_reopen); + fprintf(stdout, "Batches/snapshots : %d\n", + FLAGS_test_batches_snapshots); + fprintf(stdout, "Purge redundant %% : %d\n", + FLAGS_purge_redundant_percent); + fprintf(stdout, "Num keys per lock : %d\n", + 1 << FLAGS_log2_keys_per_lock); + + const char* compression = ""; + switch (FLAGS_compression_type) { + case leveldb::kNoCompression: + compression = "none"; + break; + case leveldb::kSnappyCompression: + compression = "snappy"; + break; + case leveldb::kZlibCompression: + compression = "zlib"; + break; + case leveldb::kBZip2Compression: + compression = "bzip2"; + break; + } + + fprintf(stdout, "Compression : %s\n", compression); + fprintf(stdout, "------------------------------------------------\n"); + } + + void Open() { + assert(db_ == nullptr); + Options options; + options.block_cache = cache_; + options.write_buffer_size = FLAGS_write_buffer_size; + options.max_write_buffer_number = FLAGS_max_write_buffer_number; + options.max_background_compactions = FLAGS_max_background_compactions; + options.block_size = FLAGS_block_size; + options.filter_policy = filter_policy_; + options.max_open_files = FLAGS_open_files; + options.statistics = dbstats; + options.env = FLAGS_env; + options.disableDataSync = FLAGS_disable_data_sync; + options.use_fsync = FLAGS_use_fsync; + options.target_file_size_base = FLAGS_target_file_size_base; + options.target_file_size_multiplier = FLAGS_target_file_size_multiplier; + options.max_bytes_for_level_base = FLAGS_max_bytes_for_level_base; + options.max_bytes_for_level_multiplier = + FLAGS_max_bytes_for_level_multiplier; + options.level0_stop_writes_trigger = FLAGS_level0_stop_writes_trigger; + options.level0_slowdown_writes_trigger = + FLAGS_level0_slowdown_writes_trigger; + options.compression = FLAGS_compression_type; + options.create_if_missing = true; + options.disable_seek_compaction = FLAGS_disable_seek_compaction; + options.delete_obsolete_files_period_micros = + FLAGS_delete_obsolete_files_period_micros; + options.max_manifest_file_size = 1024; + static Random purge_percent(1000); // no benefit from non-determinism here + if (purge_percent.Uniform(100) < FLAGS_purge_redundant_percent - 1) { + options.purge_redundant_kvs_while_flush = false; + } + Status s = DB::Open(options, FLAGS_db, &db_); + if (!s.ok()) { + fprintf(stderr, "open error: %s\n", s.ToString().c_str()); + exit(1); + } + } + + void Reopen() { + // do not close the db. Just delete the lock file. This + // simulates a crash-recovery kind of situation. + ((DBImpl*) db_)->TEST_Destroy_DBImpl(); + db_ = nullptr; + + num_times_reopened_++; + double now = FLAGS_env->NowMicros(); + fprintf(stdout, "%s Reopening database for the %dth time\n", + FLAGS_env->TimeToString((uint64_t) now/1000000).c_str(), + num_times_reopened_); + Open(); + } + + void PrintStatistics() { + if (dbstats) { + fprintf(stdout, "File opened:%ld closed:%ld errors:%ld\n", + dbstats->getTickerCount(NO_FILE_OPENS), + dbstats->getTickerCount(NO_FILE_CLOSES), + dbstats->getTickerCount(NO_FILE_ERRORS)); + } + } + + private: + shared_ptr cache_; + const FilterPolicy* filter_policy_; + DB* db_; + int num_times_reopened_; +}; + +} // namespace leveldb + +int main(int argc, char** argv) { + FLAGS_write_buffer_size = leveldb::Options().write_buffer_size; + FLAGS_max_write_buffer_number = leveldb::Options().max_write_buffer_number; + FLAGS_open_files = leveldb::Options().max_open_files; + FLAGS_max_background_compactions = + leveldb::Options().max_background_compactions; + // Compression test code above refers to FLAGS_block_size + FLAGS_block_size = leveldb::Options().block_size; + std::string default_db_path; + + for (int i = 1; i < argc; i++) { + int n; + uint32_t u; + long l; + char junk; + char hdfsname[2048]; + + if (sscanf(argv[i], "--seed=%uf%c", &u, &junk) == 1) { + FLAGS_seed = u; + } else if (sscanf(argv[i], "--max_key=%ld%c", &l, &junk) == 1) { + FLAGS_max_key = l; + } else if (sscanf(argv[i], "--log2_keys_per_lock=%u%c", &u, &junk) == 1) { + FLAGS_log2_keys_per_lock = u; + } else if (sscanf(argv[i], "--ops_per_thread=%u%c", &u, &junk) == 1) { + FLAGS_ops_per_thread = u; + } else if (sscanf(argv[i], "--verbose=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_verbose = n; + } else if (sscanf(argv[i], "--histogram=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_histogram = n; + } else if (sscanf(argv[i], "--verify_before_write=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_verify_before_write = n; + } else if (sscanf(argv[i], "--test_batches_snapshots=%d%c", &n, &junk) == 1 + && (n == 0 || n == 1)) { + FLAGS_test_batches_snapshots = n; + } else if (sscanf(argv[i], "--threads=%d%c", &n, &junk) == 1) { + FLAGS_threads = n; + } else if (sscanf(argv[i], "--value_size_mult=%d%c", &n, &junk) == 1) { + FLAGS_value_size_mult = n; + } else if (sscanf(argv[i], "--write_buffer_size=%d%c", &n, &junk) == 1) { + FLAGS_write_buffer_size = n; + } else if (sscanf(argv[i], "--max_write_buffer_number=%d%c", &n, &junk) == 1) { + FLAGS_max_write_buffer_number = n; + } else if (sscanf(argv[i], "--max_background_compactions=%d%c", &n, &junk) == 1) { + FLAGS_max_background_compactions = n; + } else if (sscanf(argv[i], "--cache_size=%ld%c", &l, &junk) == 1) { + FLAGS_cache_size = l; + } else if (sscanf(argv[i], "--block_size=%d%c", &n, &junk) == 1) { + FLAGS_block_size = n; + } else if (sscanf(argv[i], "--reopen=%d%c", &n, &junk) == 1 && n >= 0) { + FLAGS_reopen = n; + } else if (sscanf(argv[i], "--bloom_bits=%d%c", &n, &junk) == 1) { + FLAGS_bloom_bits = n; + } else if (sscanf(argv[i], "--open_files=%d%c", &n, &junk) == 1) { + FLAGS_open_files = n; + } else if (strncmp(argv[i], "--db=", 5) == 0) { + FLAGS_db = argv[i] + 5; + } else if (sscanf(argv[i], "--verify_checksum=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_verify_checksum = n; + } else if (sscanf(argv[i], "--bufferedio=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + useOsBuffer = n; + } else if (sscanf(argv[i], "--mmap_read=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + useMmapRead = n; + } else if (sscanf(argv[i], "--readhead=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + useFsReadAhead = n; + } else if (sscanf(argv[i], "--statistics=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + if (n == 1) { + dbstats = new leveldb::DBStatistics(); + } + } else if (sscanf(argv[i], "--sync=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_sync = n; + } else if (sscanf(argv[i], "--readpercent=%d%c", &n, &junk) == 1 && + (n >= 0 && n <= 100)) { + FLAGS_readpercent = n; + } else if (sscanf(argv[i], "--delpercent=%d%c", &n, &junk) == 1 && + (n >= 0 && n <= 100)) { + FLAGS_delpercent = n; + } else if (sscanf(argv[i], "--disable_data_sync=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_disable_data_sync = n; + } else if (sscanf(argv[i], "--use_fsync=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_use_fsync = n; + } else if (sscanf(argv[i], "--disable_wal=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_disable_wal = n; + } else if (sscanf(argv[i], "--hdfs=%s", hdfsname) == 1) { + FLAGS_env = new leveldb::HdfsEnv(hdfsname); + } else if (sscanf(argv[i], "--target_file_size_base=%d%c", + &n, &junk) == 1) { + FLAGS_target_file_size_base = n; + } else if ( sscanf(argv[i], "--target_file_size_multiplier=%d%c", + &n, &junk) == 1) { + FLAGS_target_file_size_multiplier = n; + } else if ( + sscanf(argv[i], "--max_bytes_for_level_base=%ld%c", &l, &junk) == 1) { + FLAGS_max_bytes_for_level_base = l; + } else if (sscanf(argv[i], "--max_bytes_for_level_multiplier=%d%c", + &n, &junk) == 1) { + FLAGS_max_bytes_for_level_multiplier = n; + } else if (sscanf(argv[i],"--level0_stop_writes_trigger=%d%c", + &n, &junk) == 1) { + FLAGS_level0_stop_writes_trigger = n; + } else if (sscanf(argv[i],"--level0_slowdown_writes_trigger=%d%c", + &n, &junk) == 1) { + FLAGS_level0_slowdown_writes_trigger = n; + } else if (strncmp(argv[i], "--compression_type=", 19) == 0) { + const char* ctype = argv[i] + 19; + if (!strcasecmp(ctype, "none")) + FLAGS_compression_type = leveldb::kNoCompression; + else if (!strcasecmp(ctype, "snappy")) + FLAGS_compression_type = leveldb::kSnappyCompression; + else if (!strcasecmp(ctype, "zlib")) + FLAGS_compression_type = leveldb::kZlibCompression; + else if (!strcasecmp(ctype, "bzip2")) + FLAGS_compression_type = leveldb::kBZip2Compression; + else { + fprintf(stdout, "Cannot parse %s\n", argv[i]); + } + } else if (sscanf(argv[i], "--disable_seek_compaction=%d%c", &n, &junk) == 1 + && (n == 0 || n == 1)) { + FLAGS_disable_seek_compaction = n; + } else if (sscanf(argv[i], "--delete_obsolete_files_period_micros=%ld%c", + &l, &junk) == 1) { + FLAGS_delete_obsolete_files_period_micros = n; + } else if (sscanf(argv[i], "--purge_redundant_percent=%d%c", &n, &junk) == 1 + && (n >= 0 && n <= 100)) { + FLAGS_purge_redundant_percent = n; + } else { + fprintf(stderr, "Invalid flag '%s'\n", argv[i]); + exit(1); + } + } + + // The number of background threads should be at least as much the + // max number of concurrent compactions. + FLAGS_env->SetBackgroundThreads(FLAGS_max_background_compactions); + + if ((FLAGS_readpercent + FLAGS_delpercent) > 100) { + fprintf(stderr, "Error: Read + Delete percents > 100!\n"); + exit(1); + } + + // Choose a location for the test database if none given with --db= + if (FLAGS_db == nullptr) { + leveldb::Env::Default()->GetTestDirectory(&default_db_path); + default_db_path += "/dbstress"; + FLAGS_db = default_db_path.c_str(); + } + + leveldb::StressTest stress; + stress.Run(); + if (dbstats) { + delete dbstats; + } + return 0; +} diff --git a/tools/ldb.cc b/tools/ldb.cc new file mode 100644 index 00000000..56e3d967 --- /dev/null +++ b/tools/ldb.cc @@ -0,0 +1,94 @@ +// Copyright (c) 2012 Facebook. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "util/ldb_cmd.h" + +namespace leveldb { + +class LDBCommandRunner { +public: + + static void PrintHelp(const char* exec_name) { + string ret; + + ret.append("ldb - LevelDB Tool"); + ret.append("\n\n"); + ret.append("All commands MUST specify --" + LDBCommand::ARG_DB + + "=\n"); + ret.append("\n"); + ret.append("The following optional parameters control if keys/values are " + "input/output as hex or as plain strings:\n"); + ret.append(" --" + LDBCommand::ARG_KEY_HEX + + " : Keys are input/output as hex\n"); + ret.append(" --" + LDBCommand::ARG_VALUE_HEX + + " : Values are input/output as hex\n"); + ret.append(" --" + LDBCommand::ARG_HEX + + " : Both keys and values are input/output as hex\n"); + ret.append("\n"); + + ret.append("The following optional parameters control the database " + "internals:\n"); + ret.append(" --" + LDBCommand::ARG_BLOOM_BITS + "=\n"); + ret.append(" --" + LDBCommand::ARG_COMPRESSION_TYPE + + "=\n"); + ret.append(" --" + LDBCommand::ARG_BLOCK_SIZE + + "=\n"); + ret.append(" --" + LDBCommand::ARG_AUTO_COMPACTION + "=\n"); + ret.append(" --" + LDBCommand::ARG_WRITE_BUFFER_SIZE + + "=\n"); + ret.append(" --" + LDBCommand::ARG_FILE_SIZE + "=\n"); + + ret.append("\n\n"); + ret.append("Data Access Commands:\n"); + PutCommand::Help(ret); + GetCommand::Help(ret); + BatchPutCommand::Help(ret); + ScanCommand::Help(ret); + DeleteCommand::Help(ret); + DBQuerierCommand::Help(ret); + ApproxSizeCommand::Help(ret); + + ret.append("\n\n"); + ret.append("Admin Commands:\n"); + WALDumperCommand::Help(ret); + CompactorCommand::Help(ret); + ReduceDBLevelsCommand::Help(ret); + DBDumperCommand::Help(ret); + DBLoaderCommand::Help(ret); + + fprintf(stderr, "%s\n", ret.c_str()); + } + + static void RunCommand(int argc, char** argv) { + if (argc <= 2) { + PrintHelp(argv[0]); + exit(1); + } + + LDBCommand* cmdObj = LDBCommand::InitFromCmdLineArgs(argc, argv); + if (cmdObj == NULL) { + fprintf(stderr, "Unknown command\n"); + PrintHelp(argv[0]); + exit(1); + } + + if (!cmdObj->ValidateCmdLineOptions()) { + exit(1); + } + + cmdObj->Run(); + LDBCommandExecuteResult ret = cmdObj->GetExecuteState(); + fprintf(stderr, "%s\n", ret.ToString().c_str()); + delete cmdObj; + + exit(ret.IsFailed()); + } + +}; + +} + +int main(int argc, char** argv) { + leveldb::LDBCommandRunner::RunCommand(argc, argv); +} diff --git a/tools/ldb_test.py b/tools/ldb_test.py new file mode 100644 index 00000000..142a5a89 --- /dev/null +++ b/tools/ldb_test.py @@ -0,0 +1,308 @@ +import os +import os.path +import shutil +import subprocess +import time +import unittest +import tempfile + +def my_check_output(*popenargs, **kwargs): + """ + If we had python 2.7, we should simply use subprocess.check_output. + This is a stop-gap solution for python 2.6 + """ + if 'stdout' in kwargs: + raise ValueError('stdout argument not allowed, it will be overridden.') + process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) + output, unused_err = process.communicate() + retcode = process.poll() + if retcode: + cmd = kwargs.get("args") + if cmd is None: + cmd = popenargs[0] + raise Exception("Exit code is not 0. It is %d. Command: %s" % + (retcode, cmd)) + return output + + +class LDBTestCase(unittest.TestCase): + def setUp(self): + self.TMP_DIR = tempfile.mkdtemp(prefix="ldb_test_") + self.DB_NAME = "testdb" + + def tearDown(self): + assert(self.TMP_DIR.strip() != "/" + and self.TMP_DIR.strip() != "/tmp" + and self.TMP_DIR.strip() != "/tmp/") #Just some paranoia + + shutil.rmtree(self.TMP_DIR) + + def dbParam(self, dbName): + return "--db=%s" % os.path.join(self.TMP_DIR, dbName) + + def assertRunOKFull(self, params, expectedOutput): + """ + All command-line params must be specified. + Allows full flexibility in testing; for example: missing db param. + + """ + + output = my_check_output("./ldb %s |grep -v \"Created bg thread\"" % + params, shell=True) + self.assertEquals(output.strip(), expectedOutput.strip()); + + def assertRunFAILFull(self, params): + """ + All command-line params must be specified. + Allows full flexibility in testing; for example: missing db param. + + """ + try: + my_check_output("./ldb %s |grep -v \"Created bg thread\"" % params, + shell=True) + except Exception, e: + return + self.fail( + "Exception should have been raised for command with params: %s" % + params) + + def assertRunOK(self, params, expectedOutput): + """ + Uses the default test db. + + """ + self.assertRunOKFull("%s %s" % (self.dbParam(self.DB_NAME), params), + expectedOutput) + + def assertRunFAIL(self, params): + """ + Uses the default test db. + """ + self.assertRunFAILFull("%s %s" % (self.dbParam(self.DB_NAME), params)) + + def testSimpleStringPutGet(self): + self.assertRunFAIL("put x1 y1") + self.assertRunOK("put --create_if_missing x1 y1", "OK") + self.assertRunOK("get x1", "y1") + self.assertRunFAIL("get x2") + + self.assertRunOK("put x2 y2", "OK") + self.assertRunOK("get x1", "y1") + self.assertRunOK("get x2", "y2") + self.assertRunFAIL("get x3") + + self.assertRunOK("scan --from=x1 --to=z", "x1 : y1\nx2 : y2") + self.assertRunOK("put x3 y3", "OK") + + self.assertRunOK("scan --from=x1 --to=z", "x1 : y1\nx2 : y2\nx3 : y3") + self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3") + self.assertRunOK("scan --from=x", "x1 : y1\nx2 : y2\nx3 : y3") + + self.assertRunOK("scan --to=x2", "x1 : y1") + self.assertRunOK("scan --from=x1 --to=z --max_keys=1", "x1 : y1") + self.assertRunOK("scan --from=x1 --to=z --max_keys=2", + "x1 : y1\nx2 : y2") + + self.assertRunOK("scan --from=x1 --to=z --max_keys=3", + "x1 : y1\nx2 : y2\nx3 : y3") + self.assertRunOK("scan --from=x1 --to=z --max_keys=4", + "x1 : y1\nx2 : y2\nx3 : y3") + self.assertRunOK("scan --from=x1 --to=x2", "x1 : y1") + self.assertRunOK("scan --from=x2 --to=x4", "x2 : y2\nx3 : y3") + self.assertRunFAIL("scan --from=x4 --to=z") # No results => FAIL + self.assertRunFAIL("scan --from=x1 --to=z --max_keys=foo") + + self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3") + + self.assertRunOK("delete x1", "OK") + self.assertRunOK("scan", "x2 : y2\nx3 : y3") + + self.assertRunOK("delete NonExistentKey", "OK") + # It is wierd that GET and SCAN raise exception for + # non-existent key, while delete does not + + def dumpDb(self, params, dumpFile): + return 0 == os.system("./ldb dump %s > %s" % (params, dumpFile)) + + def loadDb(self, params, dumpFile): + return 0 == os.system("cat %s | ./ldb load %s" % (dumpFile, params)) + + def testStringBatchPut(self): + self.assertRunOK("batchput x1 y1 --create_if_missing", "OK") + self.assertRunOK("scan", "x1 : y1") + self.assertRunOK("batchput x2 y2 x3 y3 \"x4 abc\" \"y4 xyz\"", "OK") + self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 abc : y4 xyz") + self.assertRunFAIL("batchput") + self.assertRunFAIL("batchput k1") + self.assertRunFAIL("batchput k1 v1 k2") + + + def testHexPutGet(self): + self.assertRunOK("put a1 b1 --create_if_missing", "OK") + self.assertRunOK("scan", "a1 : b1") + self.assertRunOK("scan --hex", "0x6131 : 0x6231") + self.assertRunFAIL("put --hex 6132 6232") + self.assertRunOK("put --hex 0x6132 0x6232", "OK") + self.assertRunOK("scan --hex", "0x6131 : 0x6231\n0x6132 : 0x6232") + self.assertRunOK("scan", "a1 : b1\na2 : b2") + self.assertRunOK("get a1", "b1") + self.assertRunOK("get --hex 0x6131", "0x6231") + self.assertRunOK("get a2", "b2") + self.assertRunOK("get --hex 0x6132", "0x6232") + self.assertRunOK("get --key_hex 0x6132", "b2") + self.assertRunOK("get --key_hex --value_hex 0x6132", "0x6232") + self.assertRunOK("get --value_hex a2", "0x6232") + self.assertRunOK("scan --key_hex --value_hex", + "0x6131 : 0x6231\n0x6132 : 0x6232") + self.assertRunOK("scan --hex --from=0x6131 --to=0x6133", + "0x6131 : 0x6231\n0x6132 : 0x6232") + self.assertRunOK("scan --hex --from=0x6131 --to=0x6132", + "0x6131 : 0x6231") + self.assertRunOK("scan --key_hex", "0x6131 : b1\n0x6132 : b2") + self.assertRunOK("scan --value_hex", "a1 : 0x6231\na2 : 0x6232") + self.assertRunOK("batchput --hex 0x6133 0x6233 0x6134 0x6234", "OK") + self.assertRunOK("scan", "a1 : b1\na2 : b2\na3 : b3\na4 : b4") + self.assertRunOK("delete --hex 0x6133", "OK") + self.assertRunOK("scan", "a1 : b1\na2 : b2\na4 : b4") + + + def testInvalidCmdLines(self): + # db not specified + self.assertRunFAILFull("put 0x6133 0x6233 --hex --create_if_missing") + # No param called he + self.assertRunFAIL("put 0x6133 0x6233 --he --create_if_missing") + # max_keys is not applicable for put + self.assertRunFAIL("put 0x6133 0x6233 --max_keys=1 --create_if_missing") + # hex has invalid boolean value + self.assertRunFAIL("put 0x6133 0x6233 --hex=Boo --create_if_missing") + + + def testDumpLoad(self): + self.assertRunOK("batchput --create_if_missing x1 y1 x2 y2 x3 y3 x4 y4", + "OK") + self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4") + origDbPath = os.path.join(self.TMP_DIR, self.DB_NAME) + + # Dump and load without any additional params specified + dumpFilePath = os.path.join(self.TMP_DIR, "dump1") + loadedDbPath = os.path.join(self.TMP_DIR, "loaded_from_dump1") + self.assertTrue(self.dumpDb("--db=%s" % origDbPath, dumpFilePath)) + self.assertTrue(self.loadDb( + "--db=%s --create_if_missing" % loadedDbPath, dumpFilePath)) + self.assertRunOKFull("scan --db=%s" % loadedDbPath, + "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4") + + # Dump and load in hex + dumpFilePath = os.path.join(self.TMP_DIR, "dump2") + loadedDbPath = os.path.join(self.TMP_DIR, "loaded_from_dump2") + self.assertTrue(self.dumpDb("--db=%s --hex" % origDbPath, dumpFilePath)) + self.assertTrue(self.loadDb( + "--db=%s --hex --create_if_missing" % loadedDbPath, dumpFilePath)) + self.assertRunOKFull("scan --db=%s" % loadedDbPath, + "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4") + + # Dump only a portion of the key range + dumpFilePath = os.path.join(self.TMP_DIR, "dump3") + loadedDbPath = os.path.join(self.TMP_DIR, "loaded_from_dump3") + self.assertTrue(self.dumpDb( + "--db=%s --from=x1 --to=x3" % origDbPath, dumpFilePath)) + self.assertTrue(self.loadDb( + "--db=%s --create_if_missing" % loadedDbPath, dumpFilePath)) + self.assertRunOKFull("scan --db=%s" % loadedDbPath, "x1 : y1\nx2 : y2") + + # Dump upto max_keys rows + dumpFilePath = os.path.join(self.TMP_DIR, "dump4") + loadedDbPath = os.path.join(self.TMP_DIR, "loaded_from_dump4") + self.assertTrue(self.dumpDb( + "--db=%s --max_keys=3" % origDbPath, dumpFilePath)) + self.assertTrue(self.loadDb( + "--db=%s --create_if_missing" % loadedDbPath, dumpFilePath)) + self.assertRunOKFull("scan --db=%s" % loadedDbPath, + "x1 : y1\nx2 : y2\nx3 : y3") + + # Load into an existing db, create_if_missing is not specified + self.assertTrue(self.dumpDb("--db=%s" % origDbPath, dumpFilePath)) + self.assertTrue(self.loadDb("--db=%s" % loadedDbPath, dumpFilePath)) + self.assertRunOKFull("scan --db=%s" % loadedDbPath, + "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4") + + # Dump and load with WAL disabled + dumpFilePath = os.path.join(self.TMP_DIR, "dump5") + loadedDbPath = os.path.join(self.TMP_DIR, "loaded_from_dump5") + self.assertTrue(self.dumpDb("--db=%s" % origDbPath, dumpFilePath)) + self.assertTrue(self.loadDb( + "--db=%s --disable_wal --create_if_missing" % loadedDbPath, + dumpFilePath)) + self.assertRunOKFull("scan --db=%s" % loadedDbPath, + "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4") + + # Dump and load with lots of extra params specified + extraParams = " ".join(["--bloom_bits=14", "--compression_type=bzip2", + "--block_size=1024", "--auto_compaction=true", + "--write_buffer_size=4194304", + "--file_size=2097152"]) + dumpFilePath = os.path.join(self.TMP_DIR, "dump6") + loadedDbPath = os.path.join(self.TMP_DIR, "loaded_from_dump6") + self.assertTrue(self.dumpDb( + "--db=%s %s" % (origDbPath, extraParams), dumpFilePath)) + self.assertTrue(self.loadDb( + "--db=%s %s --create_if_missing" % (loadedDbPath, extraParams), + dumpFilePath)) + self.assertRunOKFull("scan --db=%s" % loadedDbPath, + "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4") + + # Dump with count_only + dumpFilePath = os.path.join(self.TMP_DIR, "dump7") + loadedDbPath = os.path.join(self.TMP_DIR, "loaded_from_dump7") + self.assertTrue(self.dumpDb( + "--db=%s --count_only" % origDbPath, dumpFilePath)) + self.assertTrue(self.loadDb( + "--db=%s --create_if_missing" % loadedDbPath, dumpFilePath)) + # DB should have atleast one value for scan to work + self.assertRunOKFull("put --db=%s k1 v1" % loadedDbPath, "OK") + self.assertRunOKFull("scan --db=%s" % loadedDbPath, "k1 : v1") + + # Dump command fails because of typo in params + dumpFilePath = os.path.join(self.TMP_DIR, "dump8") + self.assertFalse(self.dumpDb( + "--db=%s --create_if_missin" % origDbPath, dumpFilePath)) + + + def testMiscAdminTask(self): + # These tests need to be improved; for example with asserts about + # whether compaction or level reduction actually took place. + self.assertRunOK("batchput --create_if_missing x1 y1 x2 y2 x3 y3 x4 y4", + "OK") + self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4") + origDbPath = os.path.join(self.TMP_DIR, self.DB_NAME) + + self.assertTrue(0 == os.system("./ldb compact --db=%s" % origDbPath)) + self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4") + + self.assertTrue(0 == os.system( + "./ldb reduce_levels --db=%s --new_levels=2" % origDbPath)) + self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4") + + self.assertTrue(0 == os.system( + "./ldb reduce_levels --db=%s --new_levels=3" % origDbPath)) + self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4") + + self.assertTrue(0 == os.system( + "./ldb compact --db=%s --from=x1 --to=x3" % origDbPath)) + self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4") + + self.assertTrue(0 == os.system( + "./ldb compact --db=%s --hex --from=0x6131 --to=0x6134" % + origDbPath)) + self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4") + + #TODO(dilip): Not sure what should be passed to WAL.Currently corrupted. + self.assertTrue(0 == os.system( + "./ldb dump_wal --db=%s --walfile=%s --header" % ( + origDbPath, os.path.join(origDbPath, "LOG")))) + self.assertRunOK("scan", "x1 : y1\nx2 : y2\nx3 : y3\nx4 : y4") + + +if __name__ == "__main__": + unittest.main() + diff --git a/tools/manifest_dump.cc b/tools/manifest_dump.cc new file mode 100644 index 00000000..4cb28c7c --- /dev/null +++ b/tools/manifest_dump.cc @@ -0,0 +1,79 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/version_set.h" + +#include +#include +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "db/memtable.h" +#include "db/table_cache.h" +#include "leveldb/env.h" +#include "leveldb/table_builder.h" +#include "table/merger.h" +#include "table/two_level_iterator.h" +#include "util/coding.h" +#include "util/logging.h" + +static int verbose = 0; +static int output_hex = 0; + +using namespace leveldb; + +// +// Takes a manifest file and dumps out all metedata +// +int main(int argc, char** argv) { + + // parse command line options + size_t n; + char junk; + int foundfile = 0; + std::string manifestfile; + for (int i = 1; i < argc; i++) { + std::string param(argv[i]); + if ((n = param.find("--file=")) != std::string::npos) { + manifestfile = param.substr(strlen("--file=")); + foundfile = 1; + } else if (sscanf(argv[i], "--verbose=%ld%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + verbose = n; + } else if (param == "--output_hex") { + output_hex = n; + } else { + fprintf(stderr, "Unknown or badly-formatted option: %s\n", + argv[i]); + abort(); + } + } + if (!foundfile) { + fprintf(stderr, + "%s [--verbose=0|1] [--output_hex] [--file=pathname of manifest file]\n", + argv[0]); + abort(); + } + + if (verbose) { + printf("Processing Manifest file %s\n", manifestfile.c_str()); + } + + Options options; + std::string file(manifestfile); + std::string dbname("dummy"); + TableCache* tc = new TableCache(dbname, &options, 10); + const InternalKeyComparator* cmp = new InternalKeyComparator(options.comparator); + + VersionSet* versions = new VersionSet(dbname, &options, + tc, cmp); + Status s = versions->DumpManifest(options, file, verbose, output_hex); + if (!s.ok()) { + printf("Error in processing file %s %s\n", manifestfile.c_str(), + s.ToString().c_str()); + } + if (verbose) { + printf("Processing Manifest file %s done\n", manifestfile.c_str()); + } +} diff --git a/tools/reduce_levels_test.cc b/tools/reduce_levels_test.cc new file mode 100644 index 00000000..1e48e296 --- /dev/null +++ b/tools/reduce_levels_test.cc @@ -0,0 +1,197 @@ +// Copyright (c) 2012 Facebook. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +#include "leveldb/db.h" +#include "db/db_impl.h" +#include "db/version_set.h" +#include "util/logging.h" +#include "util/testutil.h" +#include "util/testharness.h" +#include "util/ldb_cmd.h" + +namespace leveldb { + +class ReduceLevelTest { +public: + ReduceLevelTest() { + dbname_ = test::TmpDir() + "/db_reduce_levels_test"; + DestroyDB(dbname_, Options()); + db_ = NULL; + } + + Status OpenDB(bool create_if_missing, int levels, + int mem_table_compact_level); + + Status Put(const std::string& k, const std::string& v) { + return db_->Put(WriteOptions(), k, v); + } + + std::string Get(const std::string& k) { + ReadOptions options; + std::string result; + Status s = db_->Get(options, k, &result); + if (s.IsNotFound()) { + result = "NOT_FOUND"; + } else if (!s.ok()) { + result = s.ToString(); + } + return result; + } + + Status CompactMemTable() { + if (db_ == NULL) { + return Status::InvalidArgument("DB not opened."); + } + DBImpl* db_impl = reinterpret_cast(db_); + return db_impl->TEST_CompactMemTable(); + } + + void CloseDB() { + if (db_ != NULL) { + delete db_; + db_ = NULL; + } + } + + bool ReduceLevels(int target_level); + + int FilesOnLevel(int level) { + std::string property; + ASSERT_TRUE( + db_->GetProperty("leveldb.num-files-at-level" + NumberToString(level), + &property)); + return atoi(property.c_str()); + } + +private: + std::string dbname_; + DB* db_; +}; + +Status ReduceLevelTest::OpenDB(bool create_if_missing, int num_levels, + int mem_table_compact_level) { + leveldb::Options opt; + opt.num_levels = num_levels; + opt.create_if_missing = create_if_missing; + opt.max_mem_compaction_level = mem_table_compact_level; + leveldb::Status st = leveldb::DB::Open(opt, dbname_, &db_); + if (!st.ok()) { + fprintf(stderr, "Can't open the db:%s\n", st.ToString().c_str()); + } + return st; +} + +bool ReduceLevelTest::ReduceLevels(int target_level) { + std::vector args = leveldb::ReduceDBLevelsCommand::PrepareArgs( + dbname_, target_level, false); + LDBCommand* level_reducer = LDBCommand::InitFromCmdLineArgs(args); + level_reducer->Run(); + bool is_succeed = level_reducer->GetExecuteState().IsSucceed(); + delete level_reducer; + return is_succeed; +} + +TEST(ReduceLevelTest, Last_Level) { + // create files on all levels; + ASSERT_OK(OpenDB(true, 4, 3)); + ASSERT_OK(Put("aaaa", "11111")); + ASSERT_OK(CompactMemTable()); + ASSERT_EQ(FilesOnLevel(3), 1); + CloseDB(); + + ASSERT_TRUE(ReduceLevels(3)); + ASSERT_OK(OpenDB(true, 3, 1)); + ASSERT_EQ(FilesOnLevel(2), 1); + CloseDB(); + + ASSERT_TRUE(ReduceLevels(2)); + ASSERT_OK(OpenDB(true, 2, 1)); + ASSERT_EQ(FilesOnLevel(1), 1); + CloseDB(); +} + +TEST(ReduceLevelTest, Top_Level) { + // create files on all levels; + ASSERT_OK(OpenDB(true, 5, 0)); + ASSERT_OK(Put("aaaa", "11111")); + ASSERT_OK(CompactMemTable()); + ASSERT_EQ(FilesOnLevel(0), 1); + CloseDB(); + + ASSERT_TRUE(ReduceLevels(4)); + ASSERT_OK(OpenDB(true, 4, 0)); + CloseDB(); + + ASSERT_TRUE(ReduceLevels(3)); + ASSERT_OK(OpenDB(true, 3, 0)); + CloseDB(); + + ASSERT_TRUE(ReduceLevels(2)); + ASSERT_OK(OpenDB(true, 2, 0)); + CloseDB(); +} + +TEST(ReduceLevelTest, All_Levels) { + // create files on all levels; + ASSERT_OK(OpenDB(true, 5, 1)); + ASSERT_OK(Put("a", "a11111")); + ASSERT_OK(CompactMemTable()); + ASSERT_EQ(FilesOnLevel(1), 1); + CloseDB(); + + ASSERT_OK(OpenDB(true, 5, 2)); + ASSERT_OK(Put("b", "b11111")); + ASSERT_OK(CompactMemTable()); + ASSERT_EQ(FilesOnLevel(1), 1); + ASSERT_EQ(FilesOnLevel(2), 1); + CloseDB(); + + ASSERT_OK(OpenDB(true, 5, 3)); + ASSERT_OK(Put("c", "c11111")); + ASSERT_OK(CompactMemTable()); + ASSERT_EQ(FilesOnLevel(1), 1); + ASSERT_EQ(FilesOnLevel(2), 1); + ASSERT_EQ(FilesOnLevel(3), 1); + CloseDB(); + + ASSERT_OK(OpenDB(true, 5, 4)); + ASSERT_OK(Put("d", "d11111")); + ASSERT_OK(CompactMemTable()); + ASSERT_EQ(FilesOnLevel(1), 1); + ASSERT_EQ(FilesOnLevel(2), 1); + ASSERT_EQ(FilesOnLevel(3), 1); + ASSERT_EQ(FilesOnLevel(4), 1); + CloseDB(); + + ASSERT_TRUE(ReduceLevels(4)); + ASSERT_OK(OpenDB(true, 4, 0)); + ASSERT_EQ("a11111", Get("a")); + ASSERT_EQ("b11111", Get("b")); + ASSERT_EQ("c11111", Get("c")); + ASSERT_EQ("d11111", Get("d")); + CloseDB(); + + ASSERT_TRUE(ReduceLevels(3)); + ASSERT_OK(OpenDB(true, 3, 0)); + ASSERT_EQ("a11111", Get("a")); + ASSERT_EQ("b11111", Get("b")); + ASSERT_EQ("c11111", Get("c")); + ASSERT_EQ("d11111", Get("d")); + CloseDB(); + + ASSERT_TRUE(ReduceLevels(2)); + ASSERT_OK(OpenDB(true, 2, 0)); + ASSERT_EQ("a11111", Get("a")); + ASSERT_EQ("b11111", Get("b")); + ASSERT_EQ("c11111", Get("c")); + ASSERT_EQ("d11111", Get("d")); + CloseDB(); +} + +} + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/tools/shell/DBClientProxy.cpp b/tools/shell/DBClientProxy.cpp new file mode 100644 index 00000000..a1ec7b85 --- /dev/null +++ b/tools/shell/DBClientProxy.cpp @@ -0,0 +1,271 @@ + +#include + +#include "DBClientProxy.h" + + +#include "thrift/lib/cpp/protocol/TBinaryProtocol.h" +#include "thrift/lib/cpp/transport/TSocket.h" +#include "thrift/lib/cpp/transport/TTransportUtils.h" + + + +using namespace std; +using namespace boost; +using namespace Tleveldb; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; + +namespace leveldb { + +DBClientProxy::DBClientProxy(const string & host, int port) : + host_(host), + port_(port), + dbToHandle_(), + dbClient_() { +} + +DBClientProxy::~DBClientProxy() { + cleanUp(); +} + + +void DBClientProxy::connect(void) { + cleanUp(); + printf("Connecting to %s:%d\n", host_.c_str(), port_); + try { + boost::shared_ptr socket(new TSocket(host_, port_)); + boost::shared_ptr transport(new TBufferedTransport(socket)); + boost::shared_ptr protocol(new TBinaryProtocol(transport)); + dbClient_.reset(new DBClient(protocol)); + + transport->open(); + } catch (const std::exception & e) { + dbClient_.reset(); + throw; + } +} + +void DBClientProxy::cleanUp(void) { + if(dbClient_.get()) { + for(map::iterator itor = dbToHandle_.begin(); + itor != dbToHandle_.end(); + ++itor) { + dbClient_->Close(itor->second, itor->first); + } + dbClient_.reset(); + } + dbToHandle_.clear(); +} + +void DBClientProxy::open(const string & db) { + if(!dbClient_.get()) { + printf("please connect() first\n"); + return; + } + + // printf("opening database : %s\n", db.c_str()); + // we use default DBOptions here + DBOptions opt; + DBHandle handle; + try { + dbClient_->Open(handle, db, opt); + } catch (const LeveldbException & e) { + printf("%s\n", e.message.c_str()); + if(kIOError == e.errorCode) { + printf("no such database : %s\n", db.c_str()); + return; + }else { + printf("Unknown error : %d\n", e.errorCode); + return; + } + } + + dbToHandle_[db] = handle; +} + + +bool DBClientProxy::create(const string & db) { + if(!dbClient_.get()) { + printf("please connect() first\n"); + return false; + } + + printf("creating database : %s\n", db.c_str()); + DBOptions opt; + opt.create_if_missing = true; + opt.error_if_exists = true; + DBHandle handle; + try { + dbClient_->Open(handle, db, opt); + }catch (const LeveldbException & e) { + printf("%s\n", e.message.c_str()); + printf("error code : %d\n", e.errorCode); + if(kNotFound == e.errorCode) { + printf("no such database : %s\n", db.c_str()); + return false;; + } else { + printf("Unknown error : %d\n", e.errorCode); + return false; + } + } + + dbToHandle_[db] = handle; + return true; +} + + +map::iterator +DBClientProxy::getHandle(const string & db) { + map::iterator itor = dbToHandle_.find(db); + if(dbToHandle_.end() == itor) { + open(db); + itor = dbToHandle_.find(db); + } + + return itor; +} + + +bool DBClientProxy::get(const string & db, + const string & key, + string & value) { + if(!dbClient_.get()) { + printf("please connect() first\n"); + return false; + } + + map::iterator itor = getHandle(db); + if(dbToHandle_.end() == itor) { + return false; + } + + ResultItem ret; + Slice k; + k.data = key; + k.size = key.size(); + // we use default values of options here + ReadOptions opt; + dbClient_->Get(ret, + itor->second, + k, + opt); + if(kOk == ret.status) { + value = ret.value.data; + return true; + } else if(kNotFound == ret.status) { + printf("no such key : %s\n", key.c_str()); + return false; + } else { + printf("get data error : %d\n", ret.status); + return false; + } +} + + + +bool DBClientProxy::put(const string & db, + const string & key, + const string & value) { + if(!dbClient_.get()) { + printf("please connect() first\n"); + return false; + } + + map::iterator itor = getHandle(db); + if(dbToHandle_.end() == itor) { + return false; + } + + kv temp; + temp.key.data = key; + temp.key.size = key.size(); + temp.value.data = value; + temp.value.size = value.size(); + WriteOptions opt; + opt.sync = true; + Code code; + code = dbClient_->Put(itor->second, + temp, + opt); + + + if(kOk == code) { + // printf("set value finished\n"); + return true; + } else { + printf("put data error : %d\n", code); + return false; + } +} + +bool DBClientProxy::scan(const string & db, + const string & start_key, + const string & end_key, + const string & limit, + vector > & kvs) { + if(!dbClient_.get()) { + printf("please connect() first\n"); + return false; + } + + int limitInt = -1; + limitInt = atoi(limit.c_str()); + if(limitInt <= 0) { + printf("Error while parse limit : %s\n", limit.c_str()); + return false; + } + + if(start_key > end_key) { + printf("empty range.\n"); + return false; + } + + map::iterator itor = getHandle(db); + if(dbToHandle_.end() == itor) { + return false; + } + + ResultIterator ret; + // we use the default values of options here + ReadOptions opt; + Slice k; + k.data = start_key; + k.size = start_key.size(); + dbClient_->NewIterator(ret, + itor->second, + opt, + seekToKey, + k); + Iterator it; + if(kOk == ret.status) { + it = ret.iterator; + } else { + printf("get iterator error : %d\n", ret.status); + return false; + } + + int idx = 0; + string ck = start_key; + while(idx < limitInt && ck < end_key) { + ResultPair retPair; + dbClient_->GetNext(retPair, itor->second, it); + if(kOk == retPair.status) { + ++idx; + ck = retPair.keyvalue.key.data; + if (ck < end_key) { + kvs.push_back(make_pair(retPair.keyvalue.key.data, + retPair.keyvalue.value.data)); + } + } else if(kEnd == retPair.status) { + printf("not enough values\n"); + return true; + } else { + printf("GetNext() error : %d\n", retPair.status); + return false; + } + } + return true; +} + +} // namespace diff --git a/tools/shell/DBClientProxy.h b/tools/shell/DBClientProxy.h new file mode 100644 index 00000000..3be7d1a7 --- /dev/null +++ b/tools/shell/DBClientProxy.h @@ -0,0 +1,64 @@ + +#ifndef TOOLS_SHELL_DBCLIENTPROXY +#define TOOLS_SHELL_DBCLIENTPROXY + +#include +#include +#include +#include +#include + +#include "DB.h" + +/* + * class DBClientProxy maintains: + * 1. a connection to leveldb service + * 2. a map from db names to opened db handles + * + * it's client codes' responsibility to catch all possible exceptions. + */ + +namespace leveldb { + +class DBClientProxy : private boost::noncopyable { + public: + // connect to host_:port_ + void connect(void); + + // return true on success, false otherwise + bool get(const std::string & db, + const std::string & key, + std::string & value); + + // return true on success, false otherwise + bool put(const std::string & db, + const std::string & key, + const std::string & value); + + // return true on success, false otherwise + bool scan(const std::string & db, + const std::string & start_key, + const std::string & end_key, + const std::string & limit, + std::vector > & kvs); + + // return true on success, false otherwise + bool create(const std::string & db); + + DBClientProxy(const std::string & host, int port); + ~DBClientProxy(); + + private: + // some internal help functions + void cleanUp(void); + void open(const std::string & db); + std::map::iterator getHandle(const std::string & db); + + const std::string host_; + const int port_; + std::map dbToHandle_; + boost::shared_ptr dbClient_; +}; + +} // namespace +#endif diff --git a/tools/shell/LeveldbShell.cpp b/tools/shell/LeveldbShell.cpp new file mode 100644 index 00000000..e6274d3b --- /dev/null +++ b/tools/shell/LeveldbShell.cpp @@ -0,0 +1,8 @@ + + +#include "ShellContext.h" + +int main(int argc, char ** argv) { + ShellContext c(argc, argv); + c.run(); +} diff --git a/tools/shell/ShellContext.cpp b/tools/shell/ShellContext.cpp new file mode 100644 index 00000000..36a07e54 --- /dev/null +++ b/tools/shell/ShellContext.cpp @@ -0,0 +1,104 @@ + +#include +#include + +#include "ShellContext.h" +#include "ShellState.h" + + + +#include "thrift/lib/cpp/protocol/TBinaryProtocol.h" +#include "thrift/lib/cpp/transport/TSocket.h" +#include "thrift/lib/cpp/transport/TTransportUtils.h" + + + +using namespace std; +using namespace boost; +using namespace Tleveldb; +using namespace leveldb; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; + +void ShellContext::changeState(ShellState * pState) { + pShellState_ = pState; +} + +void ShellContext::stop(void) { + exit_ = true; +} + +bool ShellContext::ParseInput(void) { + if(argc_ != 3) { + printf("leveldb_shell host port\n"); + return false; + } + + port_ = atoi(argv_[2]); + if(port_ <= 0) { + printf("Error while parse port : %s\n", argv_[2]); + return false; + } + + clientProxy_.reset(new DBClientProxy(argv_[1], port_)); + if(!clientProxy_.get()) { + return false; + } else { + return true; + } +} + +void ShellContext::connect(void) { + clientProxy_->connect(); +} + +void ShellContext::create(const string & db) { + if (clientProxy_->create(db)) { + printf("%s created\n", db.c_str()); + } +} + +void ShellContext::get(const string & db, + const string & key) { + string v; + if (clientProxy_->get(db, key, v)) { + printf("%s\n", v.c_str()); + } +} + +void ShellContext::put(const string & db, + const string & key, + const string & value) { + if (clientProxy_->put(db, key, value)) { + printf("(%s, %s) has been set\n", key.c_str(), value.c_str()); + } +} + +void ShellContext::scan(const string & db, + const string & start_key, + const string & end_key, + const string & limit) { + vector > kvs; + if (clientProxy_->scan(db, start_key, end_key, limit, kvs)) { + for(unsigned int i = 0; i < kvs.size(); ++i) { + printf("%d (%s, %s)\n", i, kvs[i].first.c_str(), kvs[i].second.c_str()); + } + } +} + +void ShellContext::run(void) { + while(!exit_) { + pShellState_->run(this); + } +} + +ShellContext::ShellContext(int argc, char ** argv) : + pShellState_(ShellStateStart::getInstance()), + exit_(false), + argc_(argc), + argv_(argv), + port_(-1), + clientProxy_() { +} + + diff --git a/tools/shell/ShellContext.h b/tools/shell/ShellContext.h new file mode 100644 index 00000000..95805ad0 --- /dev/null +++ b/tools/shell/ShellContext.h @@ -0,0 +1,51 @@ +#ifndef TOOLS_SHELL_SHELLCONTEXT +#define TOOLS_SHELL_SHELLCONTEXT + +#include +#include +#include +#include + +#include "DB.h" +#include "DBClientProxy.h" + +class ShellState; + +class ShellContext : private boost::noncopyable { + public: + void changeState(ShellState * pState); + + void stop(void); + + bool ParseInput(void); + + void connect(void); + + void get(const std::string & db, + const std::string & key); + + void put(const std::string & db, + const std::string & key, + const std::string & value); + + void scan(const std::string & db, + const std::string & start_key, + const std::string & end_key, + const std::string & limit); + + void create(const std::string & db); + + void run(void); + + ShellContext(int argc, char ** argv); + + private: + ShellState * pShellState_; + bool exit_; + int argc_; + char ** argv_; + int port_; + boost::shared_ptr clientProxy_; +}; + +#endif diff --git a/tools/shell/ShellState.cpp b/tools/shell/ShellState.cpp new file mode 100644 index 00000000..057a337a --- /dev/null +++ b/tools/shell/ShellState.cpp @@ -0,0 +1,139 @@ +#include +#include +#include +#include + +#include "ShellState.h" +#include "ShellContext.h" +#include "transport/TTransportException.h" + +using namespace std; + +using namespace apache::thrift::transport; + +const char * PMT = ">> "; + + +void ShellStateStart::run(ShellContext * c) { + if(!c->ParseInput()) { + c->changeState(ShellStateStop::getInstance()); + } else { + c->changeState(ShellStateConnecting::getInstance()); + } +} + + +void ShellStateStop::run(ShellContext * c) { + c->stop(); +} + +void ShellStateConnecting::run(ShellContext * c) { + try { + c->connect(); + } catch (const TTransportException & e) { + cout << e.what() << endl; + c->changeState(ShellStateStop::getInstance()); + return; + } + + c->changeState(ShellStateConnected::getInstance()); +} + +void ShellStateConnected::unknownCmd(void) { + cout << "Unknown command!" << endl; + cout << "Use help to list all available commands" << endl; +} + +void ShellStateConnected::helpMsg(void) { + cout << "Currently supported commands:" << endl; + cout << "create db" << endl; + cout << "get db key" << endl; + cout << "scan db start_key end_key limit" << endl; + cout << "put db key value" << endl; + cout << "exit/quit" << endl; +} + +void ShellStateConnected::handleConError(ShellContext * c) { + cout << "Connection down" << endl; + cout << "Reconnect ? (y/n) :" << endl; + string s; + while(getline(cin, s)) { + if("y" == s) { + c->changeState(ShellStateConnecting::getInstance()); + break; + } else if("n" == s) { + c->changeState(ShellStateStop::getInstance()); + break; + } else { + cout << "Reconnect ? (y/n) :" << endl; + } + } +} + +void ShellStateConnected::run(ShellContext * c) { + string line; + cout << PMT; + getline(cin, line); + istringstream is(line); + vector params; + string param; + while(is >> param) { + params.push_back(param); + } + + // empty input line + if(params.empty()) + return; + + if("quit" == params[0] || "exit" == params[0]) { + c->changeState(ShellStateStop::getInstance()); + } else if("get" == params[0]) { + if(params.size() == 3) { + try { + c->get(params[1], params[2]); + } catch (const TTransportException & e) { + cout << e.what() << endl; + handleConError(c); + } + } else { + unknownCmd(); + } + } else if("create" == params[0]) { + if(params.size() == 2) { + try { + c->create(params[1]); + } catch (const TTransportException & e) { + cout << e.what() << endl; + handleConError(c); + } + } else { + unknownCmd(); + } + }else if("put" == params[0]) { + if(params.size() == 4) { + try { + c->put(params[1], params[2], params[3]); + } catch (const TTransportException & e) { + cout << e.what() << endl; + handleConError(c); + } + } else { + unknownCmd(); + } + } else if("scan" == params[0]) { + if(params.size() == 5) { + try { + c->scan(params[1], params[2], params[3], params[4]); + } catch (const TTransportException & e) { + cout << e.what() << endl; + handleConError(c); + } + } else { + unknownCmd(); + } + } else if("help" == params[0]) { + helpMsg(); + } else { + unknownCmd(); + } +} diff --git a/tools/shell/ShellState.h b/tools/shell/ShellState.h new file mode 100644 index 00000000..6167d55b --- /dev/null +++ b/tools/shell/ShellState.h @@ -0,0 +1,87 @@ + +#ifndef TOOLS_SHELL_SHELLSTATE +#define TOOLS_SHELL_SHELLSTATE + +class ShellContext; + +/* + * Currently, there are four types of state in total + * 1. start state: the first state the program enters + * 2. connecting state: the program try to connnect to a leveldb server, whose + * previous states could be "start" or "connected" states + * 3. connected states: the program has already connected to a server, and is + * processing user commands + * 4. stop state: the last state the program enters, do some cleanning up things + */ + +class ShellState { + public: + virtual void run(ShellContext *) = 0; + virtual ~ShellState() {} +}; + + +class ShellStateStart : public ShellState { + public: + static ShellStateStart * getInstance(void) { + static ShellStateStart instance; + return &instance; + } + + virtual void run(ShellContext *); + + private: + ShellStateStart() {} + virtual ~ShellStateStart() {} +}; + +class ShellStateStop : public ShellState { + public: + static ShellStateStop * getInstance(void) { + static ShellStateStop instance; + return &instance; + } + + virtual void run(ShellContext *); + + private: + ShellStateStop() {} + virtual ~ShellStateStop() {} + +}; + +class ShellStateConnecting : public ShellState { + public: + static ShellStateConnecting * getInstance(void) { + static ShellStateConnecting instance; + return &instance; + } + + virtual void run(ShellContext *); + + private: + ShellStateConnecting() {} + virtual ~ShellStateConnecting() {} + +}; + +class ShellStateConnected : public ShellState { + public: + static ShellStateConnected * getInstance(void) { + static ShellStateConnected instance; + return &instance; + } + + virtual void run(ShellContext *); + + private: + ShellStateConnected() {} + virtual ~ShellStateConnected() {} + + void unknownCmd(); + void handleConError(ShellContext *); + void helpMsg(); +}; + +#endif + diff --git a/tools/shell/test/DBClientProxyTest.cpp b/tools/shell/test/DBClientProxyTest.cpp new file mode 100644 index 00000000..27e1c856 --- /dev/null +++ b/tools/shell/test/DBClientProxyTest.cpp @@ -0,0 +1,182 @@ +/** + * Tests for DBClientProxy class for leveldb + * @author Bo Liu (newpoo.liu@gmail.com) + * Copyright 2012 Facebook + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "server_options.h" + + +#include "../DBClientProxy.h" +using namespace leveldb; + + +using namespace apache::thrift; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; +using boost::shared_ptr; +using namespace Tleveldb; +using namespace std; + + + +extern "C" void startServer(int argc, char**argv); +extern "C" void stopServer(int port); +extern ServerOptions server_options; + +static const string db1("db1"); + + +static void testDBClientProxy(DBClientProxy & dbcp) { + bool flag; + const int NOK = 100; + const int BUFSIZE = 16; + int testcase = 0; + + vector keys, values; + vector > kvs, correctKvs; + string k, v; + + for(int i = 0; i < NOK; ++i) { + char bufKey[BUFSIZE]; + char bufValue[BUFSIZE]; + snprintf(bufKey, BUFSIZE, "key%d", i); + snprintf(bufValue, BUFSIZE, "value%d", i); + keys.push_back(bufKey); + values.push_back(bufValue); + correctKvs.push_back((make_pair(string(bufKey), string(bufValue)))); + } + + sort(correctKvs.begin(), correctKvs.end()); + + + // can not do get(), put(), scan() or create() before connected. + flag = dbcp.get(db1, keys[0], v); + ASSERT_TRUE(false == flag); + printf("\033[01;40;32mTEST CASE %d passed\033[01;40;37m\n", ++testcase); + flag = dbcp.put(db1, keys[0], keys[1]); + ASSERT_TRUE(false == flag); + printf("\033[01;40;32mTEST CASE %d passed\033[01;40;37m\n", ++testcase); + flag = dbcp.scan(db1, "a", "w", "100", kvs); + ASSERT_TRUE(false == flag); + printf("\033[01;40;32mTEST CASE %d passed\033[01;40;37m\n", ++testcase); + flag = dbcp.create(db1); + ASSERT_TRUE(false == flag); + printf("\033[01;40;32mTEST CASE %d passed\033[01;40;37m\n", ++testcase); + + dbcp.connect(); + + // create a database + flag = dbcp.create(db1); + ASSERT_TRUE(true == flag); + printf("\033[01;40;32mTEST CASE %d passed\033[01;40;37m\n", ++testcase); + + // no such key + flag = dbcp.get(db1, keys[0], v); + ASSERT_TRUE(false == flag); + printf("\033[01;40;32mTEST CASE %d passed\033[01;40;37m\n", ++testcase); + + + // scan() success with empty returned key-value pairs + kvs.clear(); + flag = dbcp.scan(db1, "a", "w", "100", kvs); + ASSERT_TRUE(true == flag); + ASSERT_TRUE(kvs.empty()); + printf("\033[01;40;32mTEST CASE %d passed\033[01;40;37m\n", ++testcase); + + + // put() + for(int i = 0; i < NOK; ++i) { + flag = dbcp.put(db1, keys[i], values[i]); + ASSERT_TRUE(true == flag); + } + printf("\033[01;40;32mTEST CASE %d passed\033[01;40;37m\n", ++testcase); + + + // scan all of key-value pairs + kvs.clear(); + flag = dbcp.scan(db1, "a", "w", "100", kvs); + ASSERT_TRUE(true == flag); + ASSERT_TRUE(kvs == correctKvs); + printf("\033[01;40;32mTEST CASE %d passed\033[01;40;37m\n", ++testcase); + + + // scan the first 20 key-value pairs + { + kvs.clear(); + flag = dbcp.scan(db1, "a", "w", "20", kvs); + ASSERT_TRUE(true == flag); + vector > tkvs(correctKvs.begin(), correctKvs.begin() + 20); + ASSERT_TRUE(kvs == tkvs); + printf("\033[01;40;32mTEST CASE %d passed\033[01;40;37m\n", ++testcase); + } + + // scan key[10] to key[50] + { + kvs.clear(); + flag = dbcp.scan(db1, correctKvs[10].first, correctKvs[50].first, "100", kvs); + ASSERT_TRUE(true == flag); + + vector > tkvs(correctKvs.begin() + 10, correctKvs.begin() + 50); + ASSERT_TRUE(kvs == tkvs); + printf("\033[01;40;32mTEST CASE %d passed\033[01;40;37m\n", ++testcase); + } + + // scan "key10" to "key40" by limit constraint + { + kvs.clear(); + flag = dbcp.scan(db1, correctKvs[10].first.c_str(), "w", "30", kvs); + ASSERT_TRUE(true == flag); + vector > tkvs(correctKvs.begin() + 10, correctKvs.begin() + 40); + ASSERT_TRUE(kvs == tkvs); + printf("\033[01;40;32mTEST CASE %d passed\033[01;40;37m\n", ++testcase); + } + + + // get() + flag = dbcp.get(db1, "unknownKey", v); + ASSERT_TRUE(false == flag); + printf("\033[01;40;32mTEST CASE %d passed\033[01;40;37m\n", ++testcase); + + flag = dbcp.get(db1, keys[0], v); + ASSERT_TRUE(true == flag); + ASSERT_TRUE(v == values[0]); + printf("\033[01;40;32mTEST CASE %d passed\033[01;40;37m\n", ++testcase); +} + + + +static void cleanupDir(std::string dir) { + // remove old data, if any + char* cleanup = new char[100]; + snprintf(cleanup, 100, "rm -rf %s", dir.c_str()); + system(cleanup); +} + +int main(int argc, char **argv) { + // create a server + startServer(argc, argv); + printf("Server thread created.\n"); + + // give some time to the server to initialize itself + while (server_options.getPort() == 0) { + sleep(1); + } + + cleanupDir(server_options.getDataDirectory(db1)); + + DBClientProxy dbcp("localhost", server_options.getPort()); + testDBClientProxy(dbcp); +} + diff --git a/tools/sst_dump.cc b/tools/sst_dump.cc new file mode 100644 index 00000000..7aeb3f5a --- /dev/null +++ b/tools/sst_dump.cc @@ -0,0 +1,165 @@ +#include "leveldb/table.h" + +#include +#include +#include + +#include "db/dbformat.h" +#include "db/memtable.h" +#include "db/write_batch_internal.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "leveldb/table_builder.h" +#include "table/block.h" +#include "table/block_builder.h" +#include "table/format.h" +#include "util/random.h" +#include "util/testharness.h" +#include "util/testutil.h" + +namespace leveldb { + +class SstFileReader { +public: + SstFileReader(std::string file_name, + bool verify_checksum = false, + bool output_hex = false); + Status ReadSequential(bool print_kv, uint64_t read_num = -1); + + uint64_t GetReadNumber() { return read_num_; } + +private: + std::string file_name_; + uint64_t read_num_; + bool verify_checksum_; + bool output_hex_; +}; + +SstFileReader::SstFileReader(std::string file_path, + bool verify_checksum, + bool output_hex) + :file_name_(file_path), read_num_(0), verify_checksum_(verify_checksum), + output_hex_(output_hex) { +} + +Status SstFileReader::ReadSequential(bool print_kv, uint64_t read_num) +{ + unique_ptr
table; + Options table_options; + unique_ptr file; + Status s = table_options.env->NewRandomAccessFile(file_name_, &file); + if(!s.ok()) { + return s; + } + uint64_t file_size; + table_options.env->GetFileSize(file_name_, &file_size); + s = Table::Open(table_options, std::move(file), file_size, &table); + if(!s.ok()) { + return s; + } + + Iterator* iter = table->NewIterator(ReadOptions(verify_checksum_, false)); + uint64_t i = 0; + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + Slice key = iter->key(); + Slice value = iter->value(); + ++i; + if (read_num > 0 && i > read_num) + break; + if (print_kv) { + fprintf(stdout, "%s ==> %s\n", + key.ToString(output_hex_).c_str(), + value.ToString(output_hex_).c_str()); + } + } + + read_num_ += i; + + Status ret = iter->status(); + delete iter; + return ret; +} + +} // namespace leveldb + +static void print_help() { + fprintf(stderr, + "sst_dump [--command=check|scan] [--verify_checksum] " + "--file=data_dir_OR_sst_file" + " [--output_hex]" + " [--read_num=NUM]\n"); +} + +int main(int argc, char** argv) { + + const char* dir_or_file = NULL; + uint64_t read_num = -1; + std::string command; + + char junk; + uint64_t n; + bool verify_checksum = false; + bool output_hex = false; + for (int i = 1; i < argc; i++) + { + if (strncmp(argv[i], "--file=", 7) == 0) { + dir_or_file = argv[i] + 7; + } else if (strcmp(argv[i], "--output_hex") == 0) { + output_hex = true; + } else if (sscanf(argv[i], "--read_num=%ld%c", &n, &junk) == 1) { + read_num = n; + } else if (strcmp(argv[i], "--verify_checksum") == 0) { + verify_checksum = true; + } else if (strncmp(argv[i], "--command=", 10) == 0) { + command = argv[i] + 10; + } else { + print_help(); + exit(1); + } + } + + if(dir_or_file == NULL) { + print_help(); + exit(1); + } + + std::vector filenames; + leveldb::Env* env = leveldb::Env::Default(); + leveldb::Status st = env->GetChildren(dir_or_file, &filenames); + bool dir = true; + if (!st.ok()) { + filenames.clear(); + filenames.push_back(dir_or_file); + dir = false; + } + + uint64_t total_read = 0; + for (size_t i = 0; i < filenames.size(); i++) { + std::string filename = filenames.at(i); + if (filename.length() <= 4 || + filename.rfind(".sst") != filename.length() - 4) { + //ignore + continue; + } + if(dir) { + filename = std::string(dir_or_file) + "//" + filename; + } + leveldb::SstFileReader reader(filename, verify_checksum, + output_hex); + leveldb::Status st; + // scan all files in give file path. + if (command == "" || command == "scan" || command == "check") { + st = reader.ReadSequential(command != "check", + read_num > 0 ? (read_num - total_read) : read_num); + if (!st.ok()) { + fprintf(stderr, "%s: %s\n", filename.c_str(), + st.ToString().c_str()); + } + total_read += reader.GetReadNumber(); + if (read_num > 0 && total_read > read_num) { + break; + } + } + } +} diff --git a/util/arena.cc b/util/arena.cc new file mode 100644 index 00000000..a339f405 --- /dev/null +++ b/util/arena.cc @@ -0,0 +1,68 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/arena.h" +#include + +namespace leveldb { + +static const int kBlockSize = 4096; + +Arena::Arena() { + blocks_memory_ = 0; + alloc_ptr_ = nullptr; // First allocation will allocate a block + alloc_bytes_remaining_ = 0; +} + +Arena::~Arena() { + for (size_t i = 0; i < blocks_.size(); i++) { + delete[] blocks_[i]; + } +} + +char* Arena::AllocateFallback(size_t bytes) { + if (bytes > kBlockSize / 4) { + // Object is more than a quarter of our block size. Allocate it separately + // to avoid wasting too much space in leftover bytes. + char* result = AllocateNewBlock(bytes); + return result; + } + + // We waste the remaining space in the current block. + alloc_ptr_ = AllocateNewBlock(kBlockSize); + alloc_bytes_remaining_ = kBlockSize; + + char* result = alloc_ptr_; + alloc_ptr_ += bytes; + alloc_bytes_remaining_ -= bytes; + return result; +} + +char* Arena::AllocateAligned(size_t bytes) { + const int align = sizeof(void*); // We'll align to pointer size + assert((align & (align-1)) == 0); // Pointer size should be a power of 2 + size_t current_mod = reinterpret_cast(alloc_ptr_) & (align-1); + size_t slop = (current_mod == 0 ? 0 : align - current_mod); + size_t needed = bytes + slop; + char* result; + if (needed <= alloc_bytes_remaining_) { + result = alloc_ptr_ + slop; + alloc_ptr_ += needed; + alloc_bytes_remaining_ -= needed; + } else { + // AllocateFallback always returned aligned memory + result = AllocateFallback(bytes); + } + assert((reinterpret_cast(result) & (align-1)) == 0); + return result; +} + +char* Arena::AllocateNewBlock(size_t block_bytes) { + char* result = new char[block_bytes]; + blocks_memory_ += block_bytes; + blocks_.push_back(result); + return result; +} + +} // namespace leveldb diff --git a/util/arena.h b/util/arena.h new file mode 100644 index 00000000..8f7dde22 --- /dev/null +++ b/util/arena.h @@ -0,0 +1,68 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_ARENA_H_ +#define STORAGE_LEVELDB_UTIL_ARENA_H_ + +#include +#include +#include +#include + +namespace leveldb { + +class Arena { + public: + Arena(); + ~Arena(); + + // Return a pointer to a newly allocated memory block of "bytes" bytes. + char* Allocate(size_t bytes); + + // Allocate memory with the normal alignment guarantees provided by malloc + char* AllocateAligned(size_t bytes); + + // Returns an estimate of the total memory usage of data allocated + // by the arena (including space allocated but not yet used for user + // allocations). + size_t MemoryUsage() const { + return blocks_memory_ + blocks_.capacity() * sizeof(char*); + } + + private: + char* AllocateFallback(size_t bytes); + char* AllocateNewBlock(size_t block_bytes); + + // Allocation state + char* alloc_ptr_; + size_t alloc_bytes_remaining_; + + // Array of new[] allocated memory blocks + std::vector blocks_; + + // Bytes of memory in blocks allocated so far + size_t blocks_memory_; + + // No copying allowed + Arena(const Arena&); + void operator=(const Arena&); +}; + +inline char* Arena::Allocate(size_t bytes) { + // The semantics of what to return are a bit messy if we allow + // 0-byte allocations, so we disallow them here (we don't need + // them for our internal use). + assert(bytes > 0); + if (bytes <= alloc_bytes_remaining_) { + char* result = alloc_ptr_; + alloc_ptr_ += bytes; + alloc_bytes_remaining_ -= bytes; + return result; + } + return AllocateFallback(bytes); +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_ARENA_H_ diff --git a/util/arena_test.cc b/util/arena_test.cc new file mode 100644 index 00000000..d5c33d75 --- /dev/null +++ b/util/arena_test.cc @@ -0,0 +1,68 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/arena.h" + +#include "util/random.h" +#include "util/testharness.h" + +namespace leveldb { + +class ArenaTest { }; + +TEST(ArenaTest, Empty) { + Arena arena; +} + +TEST(ArenaTest, Simple) { + std::vector > allocated; + Arena arena; + const int N = 100000; + size_t bytes = 0; + Random rnd(301); + for (int i = 0; i < N; i++) { + size_t s; + if (i % (N / 10) == 0) { + s = i; + } else { + s = rnd.OneIn(4000) ? rnd.Uniform(6000) : + (rnd.OneIn(10) ? rnd.Uniform(100) : rnd.Uniform(20)); + } + if (s == 0) { + // Our arena disallows size 0 allocations. + s = 1; + } + char* r; + if (rnd.OneIn(10)) { + r = arena.AllocateAligned(s); + } else { + r = arena.Allocate(s); + } + + for (unsigned int b = 0; b < s; b++) { + // Fill the "i"th allocation with a known bit pattern + r[b] = i % 256; + } + bytes += s; + allocated.push_back(std::make_pair(s, r)); + ASSERT_GE(arena.MemoryUsage(), bytes); + if (i > N/10) { + ASSERT_LE(arena.MemoryUsage(), bytes * 1.10); + } + } + for (unsigned int i = 0; i < allocated.size(); i++) { + size_t num_bytes = allocated[i].first; + const char* p = allocated[i].second; + for (unsigned int b = 0; b < num_bytes; b++) { + // Check the "i"th allocation for the known bit pattern + ASSERT_EQ(int(p[b]) & 0xff, (int)(i % 256)); + } + } +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/util/auto_roll_logger.cc b/util/auto_roll_logger.cc new file mode 100644 index 00000000..20903d05 --- /dev/null +++ b/util/auto_roll_logger.cc @@ -0,0 +1,93 @@ +#include "util/auto_roll_logger.h" + +using namespace std; + +namespace leveldb { + +// -- AutoRollLogger +Status AutoRollLogger::ResetLogger() { + status_ = env_->NewLogger(log_fname_, &logger_); + + if (!status_.ok()) { + return status_; + } + + if (logger_->GetLogFileSize() == + (size_t)Logger::DO_NOT_SUPPORT_GET_LOG_FILE_SIZE) { + status_ = Status::NotSupported( + "The underlying logger doesn't support GetLogFileSize()"); + } + if (status_.ok()) { + cached_now = static_cast(env_->NowMicros() * 1e-6); + ctime_ = cached_now; + cached_now_access_count = 0; + } + + return status_; +} + +void AutoRollLogger::RollLogFile() { + std::string old_fname = OldInfoLogFileName( + dbname_, env_->NowMicros(), db_absolute_path_, db_log_dir_); + env_->RenameFile(log_fname_, old_fname); +} + +void AutoRollLogger::Logv(const char* format, va_list ap) { + assert(GetStatus().ok()); + + if (kLogFileTimeToRoll > 0 && LogExpired()) { + RollLogFile(); + ResetLogger(); + } + + logger_->Logv(format, ap); + + if (kMaxLogFileSize > 0 && logger_->GetLogFileSize() > kMaxLogFileSize) { + RollLogFile(); + ResetLogger(); + } +} + +bool AutoRollLogger::LogExpired() { + if (cached_now_access_count >= call_NowMicros_every_N_records_) { + cached_now = static_cast(env_->NowMicros() * 1e-6); + cached_now_access_count = 0; + } + + ++cached_now_access_count; + return cached_now >= ctime_ + kLogFileTimeToRoll; +} + +Status CreateLoggerFromOptions( + const std::string& dbname, + const std::string& db_log_dir, + Env* env, + const Options& options, + std::shared_ptr* logger) { + std::string db_absolute_path; + env->GetAbsolutePath(dbname, &db_absolute_path); + std::string fname = InfoLogFileName(dbname, db_absolute_path, db_log_dir); + + // Currently we only support roll by time-to-roll and log size + if (options.log_file_time_to_roll > 0 || options.max_log_file_size > 0) { + AutoRollLogger* result = new AutoRollLogger( + env, dbname, db_log_dir, + options.max_log_file_size, + options.log_file_time_to_roll); + Status s = result->GetStatus(); + if (!s.ok()) { + delete result; + } else { + logger->reset(result); + } + return s; + } else { + // Open a log file in the same directory as the db + env->CreateDir(dbname); // In case it does not exist + env->RenameFile(fname, OldInfoLogFileName(dbname, env->NowMicros(), + db_absolute_path, db_log_dir)); + return env->NewLogger(fname, logger); + } +} + +} // namespace leveldb diff --git a/util/auto_roll_logger.h b/util/auto_roll_logger.h new file mode 100644 index 00000000..e6a774a5 --- /dev/null +++ b/util/auto_roll_logger.h @@ -0,0 +1,90 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Logger implementation that can be shared by all environments +// where enough posix functionality is available. + +#ifndef STORAGE_LEVELDB_UTIL_AUTO_ROLL_LOGGER_H +#define STORAGE_LEVELDB_UTIL_AUTO_ROLL_LOGGER_H + +#include "util/posix_logger.h" +#include "db/filename.h" + +namespace leveldb { + +// Rolls the log file by size and/or time +class AutoRollLogger : public Logger { + public: + AutoRollLogger(Env* env, const std::string& dbname, + const std::string& db_log_dir, + size_t log_max_size, + size_t log_file_time_to_roll): + dbname_(dbname), + db_log_dir_(db_log_dir), + env_(env), + status_(Status::OK()), + kMaxLogFileSize(log_max_size), + kLogFileTimeToRoll(log_file_time_to_roll), + cached_now(static_cast(env_->NowMicros() * 1e-6)), + ctime_(cached_now), + cached_now_access_count(0), + call_NowMicros_every_N_records_(100) { + env->GetAbsolutePath(dbname, &db_absolute_path_); + log_fname_ = InfoLogFileName(dbname_, db_absolute_path_, db_log_dir_); + RollLogFile(); + ResetLogger(); + } + + void Logv(const char* format, va_list ap); + + // check if the logger has encountered any problem. + Status GetStatus() { + return status_; + } + + size_t GetLogFileSize() const { + return logger_->GetLogFileSize(); + } + + virtual ~AutoRollLogger() { + } + + void SetCallNowMicrosEveryNRecords(uint64_t call_NowMicros_every_N_records) { + call_NowMicros_every_N_records_ = call_NowMicros_every_N_records; + } + + private: + + bool LogExpired(); + Status ResetLogger(); + void RollLogFile(); + + std::string log_fname_; // Current active info log's file name. + std::string dbname_; + std::string db_log_dir_; + std::string db_absolute_path_; + Env* env_; + std::shared_ptr logger_; + // current status of the logger + Status status_; + const size_t kMaxLogFileSize; + const size_t kLogFileTimeToRoll; + // to avoid frequent env->NowMicros() calls, we cached the current time + uint64_t cached_now; + uint64_t ctime_; + uint64_t cached_now_access_count; + uint64_t call_NowMicros_every_N_records_; +}; + +// Facade to craete logger automatically +Status CreateLoggerFromOptions( + const std::string& dbname, + const std::string& db_log_dir, + Env* env, + const Options& options, + std::shared_ptr* logger); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_AUTO_ROLL_LOGGER_H diff --git a/util/auto_roll_logger_test.cc b/util/auto_roll_logger_test.cc new file mode 100755 index 00000000..4b12fb85 --- /dev/null +++ b/util/auto_roll_logger_test.cc @@ -0,0 +1,263 @@ +// Copyright (c) 2012 Facebook. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include "util/testharness.h" +#include "util/auto_roll_logger.h" +#include "leveldb/db.h" +#include +#include +#include + +using namespace std; + +namespace leveldb { + +class AutoRollLoggerTest { + public: + static void InitTestDb() { + string deleteCmd = "rm -rf " + kTestDir; + ASSERT_TRUE(system(deleteCmd.c_str()) == 0); + Env::Default()->CreateDir(kTestDir); + } + + void RollLogFileBySizeTest(AutoRollLogger* logger, + size_t log_max_size, + const string& log_message); + uint64_t RollLogFileByTimeTest(AutoRollLogger* logger, + size_t time, + const string& log_message); + + static const string kSampleMessage; + static const string kTestDir; + static const string kLogFile; + static Env* env; +}; + +const string AutoRollLoggerTest::kSampleMessage( + "this is the message to be written to the log file!!"); +const string AutoRollLoggerTest::kTestDir( + test::TmpDir() + "/db_log_test"); +const string AutoRollLoggerTest::kLogFile( + test::TmpDir() + "/db_log_test/LOG"); +Env* AutoRollLoggerTest::env = Env::Default(); + +// In this test we only want to Log some simple log message with +// no format. LogMessage() provides such a simple interface and +// avoids the [format-security] warning which occurs when you +// call Log(logger, log_message) directly. +void LogMessage(Logger* logger, const char* message) { + Log(logger, "%s", message); +} + +void GetFileCreateTime(const std::string& fname, uint64_t* file_ctime) { + struct stat s; + if (stat(fname.c_str(), &s) != 0) { + *file_ctime = (uint64_t)0; + } + *file_ctime = static_cast(s.st_ctime); +} + +void AutoRollLoggerTest::RollLogFileBySizeTest(AutoRollLogger* logger, + size_t log_max_size, + const string& log_message) { + // measure the size of each message, which is supposed + // to be equal or greater than log_message.size() + LogMessage(logger, log_message.c_str()); + size_t message_size = logger->GetLogFileSize(); + size_t current_log_size = message_size; + + // Test the cases when the log file will not be rolled. + while (current_log_size + message_size < log_max_size) { + LogMessage(logger, log_message.c_str()); + current_log_size += message_size; + ASSERT_EQ(current_log_size, logger->GetLogFileSize()); + } + + // Now the log file will be rolled + LogMessage(logger, log_message.c_str()); + ASSERT_TRUE(0 == logger->GetLogFileSize()); +} + +uint64_t AutoRollLoggerTest::RollLogFileByTimeTest( + AutoRollLogger* logger, size_t time, const string& log_message) { + uint64_t expected_create_time; + uint64_t actual_create_time; + uint64_t total_log_size; + ASSERT_OK(env->GetFileSize(kLogFile, &total_log_size)); + GetFileCreateTime(kLogFile, &expected_create_time); + logger->SetCallNowMicrosEveryNRecords(0); + + // -- Write to the log for several times, which is supposed + // to be finished before time. + for (int i = 0; i < 10; ++i) { + LogMessage(logger, log_message.c_str()); + ASSERT_OK(logger->GetStatus()); + // Make sure we always write to the same log file (by + // checking the create time); + GetFileCreateTime(kLogFile, &actual_create_time); + + // Also make sure the log size is increasing. + ASSERT_EQ(expected_create_time, actual_create_time); + ASSERT_GT(logger->GetLogFileSize(), total_log_size); + total_log_size = logger->GetLogFileSize(); + } + + // -- Make the log file expire + sleep(time); + LogMessage(logger, log_message.c_str()); + + // At this time, the new log file should be created. + GetFileCreateTime(kLogFile, &actual_create_time); + ASSERT_GT(actual_create_time, expected_create_time); + ASSERT_LT(logger->GetLogFileSize(), total_log_size); + expected_create_time = actual_create_time; + + return expected_create_time; +} + +TEST(AutoRollLoggerTest, RollLogFileBySize) { + InitTestDb(); + size_t log_max_size = 1024 * 5; + + AutoRollLogger* logger = new AutoRollLogger( + Env::Default(), kTestDir, "", log_max_size, 0); + + RollLogFileBySizeTest(logger, log_max_size, + kSampleMessage + ":RollLogFileBySize"); + + delete logger; +} + +TEST(AutoRollLoggerTest, RollLogFileByTime) { + size_t time = 1; + size_t log_size = 1024 * 5; + + InitTestDb(); + // -- Test the existence of file during the server restart. + ASSERT_TRUE(!env->FileExists(kLogFile)); + AutoRollLogger* logger = new AutoRollLogger( + Env::Default(), kTestDir, "", log_size, 1); + ASSERT_TRUE(env->FileExists(kLogFile)); + + RollLogFileByTimeTest(logger, time, kSampleMessage + ":RollLogFileByTime"); + + delete logger; +} + +TEST(AutoRollLoggerTest, + OpenLogFilesMultipleTimesWithOptionLog_max_size) { + // If only 'log_max_size' options is specified, then every time + // when leveldb is restarted, a new empty log file will be created. + InitTestDb(); + // WORKAROUND: + // avoid complier's complaint of "comparison between signed + // and unsigned integer expressions" because literal 0 is + // treated as "singed". + size_t kZero = 0; + size_t log_size = 1024; + + AutoRollLogger* logger = new AutoRollLogger( + Env::Default(), kTestDir, "", log_size, 0); + + LogMessage(logger, kSampleMessage.c_str()); + ASSERT_GT(logger->GetLogFileSize(), kZero); + delete logger; + + // reopens the log file and an empty log file will be created. + logger = new AutoRollLogger( + Env::Default(), kTestDir, "", log_size, 0); + ASSERT_EQ(logger->GetLogFileSize(), kZero); + delete logger; +} + +TEST(AutoRollLoggerTest, CompositeRollByTimeAndSizeLogger) { + size_t time = 1, log_max_size = 1024 * 5; + + InitTestDb(); + + AutoRollLogger* logger = new AutoRollLogger( + Env::Default(), kTestDir, "", log_max_size, time); + + // Test the ability to roll by size + RollLogFileBySizeTest( + logger, log_max_size, + kSampleMessage + ":CompositeRollByTimeAndSizeLogger"); + + // Test the ability to roll by Time + RollLogFileByTimeTest( logger, time, + kSampleMessage + ":CompositeRollByTimeAndSizeLogger"); +} + +TEST(AutoRollLoggerTest, CreateLoggerFromOptions) { + Options options; + shared_ptr logger; + + // Normal logger + ASSERT_OK(CreateLoggerFromOptions(kTestDir, "", env, options, &logger)); + ASSERT_TRUE(dynamic_cast(logger.get())); + + // Only roll by size + InitTestDb(); + options.max_log_file_size = 1024; + ASSERT_OK(CreateLoggerFromOptions(kTestDir, "", env, options, &logger)); + AutoRollLogger* auto_roll_logger = + dynamic_cast(logger.get()); + ASSERT_TRUE(auto_roll_logger); + RollLogFileBySizeTest( + auto_roll_logger, options.max_log_file_size, + kSampleMessage + ":CreateLoggerFromOptions - size"); + + // Only roll by Time + InitTestDb(); + options.max_log_file_size = 0; + options.log_file_time_to_roll = 1; + ASSERT_OK(CreateLoggerFromOptions(kTestDir, "", env, options, &logger)); + auto_roll_logger = + dynamic_cast(logger.get()); + RollLogFileByTimeTest( + auto_roll_logger, options.log_file_time_to_roll, + kSampleMessage + ":CreateLoggerFromOptions - time"); + + // roll by both Time and size + InitTestDb(); + options.max_log_file_size = 1024 * 5; + options.log_file_time_to_roll = 1; + ASSERT_OK(CreateLoggerFromOptions(kTestDir, "", env, options, &logger)); + auto_roll_logger = + dynamic_cast(logger.get()); + RollLogFileBySizeTest( + auto_roll_logger, options.max_log_file_size, + kSampleMessage + ":CreateLoggerFromOptions - both"); + RollLogFileByTimeTest( + auto_roll_logger, options.log_file_time_to_roll, + kSampleMessage + ":CreateLoggerFromOptions - both"); +} + +int OldLogFileCount(const string& dir) { + std::vector files; + Env::Default()->GetChildren(dir, &files); + int log_file_count = 0; + + for (std::vector::iterator it = files.begin(); + it != files.end(); ++it) { + uint64_t create_time; + FileType type; + if (!ParseFileName(*it, &create_time, &type)) { + continue; + } + if (type == kInfoLogFile && create_time > 0) { + ++log_file_count; + } + } + + return log_file_count; +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/util/bloom.cc b/util/bloom.cc new file mode 100644 index 00000000..d5ad9f21 --- /dev/null +++ b/util/bloom.cc @@ -0,0 +1,106 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/filter_policy.h" + +#include "leveldb/slice.h" +#include "util/hash.h" + +namespace leveldb { + +namespace { +static uint32_t BloomHash(const Slice& key) { + return Hash(key.data(), key.size(), 0xbc9f1d34); +} + +class BloomFilterPolicy : public FilterPolicy { + private: + size_t bits_per_key_; + size_t k_; + uint32_t (*hash_func_)(const Slice& key); + + void initialize() { + // We intentionally round down to reduce probing cost a little bit + k_ = static_cast(bits_per_key_ * 0.69); // 0.69 =~ ln(2) + if (k_ < 1) k_ = 1; + if (k_ > 30) k_ = 30; + } + + public: + explicit BloomFilterPolicy(int bits_per_key, + uint32_t (*hash_func)(const Slice& key)) + : bits_per_key_(bits_per_key), hash_func_(hash_func) { + initialize(); + } + explicit BloomFilterPolicy(int bits_per_key) + : bits_per_key_(bits_per_key) { + hash_func_ = BloomHash; + initialize(); + } + + virtual const char* Name() const { + return "leveldb.BuiltinBloomFilter"; + } + + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const { + // Compute bloom filter size (in both bits and bytes) + size_t bits = n * bits_per_key_; + + // For small n, we can see a very high false positive rate. Fix it + // by enforcing a minimum bloom filter length. + if (bits < 64) bits = 64; + + size_t bytes = (bits + 7) / 8; + bits = bytes * 8; + + const size_t init_size = dst->size(); + dst->resize(init_size + bytes, 0); + dst->push_back(static_cast(k_)); // Remember # of probes in filter + char* array = &(*dst)[init_size]; + for (size_t i = 0; i < (size_t)n; i++) { + // Use double-hashing to generate a sequence of hash values. + // See analysis in [Kirsch,Mitzenmacher 2006]. + uint32_t h = hash_func_(keys[i]); + const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits + for (size_t j = 0; j < k_; j++) { + const uint32_t bitpos = h % bits; + array[bitpos/8] |= (1 << (bitpos % 8)); + h += delta; + } + } + } + + virtual bool KeyMayMatch(const Slice& key, const Slice& bloom_filter) const { + const size_t len = bloom_filter.size(); + if (len < 2) return false; + + const char* array = bloom_filter.data(); + const size_t bits = (len - 1) * 8; + + // Use the encoded k so that we can read filters generated by + // bloom filters created using different parameters. + const size_t k = array[len-1]; + if (k > 30) { + // Reserved for potentially new encodings for short bloom filters. + // Consider it a match. + return true; + } + + uint32_t h = hash_func_(key); + const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits + for (size_t j = 0; j < k; j++) { + const uint32_t bitpos = h % bits; + if ((array[bitpos/8] & (1 << (bitpos % 8))) == 0) return false; + h += delta; + } + return true; + } +}; +} + +const FilterPolicy* NewBloomFilterPolicy(int bits_per_key) { + return new BloomFilterPolicy(bits_per_key); +} + +} // namespace leveldb diff --git a/util/bloom_test.cc b/util/bloom_test.cc new file mode 100644 index 00000000..d29a0b20 --- /dev/null +++ b/util/bloom_test.cc @@ -0,0 +1,159 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/filter_policy.h" + +#include "util/logging.h" +#include "util/testharness.h" +#include "util/testutil.h" + +namespace leveldb { + +static const int kVerbose = 1; + +static Slice Key(int i, char* buffer) { + memcpy(buffer, &i, sizeof(i)); + return Slice(buffer, sizeof(i)); +} + +class BloomTest { + private: + const FilterPolicy* policy_; + std::string filter_; + std::vector keys_; + + public: + BloomTest() : policy_(NewBloomFilterPolicy(10)) { } + + ~BloomTest() { + delete policy_; + } + + void Reset() { + keys_.clear(); + filter_.clear(); + } + + void Add(const Slice& s) { + keys_.push_back(s.ToString()); + } + + void Build() { + std::vector key_slices; + for (size_t i = 0; i < keys_.size(); i++) { + key_slices.push_back(Slice(keys_[i])); + } + filter_.clear(); + policy_->CreateFilter(&key_slices[0], key_slices.size(), &filter_); + keys_.clear(); + if (kVerbose >= 2) DumpFilter(); + } + + size_t FilterSize() const { + return filter_.size(); + } + + void DumpFilter() { + fprintf(stderr, "F("); + for (size_t i = 0; i+1 < filter_.size(); i++) { + const unsigned int c = static_cast(filter_[i]); + for (int j = 0; j < 8; j++) { + fprintf(stderr, "%c", (c & (1 <KeyMayMatch(s, filter_); + } + + double FalsePositiveRate() { + char buffer[sizeof(int)]; + int result = 0; + for (int i = 0; i < 10000; i++) { + if (Matches(Key(i + 1000000000, buffer))) { + result++; + } + } + return result / 10000.0; + } +}; + +TEST(BloomTest, EmptyFilter) { + ASSERT_TRUE(! Matches("hello")); + ASSERT_TRUE(! Matches("world")); +} + +TEST(BloomTest, Small) { + Add("hello"); + Add("world"); + ASSERT_TRUE(Matches("hello")); + ASSERT_TRUE(Matches("world")); + ASSERT_TRUE(! Matches("x")); + ASSERT_TRUE(! Matches("foo")); +} + +static int NextLength(int length) { + if (length < 10) { + length += 1; + } else if (length < 100) { + length += 10; + } else if (length < 1000) { + length += 100; + } else { + length += 1000; + } + return length; +} + +TEST(BloomTest, VaryingLengths) { + char buffer[sizeof(int)]; + + // Count number of filters that significantly exceed the false positive rate + int mediocre_filters = 0; + int good_filters = 0; + + for (int length = 1; length <= 10000; length = NextLength(length)) { + Reset(); + for (int i = 0; i < length; i++) { + Add(Key(i, buffer)); + } + Build(); + + ASSERT_LE(FilterSize(), (size_t)((length * 10 / 8) + 40)) << length; + + // All added keys must match + for (int i = 0; i < length; i++) { + ASSERT_TRUE(Matches(Key(i, buffer))) + << "Length " << length << "; key " << i; + } + + // Check false positive rate + double rate = FalsePositiveRate(); + if (kVerbose >= 1) { + fprintf(stderr, "False positives: %5.2f%% @ length = %6d ; bytes = %6d\n", + rate*100.0, length, static_cast(FilterSize())); + } + ASSERT_LE(rate, 0.02); // Must not be over 2% + if (rate > 0.0125) mediocre_filters++; // Allowed, but not too often + else good_filters++; + } + if (kVerbose >= 1) { + fprintf(stderr, "Filters: %d good, %d mediocre\n", + good_filters, mediocre_filters); + } + ASSERT_LE(mediocre_filters, good_filters/5); +} + +// Different bits-per-byte + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/util/build_version.h b/util/build_version.h new file mode 100644 index 00000000..516c6404 --- /dev/null +++ b/util/build_version.h @@ -0,0 +1,13 @@ +/*version.h*/ +#ifndef VERSION_H_ +#define VERSION_H_ + +// these variables tell us about the git config and time +extern const char* leveldb_build_git_sha; + +// these variables tell us when the compilation occured +extern const char* leveldb_build_compile_time; +extern const char* leveldb_build_compile_date; + + +#endif /* VERSION_H_ */ diff --git a/util/cache.cc b/util/cache.cc new file mode 100644 index 00000000..345d98c4 --- /dev/null +++ b/util/cache.cc @@ -0,0 +1,352 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include + +#include "leveldb/cache.h" +#include "port/port.h" +#include "util/hash.h" +#include "util/mutexlock.h" + +namespace leveldb { + +Cache::~Cache() { +} + +namespace { + +// LRU cache implementation + +// An entry is a variable length heap-allocated structure. Entries +// are kept in a circular doubly linked list ordered by access time. +struct LRUHandle { + void* value; + void (*deleter)(const Slice&, void* value); + LRUHandle* next_hash; + LRUHandle* next; + LRUHandle* prev; + size_t charge; // TODO(opt): Only allow uint32_t? + size_t key_length; + uint32_t refs; + uint32_t hash; // Hash of key(); used for fast sharding and comparisons + char key_data[1]; // Beginning of key + + Slice key() const { + // For cheaper lookups, we allow a temporary Handle object + // to store a pointer to a key in "value". + if (next == this) { + return *(reinterpret_cast(value)); + } else { + return Slice(key_data, key_length); + } + } +}; + +// We provide our own simple hash table since it removes a whole bunch +// of porting hacks and is also faster than some of the built-in hash +// table implementations in some of the compiler/runtime combinations +// we have tested. E.g., readrandom speeds up by ~5% over the g++ +// 4.4.3's builtin hashtable. +class HandleTable { + public: + HandleTable() : length_(0), elems_(0), list_(nullptr) { Resize(); } + ~HandleTable() { delete[] list_; } + + LRUHandle* Lookup(const Slice& key, uint32_t hash) { + return *FindPointer(key, hash); + } + + LRUHandle* Insert(LRUHandle* h) { + LRUHandle** ptr = FindPointer(h->key(), h->hash); + LRUHandle* old = *ptr; + h->next_hash = (old == nullptr ? nullptr : old->next_hash); + *ptr = h; + if (old == nullptr) { + ++elems_; + if (elems_ > length_) { + // Since each cache entry is fairly large, we aim for a small + // average linked list length (<= 1). + Resize(); + } + } + return old; + } + + LRUHandle* Remove(const Slice& key, uint32_t hash) { + LRUHandle** ptr = FindPointer(key, hash); + LRUHandle* result = *ptr; + if (result != nullptr) { + *ptr = result->next_hash; + --elems_; + } + return result; + } + + private: + // The table consists of an array of buckets where each bucket is + // a linked list of cache entries that hash into the bucket. + uint32_t length_; + uint32_t elems_; + LRUHandle** list_; + + // Return a pointer to slot that points to a cache entry that + // matches key/hash. If there is no such cache entry, return a + // pointer to the trailing slot in the corresponding linked list. + LRUHandle** FindPointer(const Slice& key, uint32_t hash) { + LRUHandle** ptr = &list_[hash & (length_ - 1)]; + while (*ptr != nullptr && + ((*ptr)->hash != hash || key != (*ptr)->key())) { + ptr = &(*ptr)->next_hash; + } + return ptr; + } + + void Resize() { + uint32_t new_length = 4; + while (new_length < elems_) { + new_length *= 2; + } + LRUHandle** new_list = new LRUHandle*[new_length]; + memset(new_list, 0, sizeof(new_list[0]) * new_length); + uint32_t count = 0; + for (uint32_t i = 0; i < length_; i++) { + LRUHandle* h = list_[i]; + while (h != nullptr) { + LRUHandle* next = h->next_hash; + uint32_t hash = h->hash; + LRUHandle** ptr = &new_list[hash & (new_length - 1)]; + h->next_hash = *ptr; + *ptr = h; + h = next; + count++; + } + } + assert(elems_ == count); + delete[] list_; + list_ = new_list; + length_ = new_length; + } +}; + +// A single shard of sharded cache. +class LRUCache { + public: + LRUCache(); + ~LRUCache(); + + // Separate from constructor so caller can easily make an array of LRUCache + void SetCapacity(size_t capacity) { capacity_ = capacity; } + + // Like Cache methods, but with an extra "hash" parameter. + Cache::Handle* Insert(const Slice& key, uint32_t hash, + void* value, size_t charge, + void (*deleter)(const Slice& key, void* value)); + Cache::Handle* Lookup(const Slice& key, uint32_t hash); + void Release(Cache::Handle* handle); + void Erase(const Slice& key, uint32_t hash); + + private: + void LRU_Remove(LRUHandle* e); + void LRU_Append(LRUHandle* e); + void Unref(LRUHandle* e); + + // Initialized before use. + size_t capacity_; + + // mutex_ protects the following state. + port::Mutex mutex_; + size_t usage_; + uint64_t last_id_; + + // Dummy head of LRU list. + // lru.prev is newest entry, lru.next is oldest entry. + LRUHandle lru_; + + HandleTable table_; +}; + +LRUCache::LRUCache() + : usage_(0), + last_id_(0) { + // Make empty circular linked list + lru_.next = &lru_; + lru_.prev = &lru_; +} + +LRUCache::~LRUCache() { + for (LRUHandle* e = lru_.next; e != &lru_; ) { + LRUHandle* next = e->next; + assert(e->refs == 1); // Error if caller has an unreleased handle + Unref(e); + e = next; + } +} + +void LRUCache::Unref(LRUHandle* e) { + assert(e->refs > 0); + e->refs--; + if (e->refs <= 0) { + usage_ -= e->charge; + (*e->deleter)(e->key(), e->value); + free(e); + } +} + +void LRUCache::LRU_Remove(LRUHandle* e) { + e->next->prev = e->prev; + e->prev->next = e->next; +} + +void LRUCache::LRU_Append(LRUHandle* e) { + // Make "e" newest entry by inserting just before lru_ + e->next = &lru_; + e->prev = lru_.prev; + e->prev->next = e; + e->next->prev = e; +} + +Cache::Handle* LRUCache::Lookup(const Slice& key, uint32_t hash) { + MutexLock l(&mutex_); + LRUHandle* e = table_.Lookup(key, hash); + if (e != nullptr) { + e->refs++; + LRU_Remove(e); + LRU_Append(e); + } + return reinterpret_cast(e); +} + +void LRUCache::Release(Cache::Handle* handle) { + MutexLock l(&mutex_); + Unref(reinterpret_cast(handle)); +} + +Cache::Handle* LRUCache::Insert( + const Slice& key, uint32_t hash, void* value, size_t charge, + void (*deleter)(const Slice& key, void* value)) { + MutexLock l(&mutex_); + + LRUHandle* e = reinterpret_cast( + malloc(sizeof(LRUHandle)-1 + key.size())); + e->value = value; + e->deleter = deleter; + e->charge = charge; + e->key_length = key.size(); + e->hash = hash; + e->refs = 2; // One from LRUCache, one for the returned handle + memcpy(e->key_data, key.data(), key.size()); + LRU_Append(e); + usage_ += charge; + + LRUHandle* old = table_.Insert(e); + if (old != nullptr) { + LRU_Remove(old); + Unref(old); + } + + while (usage_ > capacity_ && lru_.next != &lru_) { + LRUHandle* old = lru_.next; + LRU_Remove(old); + table_.Remove(old->key(), old->hash); + Unref(old); + } + + return reinterpret_cast(e); +} + +void LRUCache::Erase(const Slice& key, uint32_t hash) { + MutexLock l(&mutex_); + LRUHandle* e = table_.Remove(key, hash); + if (e != nullptr) { + LRU_Remove(e); + Unref(e); + } +} + +static int kNumShardBits = 4; // default values, can be overridden + +class ShardedLRUCache : public Cache { + private: + LRUCache* shard_; + port::Mutex id_mutex_; + uint64_t last_id_; + int numShardBits; + size_t capacity_; + + static inline uint32_t HashSlice(const Slice& s) { + return Hash(s.data(), s.size(), 0); + } + + uint32_t Shard(uint32_t hash) { + return hash >> (32 - numShardBits); + } + + void init(size_t capacity, int numbits) { + numShardBits = numbits; + capacity_ = capacity; + int numShards = 1 << numShardBits; + shard_ = new LRUCache[numShards]; + const size_t per_shard = (capacity + (numShards - 1)) / numShards; + for (int s = 0; s < numShards; s++) { + shard_[s].SetCapacity(per_shard); + } + } + + public: + explicit ShardedLRUCache(size_t capacity) + : last_id_(0) { + init(capacity, kNumShardBits); + } + ShardedLRUCache(size_t capacity, int numShardBits) + : last_id_(0) { + init(capacity, numShardBits); + } + virtual ~ShardedLRUCache() { + delete[] shard_; + } + virtual Handle* Insert(const Slice& key, void* value, size_t charge, + void (*deleter)(const Slice& key, void* value)) { + const uint32_t hash = HashSlice(key); + return shard_[Shard(hash)].Insert(key, hash, value, charge, deleter); + } + virtual Handle* Lookup(const Slice& key) { + const uint32_t hash = HashSlice(key); + return shard_[Shard(hash)].Lookup(key, hash); + } + virtual void Release(Handle* handle) { + LRUHandle* h = reinterpret_cast(handle); + shard_[Shard(h->hash)].Release(handle); + } + virtual void Erase(const Slice& key) { + const uint32_t hash = HashSlice(key); + shard_[Shard(hash)].Erase(key, hash); + } + virtual void* Value(Handle* handle) { + return reinterpret_cast(handle)->value; + } + virtual uint64_t NewId() { + MutexLock l(&id_mutex_); + return ++(last_id_); + } + virtual uint64_t GetCapacity() { + return capacity_; + } +}; + +} // end anonymous namespace + +shared_ptr NewLRUCache(size_t capacity) { + return std::make_shared(capacity); +} + +shared_ptr NewLRUCache(size_t capacity, int numShardBits) { + if (numShardBits >= 20) { + return nullptr; // the cache cannot be sharded into too many fine pieces + } + return std::make_shared(capacity, numShardBits); +} + +} // namespace leveldb diff --git a/util/cache_test.cc b/util/cache_test.cc new file mode 100644 index 00000000..00233a31 --- /dev/null +++ b/util/cache_test.cc @@ -0,0 +1,185 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/cache.h" + +#include +#include "util/coding.h" +#include "util/testharness.h" + +namespace leveldb { + +// Conversions between numeric keys/values and the types expected by Cache. +static std::string EncodeKey(int k) { + std::string result; + PutFixed32(&result, k); + return result; +} +static int DecodeKey(const Slice& k) { + assert(k.size() == 4); + return DecodeFixed32(k.data()); +} +static void* EncodeValue(uintptr_t v) { return reinterpret_cast(v); } +static int DecodeValue(void* v) { return reinterpret_cast(v); } + +class CacheTest { + public: + static CacheTest* current_; + + static void Deleter(const Slice& key, void* v) { + current_->deleted_keys_.push_back(DecodeKey(key)); + current_->deleted_values_.push_back(DecodeValue(v)); + } + + static const int kCacheSize = 1000; + std::vector deleted_keys_; + std::vector deleted_values_; + shared_ptr cache_; + + CacheTest() : cache_(NewLRUCache(kCacheSize)) { + current_ = this; + } + + ~CacheTest() { + } + + int Lookup(int key) { + Cache::Handle* handle = cache_->Lookup(EncodeKey(key)); + const int r = (handle == nullptr) ? -1 : DecodeValue(cache_->Value(handle)); + if (handle != nullptr) { + cache_->Release(handle); + } + return r; + } + + void Insert(int key, int value, int charge = 1) { + cache_->Release(cache_->Insert(EncodeKey(key), EncodeValue(value), charge, + &CacheTest::Deleter)); + } + + void Erase(int key) { + cache_->Erase(EncodeKey(key)); + } +}; +CacheTest* CacheTest::current_; + +TEST(CacheTest, HitAndMiss) { + ASSERT_EQ(-1, Lookup(100)); + + Insert(100, 101); + ASSERT_EQ(101, Lookup(100)); + ASSERT_EQ(-1, Lookup(200)); + ASSERT_EQ(-1, Lookup(300)); + + Insert(200, 201); + ASSERT_EQ(101, Lookup(100)); + ASSERT_EQ(201, Lookup(200)); + ASSERT_EQ(-1, Lookup(300)); + + Insert(100, 102); + ASSERT_EQ(102, Lookup(100)); + ASSERT_EQ(201, Lookup(200)); + ASSERT_EQ(-1, Lookup(300)); + + ASSERT_EQ(1U, deleted_keys_.size()); + ASSERT_EQ(100, deleted_keys_[0]); + ASSERT_EQ(101, deleted_values_[0]); +} + +TEST(CacheTest, Erase) { + Erase(200); + ASSERT_EQ(0U, deleted_keys_.size()); + + Insert(100, 101); + Insert(200, 201); + Erase(100); + ASSERT_EQ(-1, Lookup(100)); + ASSERT_EQ(201, Lookup(200)); + ASSERT_EQ(1U, deleted_keys_.size()); + ASSERT_EQ(100, deleted_keys_[0]); + ASSERT_EQ(101, deleted_values_[0]); + + Erase(100); + ASSERT_EQ(-1, Lookup(100)); + ASSERT_EQ(201, Lookup(200)); + ASSERT_EQ(1U, deleted_keys_.size()); +} + +TEST(CacheTest, EntriesArePinned) { + Insert(100, 101); + Cache::Handle* h1 = cache_->Lookup(EncodeKey(100)); + ASSERT_EQ(101, DecodeValue(cache_->Value(h1))); + + Insert(100, 102); + Cache::Handle* h2 = cache_->Lookup(EncodeKey(100)); + ASSERT_EQ(102, DecodeValue(cache_->Value(h2))); + ASSERT_EQ(0U, deleted_keys_.size()); + + cache_->Release(h1); + ASSERT_EQ(1U, deleted_keys_.size()); + ASSERT_EQ(100, deleted_keys_[0]); + ASSERT_EQ(101, deleted_values_[0]); + + Erase(100); + ASSERT_EQ(-1, Lookup(100)); + ASSERT_EQ(1U, deleted_keys_.size()); + + cache_->Release(h2); + ASSERT_EQ(2U, deleted_keys_.size()); + ASSERT_EQ(100, deleted_keys_[1]); + ASSERT_EQ(102, deleted_values_[1]); +} + +TEST(CacheTest, EvictionPolicy) { + Insert(100, 101); + Insert(200, 201); + + // Frequently used entry must be kept around + for (int i = 0; i < kCacheSize + 100; i++) { + Insert(1000+i, 2000+i); + ASSERT_EQ(2000+i, Lookup(1000+i)); + ASSERT_EQ(101, Lookup(100)); + } + ASSERT_EQ(101, Lookup(100)); + ASSERT_EQ(-1, Lookup(200)); +} + +TEST(CacheTest, HeavyEntries) { + // Add a bunch of light and heavy entries and then count the combined + // size of items still in the cache, which must be approximately the + // same as the total capacity. + const int kLight = 1; + const int kHeavy = 10; + int added = 0; + int index = 0; + while (added < 2*kCacheSize) { + const int weight = (index & 1) ? kLight : kHeavy; + Insert(index, 1000+index, weight); + added += weight; + index++; + } + + int cached_weight = 0; + for (int i = 0; i < index; i++) { + const int weight = (i & 1 ? kLight : kHeavy); + int r = Lookup(i); + if (r >= 0) { + cached_weight += weight; + ASSERT_EQ(1000+i, r); + } + } + ASSERT_LE(cached_weight, kCacheSize + kCacheSize/10); +} + +TEST(CacheTest, NewId) { + uint64_t a = cache_->NewId(); + uint64_t b = cache_->NewId(); + ASSERT_NE(a, b); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/util/coding.cc b/util/coding.cc new file mode 100644 index 00000000..58b2c475 --- /dev/null +++ b/util/coding.cc @@ -0,0 +1,294 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/coding.h" + +#include + +namespace leveldb { + +void EncodeFixed32(char* buf, uint32_t value) { +#if __BYTE_ORDER == __LITTLE_ENDIAN + memcpy(buf, &value, sizeof(value)); +#else + buf[0] = value & 0xff; + buf[1] = (value >> 8) & 0xff; + buf[2] = (value >> 16) & 0xff; + buf[3] = (value >> 24) & 0xff; +#endif +} + +void EncodeFixed64(char* buf, uint64_t value) { +#if __BYTE_ORDER == __LITTLE_ENDIAN + memcpy(buf, &value, sizeof(value)); +#else + buf[0] = value & 0xff; + buf[1] = (value >> 8) & 0xff; + buf[2] = (value >> 16) & 0xff; + buf[3] = (value >> 24) & 0xff; + buf[4] = (value >> 32) & 0xff; + buf[5] = (value >> 40) & 0xff; + buf[6] = (value >> 48) & 0xff; + buf[7] = (value >> 56) & 0xff; +#endif +} + +void PutFixed32(std::string* dst, uint32_t value) { + char buf[sizeof(value)]; + EncodeFixed32(buf, value); + dst->append(buf, sizeof(buf)); +} + +void PutFixed64(std::string* dst, uint64_t value) { + char buf[sizeof(value)]; + EncodeFixed64(buf, value); + dst->append(buf, sizeof(buf)); +} + +char* EncodeVarint32(char* dst, uint32_t v) { + // Operate on characters as unsigneds + unsigned char* ptr = reinterpret_cast(dst); + static const int B = 128; + if (v < (1<<7)) { + *(ptr++) = v; + } else if (v < (1<<14)) { + *(ptr++) = v | B; + *(ptr++) = v>>7; + } else if (v < (1<<21)) { + *(ptr++) = v | B; + *(ptr++) = (v>>7) | B; + *(ptr++) = v>>14; + } else if (v < (1<<28)) { + *(ptr++) = v | B; + *(ptr++) = (v>>7) | B; + *(ptr++) = (v>>14) | B; + *(ptr++) = v>>21; + } else { + *(ptr++) = v | B; + *(ptr++) = (v>>7) | B; + *(ptr++) = (v>>14) | B; + *(ptr++) = (v>>21) | B; + *(ptr++) = v>>28; + } + return reinterpret_cast(ptr); +} + +void PutVarint32(std::string* dst, uint32_t v) { + char buf[5]; + char* ptr = EncodeVarint32(buf, v); + dst->append(buf, ptr - buf); +} + +char* EncodeVarint64(char* dst, uint64_t v) { + static const unsigned int B = 128; + unsigned char* ptr = reinterpret_cast(dst); + while (v >= B) { + *(ptr++) = (v & (B-1)) | B; + v >>= 7; + } + *(ptr++) = static_cast(v); + return reinterpret_cast(ptr); +} + +void PutVarint64(std::string* dst, uint64_t v) { + char buf[10]; + char* ptr = EncodeVarint64(buf, v); + dst->append(buf, ptr - buf); +} + +void PutLengthPrefixedSlice(std::string* dst, const Slice& value) { + PutVarint32(dst, value.size()); + dst->append(value.data(), value.size()); +} + +int VarintLength(uint64_t v) { + int len = 1; + while (v >= 128) { + v >>= 7; + len++; + } + return len; +} + +const char* GetVarint32PtrFallback(const char* p, + const char* limit, + uint32_t* value) { + uint32_t result = 0; + for (uint32_t shift = 0; shift <= 28 && p < limit; shift += 7) { + uint32_t byte = *(reinterpret_cast(p)); + p++; + if (byte & 128) { + // More bytes are present + result |= ((byte & 127) << shift); + } else { + result |= (byte << shift); + *value = result; + return reinterpret_cast(p); + } + } + return nullptr; +} + +bool GetVarint32(Slice* input, uint32_t* value) { + const char* p = input->data(); + const char* limit = p + input->size(); + const char* q = GetVarint32Ptr(p, limit, value); + if (q == nullptr) { + return false; + } else { + *input = Slice(q, limit - q); + return true; + } +} + +const char* GetVarint64Ptr(const char* p, const char* limit, uint64_t* value) { + uint64_t result = 0; + for (uint32_t shift = 0; shift <= 63 && p < limit; shift += 7) { + uint64_t byte = *(reinterpret_cast(p)); + p++; + if (byte & 128) { + // More bytes are present + result |= ((byte & 127) << shift); + } else { + result |= (byte << shift); + *value = result; + return reinterpret_cast(p); + } + } + return nullptr; +} + +bool GetVarint64(Slice* input, uint64_t* value) { + const char* p = input->data(); + const char* limit = p + input->size(); + const char* q = GetVarint64Ptr(p, limit, value); + if (q == nullptr) { + return false; + } else { + *input = Slice(q, limit - q); + return true; + } +} + +const char* GetLengthPrefixedSlice(const char* p, const char* limit, + Slice* result) { + uint32_t len; + p = GetVarint32Ptr(p, limit, &len); + if (p == nullptr) return nullptr; + if (p + len > limit) return nullptr; + *result = Slice(p, len); + return p + len; +} + +bool GetLengthPrefixedSlice(Slice* input, Slice* result) { + uint32_t len; + if (GetVarint32(input, &len) && + input->size() >= len) { + *result = Slice(input->data(), len); + input->remove_prefix(len); + return true; + } else { + return false; + } +} + +void BitStreamPutInt(char* dst, size_t dstlen, size_t offset, + uint32_t bits, uint64_t value) { + assert((offset + bits + 7)/8 <= dstlen); + assert(bits <= 64); + + unsigned char* ptr = reinterpret_cast(dst); + + size_t byteOffset = offset / 8; + size_t bitOffset = offset % 8; + + // This prevents unused variable warnings when compiling. +#ifndef NDEBUG + // Store truncated value. + uint64_t origValue = (bits < 64)?(value & (((uint64_t)1 << bits) - 1)):value; + uint32_t origBits = bits; +#endif + + while (bits > 0) { + size_t bitsToGet = std::min(bits, 8 - bitOffset); + unsigned char mask = ((1 << bitsToGet) - 1); + + ptr[byteOffset] = (ptr[byteOffset] & ~(mask << bitOffset)) + + ((value & mask) << bitOffset); + + value >>= bitsToGet; + byteOffset += 1; + bitOffset = 0; + bits -= bitsToGet; + } + + assert(origValue == BitStreamGetInt(dst, dstlen, offset, origBits)); +} + +uint64_t BitStreamGetInt(const char* src, size_t srclen, size_t offset, + uint32_t bits) { + assert((offset + bits + 7)/8 <= srclen); + assert(bits <= 64); + + const unsigned char* ptr = reinterpret_cast(src); + + uint64_t result = 0; + + size_t byteOffset = offset / 8; + size_t bitOffset = offset % 8; + size_t shift = 0; + + while (bits > 0) { + size_t bitsToGet = std::min(bits, 8 - bitOffset); + unsigned char mask = ((1 << bitsToGet) - 1); + + result += (uint64_t)((ptr[byteOffset] >> bitOffset) & mask) << shift; + + shift += bitsToGet; + byteOffset += 1; + bitOffset = 0; + bits -= bitsToGet; + } + + return result; +} + +void BitStreamPutInt(std::string* dst, size_t offset, uint32_t bits, + uint64_t value) { + assert((offset + bits + 7)/8 <= dst->size()); + + const size_t kTmpBufLen = sizeof(value) + 1; + char tmpBuf[kTmpBufLen]; + + // Number of bytes of tmpBuf being used + const size_t kUsedBytes = (offset%8 + bits)/8; + + // Copy relevant parts of dst to tmpBuf + for (size_t idx = 0; idx <= kUsedBytes; ++idx) { + tmpBuf[idx] = (*dst)[offset/8 + idx]; + } + + BitStreamPutInt(tmpBuf, kTmpBufLen, offset%8, bits, value); + + // Copy tmpBuf back to dst + for (size_t idx = 0; idx <= kUsedBytes; ++idx) { + (*dst)[offset/8 + idx] = tmpBuf[idx]; + } + + // Do the check here too as we are working with a buffer. + assert(((bits < 64)?(value & (((uint64_t)1 << bits) - 1)):value) == + BitStreamGetInt(dst, offset, bits)); +} + +uint64_t BitStreamGetInt(const std::string* src, size_t offset, + uint32_t bits) { + return BitStreamGetInt(src->data(), src->size(), offset, bits); +} + +uint64_t BitStreamGetInt(const Slice* src, size_t offset, + uint32_t bits) { + return BitStreamGetInt(src->data(), src->size(), offset, bits); +} + +} // namespace leveldb diff --git a/util/coding.h b/util/coding.h new file mode 100644 index 00000000..59c61b1b --- /dev/null +++ b/util/coding.h @@ -0,0 +1,134 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Endian-neutral encoding: +// * Fixed-length numbers are encoded with least-significant byte first +// * In addition we support variable length "varint" encoding +// * Strings are encoded prefixed by their length in varint format + +#ifndef STORAGE_LEVELDB_UTIL_CODING_H_ +#define STORAGE_LEVELDB_UTIL_CODING_H_ + +#include +#include +#include +#include "leveldb/slice.h" +#include "port/port.h" + +namespace leveldb { + +// The maximum length of a varint in bytes for 32 and 64 bits respectively. +const unsigned int kMaxVarint32Length = 5; +const unsigned int kMaxVarint64Length = 10; + +// Standard Put... routines append to a string +extern void PutFixed32(std::string* dst, uint32_t value); +extern void PutFixed64(std::string* dst, uint64_t value); +extern void PutVarint32(std::string* dst, uint32_t value); +extern void PutVarint64(std::string* dst, uint64_t value); +extern void PutLengthPrefixedSlice(std::string* dst, const Slice& value); + +// Standard Get... routines parse a value from the beginning of a Slice +// and advance the slice past the parsed value. +extern bool GetVarint32(Slice* input, uint32_t* value); +extern bool GetVarint64(Slice* input, uint64_t* value); +extern bool GetLengthPrefixedSlice(Slice* input, Slice* result); + +// Pointer-based variants of GetVarint... These either store a value +// in *v and return a pointer just past the parsed value, or return +// nullptr on error. These routines only look at bytes in the range +// [p..limit-1] +extern const char* GetVarint32Ptr(const char* p,const char* limit, uint32_t* v); +extern const char* GetVarint64Ptr(const char* p,const char* limit, uint64_t* v); + +// Returns the length of the varint32 or varint64 encoding of "v" +extern int VarintLength(uint64_t v); + +// Lower-level versions of Put... that write directly into a character buffer +// REQUIRES: dst has enough space for the value being written +extern void EncodeFixed32(char* dst, uint32_t value); +extern void EncodeFixed64(char* dst, uint64_t value); + +// Lower-level versions of Put... that write directly into a character buffer +// and return a pointer just past the last byte written. +// REQUIRES: dst has enough space for the value being written +extern char* EncodeVarint32(char* dst, uint32_t value); +extern char* EncodeVarint64(char* dst, uint64_t value); + +// Lower-level versions of Get... that read directly from a character buffer +// without any bounds checking. + +inline uint32_t DecodeFixed32(const char* ptr) { + if (port::kLittleEndian) { + // Load the raw bytes + uint32_t result; + memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load + return result; + } else { + return ((static_cast(static_cast(ptr[0]))) + | (static_cast(static_cast(ptr[1])) << 8) + | (static_cast(static_cast(ptr[2])) << 16) + | (static_cast(static_cast(ptr[3])) << 24)); + } +} + +inline uint64_t DecodeFixed64(const char* ptr) { + if (port::kLittleEndian) { + // Load the raw bytes + uint64_t result; + memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load + return result; + } else { + uint64_t lo = DecodeFixed32(ptr); + uint64_t hi = DecodeFixed32(ptr + 4); + return (hi << 32) | lo; + } +} + +// Internal routine for use by fallback path of GetVarint32Ptr +extern const char* GetVarint32PtrFallback(const char* p, + const char* limit, + uint32_t* value); +inline const char* GetVarint32Ptr(const char* p, + const char* limit, + uint32_t* value) { + if (p < limit) { + uint32_t result = *(reinterpret_cast(p)); + if ((result & 128) == 0) { + *value = result; + return p + 1; + } + } + return GetVarint32PtrFallback(p, limit, value); +} + +// Writes an unsigned integer with bits number of bits with its least +// significant bit at offset. +// Bits are numbered from 0 to 7 in the first byte, 8 to 15 in the second and +// so on. +// value is truncated to the bits number of least significant bits. +// REQUIRES: (offset+bits+7)/8 <= dstlen +// REQUIRES: bits <= 64 +extern void BitStreamPutInt(char* dst, size_t dstlen, size_t offset, + uint32_t bits, uint64_t value); + +// Reads an unsigned integer with bits number of bits with its least +// significant bit at offset. +// Bits are numbered in the same way as ByteStreamPutInt(). +// REQUIRES: (offset+bits+7)/8 <= srclen +// REQUIRES: bits <= 64 +extern uint64_t BitStreamGetInt(const char* src, size_t srclen, size_t offset, + uint32_t bits); + +// Convenience functions +extern void BitStreamPutInt(std::string* dst, size_t offset, uint32_t bits, + uint64_t value); +extern uint64_t BitStreamGetInt(const std::string* src, size_t offset, + uint32_t bits); +extern uint64_t BitStreamGetInt(const Slice* src, size_t offset, + uint32_t bits); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_CODING_H_ diff --git a/util/coding_test.cc b/util/coding_test.cc new file mode 100644 index 00000000..b3897091 --- /dev/null +++ b/util/coding_test.cc @@ -0,0 +1,291 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/coding.h" + +#include "util/testharness.h" + +namespace leveldb { + +class Coding { }; + +TEST(Coding, Fixed32) { + std::string s; + for (uint32_t v = 0; v < 100000; v++) { + PutFixed32(&s, v); + } + + const char* p = s.data(); + for (uint32_t v = 0; v < 100000; v++) { + uint32_t actual = DecodeFixed32(p); + ASSERT_EQ(v, actual); + p += sizeof(uint32_t); + } +} + +TEST(Coding, Fixed64) { + std::string s; + for (int power = 0; power <= 63; power++) { + uint64_t v = static_cast(1) << power; + PutFixed64(&s, v - 1); + PutFixed64(&s, v + 0); + PutFixed64(&s, v + 1); + } + + const char* p = s.data(); + for (int power = 0; power <= 63; power++) { + uint64_t v = static_cast(1) << power; + uint64_t actual; + actual = DecodeFixed64(p); + ASSERT_EQ(v-1, actual); + p += sizeof(uint64_t); + + actual = DecodeFixed64(p); + ASSERT_EQ(v+0, actual); + p += sizeof(uint64_t); + + actual = DecodeFixed64(p); + ASSERT_EQ(v+1, actual); + p += sizeof(uint64_t); + } +} + +// Test that encoding routines generate little-endian encodings +TEST(Coding, EncodingOutput) { + std::string dst; + PutFixed32(&dst, 0x04030201); + ASSERT_EQ(4U, dst.size()); + ASSERT_EQ(0x01, static_cast(dst[0])); + ASSERT_EQ(0x02, static_cast(dst[1])); + ASSERT_EQ(0x03, static_cast(dst[2])); + ASSERT_EQ(0x04, static_cast(dst[3])); + + dst.clear(); + PutFixed64(&dst, 0x0807060504030201ull); + ASSERT_EQ(8U, dst.size()); + ASSERT_EQ(0x01, static_cast(dst[0])); + ASSERT_EQ(0x02, static_cast(dst[1])); + ASSERT_EQ(0x03, static_cast(dst[2])); + ASSERT_EQ(0x04, static_cast(dst[3])); + ASSERT_EQ(0x05, static_cast(dst[4])); + ASSERT_EQ(0x06, static_cast(dst[5])); + ASSERT_EQ(0x07, static_cast(dst[6])); + ASSERT_EQ(0x08, static_cast(dst[7])); +} + +TEST(Coding, Varint32) { + std::string s; + for (uint32_t i = 0; i < (32 * 32); i++) { + uint32_t v = (i / 32) << (i % 32); + PutVarint32(&s, v); + } + + const char* p = s.data(); + const char* limit = p + s.size(); + for (uint32_t i = 0; i < (32 * 32); i++) { + uint32_t expected = (i / 32) << (i % 32); + uint32_t actual; + const char* start = p; + p = GetVarint32Ptr(p, limit, &actual); + ASSERT_TRUE(p != nullptr); + ASSERT_EQ(expected, actual); + ASSERT_EQ(VarintLength(actual), p - start); + } + ASSERT_EQ(p, s.data() + s.size()); +} + +TEST(Coding, Varint64) { + // Construct the list of values to check + std::vector values; + // Some special values + values.push_back(0); + values.push_back(100); + values.push_back(~static_cast(0)); + values.push_back(~static_cast(0) - 1); + for (uint32_t k = 0; k < 64; k++) { + // Test values near powers of two + const uint64_t power = 1ull << k; + values.push_back(power); + values.push_back(power-1); + values.push_back(power+1); + }; + + std::string s; + for (unsigned int i = 0; i < values.size(); i++) { + PutVarint64(&s, values[i]); + } + + const char* p = s.data(); + const char* limit = p + s.size(); + for (unsigned int i = 0; i < values.size(); i++) { + ASSERT_TRUE(p < limit); + uint64_t actual; + const char* start = p; + p = GetVarint64Ptr(p, limit, &actual); + ASSERT_TRUE(p != nullptr); + ASSERT_EQ(values[i], actual); + ASSERT_EQ(VarintLength(actual), p - start); + } + ASSERT_EQ(p, limit); + +} + +TEST(Coding, Varint32Overflow) { + uint32_t result; + std::string input("\x81\x82\x83\x84\x85\x11"); + ASSERT_TRUE(GetVarint32Ptr(input.data(), input.data() + input.size(), &result) + == nullptr); +} + +TEST(Coding, Varint32Truncation) { + uint32_t large_value = (1u << 31) + 100; + std::string s; + PutVarint32(&s, large_value); + uint32_t result; + for (unsigned int len = 0; len < s.size() - 1; len++) { + ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + len, &result) == nullptr); + } + ASSERT_TRUE( + GetVarint32Ptr(s.data(), s.data() + s.size(), &result) != nullptr); + ASSERT_EQ(large_value, result); +} + +TEST(Coding, Varint64Overflow) { + uint64_t result; + std::string input("\x81\x82\x83\x84\x85\x81\x82\x83\x84\x85\x11"); + ASSERT_TRUE(GetVarint64Ptr(input.data(), input.data() + input.size(), &result) + == nullptr); +} + +TEST(Coding, Varint64Truncation) { + uint64_t large_value = (1ull << 63) + 100ull; + std::string s; + PutVarint64(&s, large_value); + uint64_t result; + for (unsigned int len = 0; len < s.size() - 1; len++) { + ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + len, &result) == nullptr); + } + ASSERT_TRUE( + GetVarint64Ptr(s.data(), s.data() + s.size(), &result) != nullptr); + ASSERT_EQ(large_value, result); +} + +TEST(Coding, Strings) { + std::string s; + PutLengthPrefixedSlice(&s, Slice("")); + PutLengthPrefixedSlice(&s, Slice("foo")); + PutLengthPrefixedSlice(&s, Slice("bar")); + PutLengthPrefixedSlice(&s, Slice(std::string(200, 'x'))); + + Slice input(s); + Slice v; + ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v)); + ASSERT_EQ("", v.ToString()); + ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v)); + ASSERT_EQ("foo", v.ToString()); + ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v)); + ASSERT_EQ("bar", v.ToString()); + ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v)); + ASSERT_EQ(std::string(200, 'x'), v.ToString()); + ASSERT_EQ("", input.ToString()); +} + +TEST(Coding, BitStream) { + const int kNumBytes = 10; + char bytes[kNumBytes+1]; + for (int i = 0; i < kNumBytes + 1; ++i) { + bytes[i] = '\0'; + } + + // Simple byte aligned test. + for (int i = 0; i < kNumBytes; ++i) { + BitStreamPutInt(bytes, kNumBytes, i*8, 8, 255-i); + + ASSERT_EQ((unsigned char)bytes[i], (unsigned char)(255-i)); + } + for (int i = 0; i < kNumBytes; ++i) { + ASSERT_EQ(BitStreamGetInt(bytes, kNumBytes, i*8, 8), (uint32_t)(255-i)); + } + ASSERT_EQ(bytes[kNumBytes], '\0'); + + // Write and read back at strange offsets + for (int i = 0; i < kNumBytes + 1; ++i) { + bytes[i] = '\0'; + } + for (int i = 0; i < kNumBytes; ++i) { + BitStreamPutInt(bytes, kNumBytes, i*5+1, 4, (i * 7) % (1 << 4)); + } + for (int i = 0; i < kNumBytes; ++i) { + ASSERT_EQ(BitStreamGetInt(bytes, kNumBytes, i*5+1, 4), + (uint32_t)((i * 7) % (1 << 4))); + } + ASSERT_EQ(bytes[kNumBytes], '\0'); + + // Create 11011011 as a bit pattern + for (int i = 0; i < kNumBytes + 1; ++i) { + bytes[i] = '\0'; + } + for (int i = 0; i < kNumBytes; ++i) { + BitStreamPutInt(bytes, kNumBytes, i*8, 2, 3); + BitStreamPutInt(bytes, kNumBytes, i*8+3, 2, 3); + BitStreamPutInt(bytes, kNumBytes, i*8+6, 2, 3); + + ASSERT_EQ((unsigned char)bytes[i], + (unsigned char)(3 + (3 << 3) + (3 << 6))); + } + ASSERT_EQ(bytes[kNumBytes], '\0'); + + + // Test large values + for (int i = 0; i < kNumBytes + 1; ++i) { + bytes[i] = '\0'; + } + BitStreamPutInt(bytes, kNumBytes, 0, 64, (uint64_t)(-1)); + for (int i = 0; i < 64/8; ++i) { + ASSERT_EQ((unsigned char)bytes[i], + (unsigned char)(255)); + } + ASSERT_EQ(bytes[64/8], '\0'); + + +} + +TEST(Coding, BitStreamConvenienceFuncs) { + std::string bytes(1, '\0'); + + // Check that independent changes to byte are preserved. + BitStreamPutInt(&bytes, 0, 2, 3); + BitStreamPutInt(&bytes, 3, 2, 3); + BitStreamPutInt(&bytes, 6, 2, 3); + ASSERT_EQ((unsigned char)bytes[0], (unsigned char)(3 + (3 << 3) + (3 << 6))); + ASSERT_EQ(BitStreamGetInt(&bytes, 0, 2), 3u); + ASSERT_EQ(BitStreamGetInt(&bytes, 3, 2), 3u); + ASSERT_EQ(BitStreamGetInt(&bytes, 6, 2), 3u); + Slice slice(bytes); + ASSERT_EQ(BitStreamGetInt(&slice, 0, 2), 3u); + ASSERT_EQ(BitStreamGetInt(&slice, 3, 2), 3u); + ASSERT_EQ(BitStreamGetInt(&slice, 6, 2), 3u); + + // Test overlapping crossing over byte boundaries + bytes = std::string(2, '\0'); + BitStreamPutInt(&bytes, 6, 4, 15); + ASSERT_EQ((unsigned char)bytes[0], 3 << 6); + ASSERT_EQ((unsigned char)bytes[1], 3); + ASSERT_EQ(BitStreamGetInt(&bytes, 6, 4), 15u); + slice = Slice(bytes); + ASSERT_EQ(BitStreamGetInt(&slice, 6, 4), 15u); + + // Test 64-bit number + bytes = std::string(64/8, '\0'); + BitStreamPutInt(&bytes, 0, 64, (uint64_t)(-1)); + ASSERT_EQ(BitStreamGetInt(&bytes, 0, 64), (uint64_t)(-1)); + slice = Slice(bytes); + ASSERT_EQ(BitStreamGetInt(&slice, 0, 64), (uint64_t)(-1)); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/util/comparator.cc b/util/comparator.cc new file mode 100644 index 00000000..4b7b5724 --- /dev/null +++ b/util/comparator.cc @@ -0,0 +1,81 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include "leveldb/comparator.h" +#include "leveldb/slice.h" +#include "port/port.h" +#include "util/logging.h" + +namespace leveldb { + +Comparator::~Comparator() { } + +namespace { +class BytewiseComparatorImpl : public Comparator { + public: + BytewiseComparatorImpl() { } + + virtual const char* Name() const { + return "leveldb.BytewiseComparator"; + } + + virtual int Compare(const Slice& a, const Slice& b) const { + return a.compare(b); + } + + virtual void FindShortestSeparator( + std::string* start, + const Slice& limit) const { + // Find length of common prefix + size_t min_length = std::min(start->size(), limit.size()); + size_t diff_index = 0; + while ((diff_index < min_length) && + ((*start)[diff_index] == limit[diff_index])) { + diff_index++; + } + + if (diff_index >= min_length) { + // Do not shorten if one string is a prefix of the other + } else { + uint8_t diff_byte = static_cast((*start)[diff_index]); + if (diff_byte < static_cast(0xff) && + diff_byte + 1 < static_cast(limit[diff_index])) { + (*start)[diff_index]++; + start->resize(diff_index + 1); + assert(Compare(*start, limit) < 0); + } + } + } + + virtual void FindShortSuccessor(std::string* key) const { + // Find first character that can be incremented + size_t n = key->size(); + for (size_t i = 0; i < n; i++) { + const uint8_t byte = (*key)[i]; + if (byte != static_cast(0xff)) { + (*key)[i] = byte + 1; + key->resize(i+1); + return; + } + } + // *key is a run of 0xffs. Leave it alone. + } +}; +} // namespace + +static port::OnceType once = LEVELDB_ONCE_INIT; +static const Comparator* bytewise; + +static void InitModule() { + bytewise = new BytewiseComparatorImpl; +} + +const Comparator* BytewiseComparator() { + port::InitOnce(&once, InitModule); + return bytewise; +} + +} // namespace leveldb diff --git a/util/crc32c.cc b/util/crc32c.cc new file mode 100644 index 00000000..a4115dfc --- /dev/null +++ b/util/crc32c.cc @@ -0,0 +1,388 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A portable implementation of crc32c, optimized to handle +// four bytes at a time. + +#include "util/crc32c.h" + +#include +#ifdef __SSE4_2__ +#include +#endif +#include "util/coding.h" + +namespace leveldb { +namespace crc32c { + +static const uint32_t table0_[256] = { + 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, + 0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb, + 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b, + 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24, + 0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b, + 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384, + 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, + 0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b, + 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a, + 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35, + 0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5, + 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa, + 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, + 0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a, + 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a, + 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595, + 0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48, + 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957, + 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, + 0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198, + 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927, + 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38, + 0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8, + 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7, + 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, + 0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789, + 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859, + 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46, + 0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9, + 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6, + 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, + 0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829, + 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c, + 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93, + 0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043, + 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c, + 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, + 0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc, + 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c, + 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033, + 0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652, + 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d, + 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, + 0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982, + 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d, + 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622, + 0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2, + 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed, + 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, + 0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f, + 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff, + 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0, + 0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f, + 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540, + 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, + 0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f, + 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee, + 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1, + 0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321, + 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e, + 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, + 0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e, + 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e, + 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351 +}; +static const uint32_t table1_[256] = { + 0x00000000, 0x13a29877, 0x274530ee, 0x34e7a899, + 0x4e8a61dc, 0x5d28f9ab, 0x69cf5132, 0x7a6dc945, + 0x9d14c3b8, 0x8eb65bcf, 0xba51f356, 0xa9f36b21, + 0xd39ea264, 0xc03c3a13, 0xf4db928a, 0xe7790afd, + 0x3fc5f181, 0x2c6769f6, 0x1880c16f, 0x0b225918, + 0x714f905d, 0x62ed082a, 0x560aa0b3, 0x45a838c4, + 0xa2d13239, 0xb173aa4e, 0x859402d7, 0x96369aa0, + 0xec5b53e5, 0xfff9cb92, 0xcb1e630b, 0xd8bcfb7c, + 0x7f8be302, 0x6c297b75, 0x58ced3ec, 0x4b6c4b9b, + 0x310182de, 0x22a31aa9, 0x1644b230, 0x05e62a47, + 0xe29f20ba, 0xf13db8cd, 0xc5da1054, 0xd6788823, + 0xac154166, 0xbfb7d911, 0x8b507188, 0x98f2e9ff, + 0x404e1283, 0x53ec8af4, 0x670b226d, 0x74a9ba1a, + 0x0ec4735f, 0x1d66eb28, 0x298143b1, 0x3a23dbc6, + 0xdd5ad13b, 0xcef8494c, 0xfa1fe1d5, 0xe9bd79a2, + 0x93d0b0e7, 0x80722890, 0xb4958009, 0xa737187e, + 0xff17c604, 0xecb55e73, 0xd852f6ea, 0xcbf06e9d, + 0xb19da7d8, 0xa23f3faf, 0x96d89736, 0x857a0f41, + 0x620305bc, 0x71a19dcb, 0x45463552, 0x56e4ad25, + 0x2c896460, 0x3f2bfc17, 0x0bcc548e, 0x186eccf9, + 0xc0d23785, 0xd370aff2, 0xe797076b, 0xf4359f1c, + 0x8e585659, 0x9dface2e, 0xa91d66b7, 0xbabffec0, + 0x5dc6f43d, 0x4e646c4a, 0x7a83c4d3, 0x69215ca4, + 0x134c95e1, 0x00ee0d96, 0x3409a50f, 0x27ab3d78, + 0x809c2506, 0x933ebd71, 0xa7d915e8, 0xb47b8d9f, + 0xce1644da, 0xddb4dcad, 0xe9537434, 0xfaf1ec43, + 0x1d88e6be, 0x0e2a7ec9, 0x3acdd650, 0x296f4e27, + 0x53028762, 0x40a01f15, 0x7447b78c, 0x67e52ffb, + 0xbf59d487, 0xacfb4cf0, 0x981ce469, 0x8bbe7c1e, + 0xf1d3b55b, 0xe2712d2c, 0xd69685b5, 0xc5341dc2, + 0x224d173f, 0x31ef8f48, 0x050827d1, 0x16aabfa6, + 0x6cc776e3, 0x7f65ee94, 0x4b82460d, 0x5820de7a, + 0xfbc3faf9, 0xe861628e, 0xdc86ca17, 0xcf245260, + 0xb5499b25, 0xa6eb0352, 0x920cabcb, 0x81ae33bc, + 0x66d73941, 0x7575a136, 0x419209af, 0x523091d8, + 0x285d589d, 0x3bffc0ea, 0x0f186873, 0x1cbaf004, + 0xc4060b78, 0xd7a4930f, 0xe3433b96, 0xf0e1a3e1, + 0x8a8c6aa4, 0x992ef2d3, 0xadc95a4a, 0xbe6bc23d, + 0x5912c8c0, 0x4ab050b7, 0x7e57f82e, 0x6df56059, + 0x1798a91c, 0x043a316b, 0x30dd99f2, 0x237f0185, + 0x844819fb, 0x97ea818c, 0xa30d2915, 0xb0afb162, + 0xcac27827, 0xd960e050, 0xed8748c9, 0xfe25d0be, + 0x195cda43, 0x0afe4234, 0x3e19eaad, 0x2dbb72da, + 0x57d6bb9f, 0x447423e8, 0x70938b71, 0x63311306, + 0xbb8de87a, 0xa82f700d, 0x9cc8d894, 0x8f6a40e3, + 0xf50789a6, 0xe6a511d1, 0xd242b948, 0xc1e0213f, + 0x26992bc2, 0x353bb3b5, 0x01dc1b2c, 0x127e835b, + 0x68134a1e, 0x7bb1d269, 0x4f567af0, 0x5cf4e287, + 0x04d43cfd, 0x1776a48a, 0x23910c13, 0x30339464, + 0x4a5e5d21, 0x59fcc556, 0x6d1b6dcf, 0x7eb9f5b8, + 0x99c0ff45, 0x8a626732, 0xbe85cfab, 0xad2757dc, + 0xd74a9e99, 0xc4e806ee, 0xf00fae77, 0xe3ad3600, + 0x3b11cd7c, 0x28b3550b, 0x1c54fd92, 0x0ff665e5, + 0x759baca0, 0x663934d7, 0x52de9c4e, 0x417c0439, + 0xa6050ec4, 0xb5a796b3, 0x81403e2a, 0x92e2a65d, + 0xe88f6f18, 0xfb2df76f, 0xcfca5ff6, 0xdc68c781, + 0x7b5fdfff, 0x68fd4788, 0x5c1aef11, 0x4fb87766, + 0x35d5be23, 0x26772654, 0x12908ecd, 0x013216ba, + 0xe64b1c47, 0xf5e98430, 0xc10e2ca9, 0xd2acb4de, + 0xa8c17d9b, 0xbb63e5ec, 0x8f844d75, 0x9c26d502, + 0x449a2e7e, 0x5738b609, 0x63df1e90, 0x707d86e7, + 0x0a104fa2, 0x19b2d7d5, 0x2d557f4c, 0x3ef7e73b, + 0xd98eedc6, 0xca2c75b1, 0xfecbdd28, 0xed69455f, + 0x97048c1a, 0x84a6146d, 0xb041bcf4, 0xa3e32483 +}; +static const uint32_t table2_[256] = { + 0x00000000, 0xa541927e, 0x4f6f520d, 0xea2ec073, + 0x9edea41a, 0x3b9f3664, 0xd1b1f617, 0x74f06469, + 0x38513ec5, 0x9d10acbb, 0x773e6cc8, 0xd27ffeb6, + 0xa68f9adf, 0x03ce08a1, 0xe9e0c8d2, 0x4ca15aac, + 0x70a27d8a, 0xd5e3eff4, 0x3fcd2f87, 0x9a8cbdf9, + 0xee7cd990, 0x4b3d4bee, 0xa1138b9d, 0x045219e3, + 0x48f3434f, 0xedb2d131, 0x079c1142, 0xa2dd833c, + 0xd62de755, 0x736c752b, 0x9942b558, 0x3c032726, + 0xe144fb14, 0x4405696a, 0xae2ba919, 0x0b6a3b67, + 0x7f9a5f0e, 0xdadbcd70, 0x30f50d03, 0x95b49f7d, + 0xd915c5d1, 0x7c5457af, 0x967a97dc, 0x333b05a2, + 0x47cb61cb, 0xe28af3b5, 0x08a433c6, 0xade5a1b8, + 0x91e6869e, 0x34a714e0, 0xde89d493, 0x7bc846ed, + 0x0f382284, 0xaa79b0fa, 0x40577089, 0xe516e2f7, + 0xa9b7b85b, 0x0cf62a25, 0xe6d8ea56, 0x43997828, + 0x37691c41, 0x92288e3f, 0x78064e4c, 0xdd47dc32, + 0xc76580d9, 0x622412a7, 0x880ad2d4, 0x2d4b40aa, + 0x59bb24c3, 0xfcfab6bd, 0x16d476ce, 0xb395e4b0, + 0xff34be1c, 0x5a752c62, 0xb05bec11, 0x151a7e6f, + 0x61ea1a06, 0xc4ab8878, 0x2e85480b, 0x8bc4da75, + 0xb7c7fd53, 0x12866f2d, 0xf8a8af5e, 0x5de93d20, + 0x29195949, 0x8c58cb37, 0x66760b44, 0xc337993a, + 0x8f96c396, 0x2ad751e8, 0xc0f9919b, 0x65b803e5, + 0x1148678c, 0xb409f5f2, 0x5e273581, 0xfb66a7ff, + 0x26217bcd, 0x8360e9b3, 0x694e29c0, 0xcc0fbbbe, + 0xb8ffdfd7, 0x1dbe4da9, 0xf7908dda, 0x52d11fa4, + 0x1e704508, 0xbb31d776, 0x511f1705, 0xf45e857b, + 0x80aee112, 0x25ef736c, 0xcfc1b31f, 0x6a802161, + 0x56830647, 0xf3c29439, 0x19ec544a, 0xbcadc634, + 0xc85da25d, 0x6d1c3023, 0x8732f050, 0x2273622e, + 0x6ed23882, 0xcb93aafc, 0x21bd6a8f, 0x84fcf8f1, + 0xf00c9c98, 0x554d0ee6, 0xbf63ce95, 0x1a225ceb, + 0x8b277743, 0x2e66e53d, 0xc448254e, 0x6109b730, + 0x15f9d359, 0xb0b84127, 0x5a968154, 0xffd7132a, + 0xb3764986, 0x1637dbf8, 0xfc191b8b, 0x595889f5, + 0x2da8ed9c, 0x88e97fe2, 0x62c7bf91, 0xc7862def, + 0xfb850ac9, 0x5ec498b7, 0xb4ea58c4, 0x11abcaba, + 0x655baed3, 0xc01a3cad, 0x2a34fcde, 0x8f756ea0, + 0xc3d4340c, 0x6695a672, 0x8cbb6601, 0x29faf47f, + 0x5d0a9016, 0xf84b0268, 0x1265c21b, 0xb7245065, + 0x6a638c57, 0xcf221e29, 0x250cde5a, 0x804d4c24, + 0xf4bd284d, 0x51fcba33, 0xbbd27a40, 0x1e93e83e, + 0x5232b292, 0xf77320ec, 0x1d5de09f, 0xb81c72e1, + 0xccec1688, 0x69ad84f6, 0x83834485, 0x26c2d6fb, + 0x1ac1f1dd, 0xbf8063a3, 0x55aea3d0, 0xf0ef31ae, + 0x841f55c7, 0x215ec7b9, 0xcb7007ca, 0x6e3195b4, + 0x2290cf18, 0x87d15d66, 0x6dff9d15, 0xc8be0f6b, + 0xbc4e6b02, 0x190ff97c, 0xf321390f, 0x5660ab71, + 0x4c42f79a, 0xe90365e4, 0x032da597, 0xa66c37e9, + 0xd29c5380, 0x77ddc1fe, 0x9df3018d, 0x38b293f3, + 0x7413c95f, 0xd1525b21, 0x3b7c9b52, 0x9e3d092c, + 0xeacd6d45, 0x4f8cff3b, 0xa5a23f48, 0x00e3ad36, + 0x3ce08a10, 0x99a1186e, 0x738fd81d, 0xd6ce4a63, + 0xa23e2e0a, 0x077fbc74, 0xed517c07, 0x4810ee79, + 0x04b1b4d5, 0xa1f026ab, 0x4bdee6d8, 0xee9f74a6, + 0x9a6f10cf, 0x3f2e82b1, 0xd50042c2, 0x7041d0bc, + 0xad060c8e, 0x08479ef0, 0xe2695e83, 0x4728ccfd, + 0x33d8a894, 0x96993aea, 0x7cb7fa99, 0xd9f668e7, + 0x9557324b, 0x3016a035, 0xda386046, 0x7f79f238, + 0x0b899651, 0xaec8042f, 0x44e6c45c, 0xe1a75622, + 0xdda47104, 0x78e5e37a, 0x92cb2309, 0x378ab177, + 0x437ad51e, 0xe63b4760, 0x0c158713, 0xa954156d, + 0xe5f54fc1, 0x40b4ddbf, 0xaa9a1dcc, 0x0fdb8fb2, + 0x7b2bebdb, 0xde6a79a5, 0x3444b9d6, 0x91052ba8 +}; +static const uint32_t table3_[256] = { + 0x00000000, 0xdd45aab8, 0xbf672381, 0x62228939, + 0x7b2231f3, 0xa6679b4b, 0xc4451272, 0x1900b8ca, + 0xf64463e6, 0x2b01c95e, 0x49234067, 0x9466eadf, + 0x8d665215, 0x5023f8ad, 0x32017194, 0xef44db2c, + 0xe964b13d, 0x34211b85, 0x560392bc, 0x8b463804, + 0x924680ce, 0x4f032a76, 0x2d21a34f, 0xf06409f7, + 0x1f20d2db, 0xc2657863, 0xa047f15a, 0x7d025be2, + 0x6402e328, 0xb9474990, 0xdb65c0a9, 0x06206a11, + 0xd725148b, 0x0a60be33, 0x6842370a, 0xb5079db2, + 0xac072578, 0x71428fc0, 0x136006f9, 0xce25ac41, + 0x2161776d, 0xfc24ddd5, 0x9e0654ec, 0x4343fe54, + 0x5a43469e, 0x8706ec26, 0xe524651f, 0x3861cfa7, + 0x3e41a5b6, 0xe3040f0e, 0x81268637, 0x5c632c8f, + 0x45639445, 0x98263efd, 0xfa04b7c4, 0x27411d7c, + 0xc805c650, 0x15406ce8, 0x7762e5d1, 0xaa274f69, + 0xb327f7a3, 0x6e625d1b, 0x0c40d422, 0xd1057e9a, + 0xaba65fe7, 0x76e3f55f, 0x14c17c66, 0xc984d6de, + 0xd0846e14, 0x0dc1c4ac, 0x6fe34d95, 0xb2a6e72d, + 0x5de23c01, 0x80a796b9, 0xe2851f80, 0x3fc0b538, + 0x26c00df2, 0xfb85a74a, 0x99a72e73, 0x44e284cb, + 0x42c2eeda, 0x9f874462, 0xfda5cd5b, 0x20e067e3, + 0x39e0df29, 0xe4a57591, 0x8687fca8, 0x5bc25610, + 0xb4868d3c, 0x69c32784, 0x0be1aebd, 0xd6a40405, + 0xcfa4bccf, 0x12e11677, 0x70c39f4e, 0xad8635f6, + 0x7c834b6c, 0xa1c6e1d4, 0xc3e468ed, 0x1ea1c255, + 0x07a17a9f, 0xdae4d027, 0xb8c6591e, 0x6583f3a6, + 0x8ac7288a, 0x57828232, 0x35a00b0b, 0xe8e5a1b3, + 0xf1e51979, 0x2ca0b3c1, 0x4e823af8, 0x93c79040, + 0x95e7fa51, 0x48a250e9, 0x2a80d9d0, 0xf7c57368, + 0xeec5cba2, 0x3380611a, 0x51a2e823, 0x8ce7429b, + 0x63a399b7, 0xbee6330f, 0xdcc4ba36, 0x0181108e, + 0x1881a844, 0xc5c402fc, 0xa7e68bc5, 0x7aa3217d, + 0x52a0c93f, 0x8fe56387, 0xedc7eabe, 0x30824006, + 0x2982f8cc, 0xf4c75274, 0x96e5db4d, 0x4ba071f5, + 0xa4e4aad9, 0x79a10061, 0x1b838958, 0xc6c623e0, + 0xdfc69b2a, 0x02833192, 0x60a1b8ab, 0xbde41213, + 0xbbc47802, 0x6681d2ba, 0x04a35b83, 0xd9e6f13b, + 0xc0e649f1, 0x1da3e349, 0x7f816a70, 0xa2c4c0c8, + 0x4d801be4, 0x90c5b15c, 0xf2e73865, 0x2fa292dd, + 0x36a22a17, 0xebe780af, 0x89c50996, 0x5480a32e, + 0x8585ddb4, 0x58c0770c, 0x3ae2fe35, 0xe7a7548d, + 0xfea7ec47, 0x23e246ff, 0x41c0cfc6, 0x9c85657e, + 0x73c1be52, 0xae8414ea, 0xcca69dd3, 0x11e3376b, + 0x08e38fa1, 0xd5a62519, 0xb784ac20, 0x6ac10698, + 0x6ce16c89, 0xb1a4c631, 0xd3864f08, 0x0ec3e5b0, + 0x17c35d7a, 0xca86f7c2, 0xa8a47efb, 0x75e1d443, + 0x9aa50f6f, 0x47e0a5d7, 0x25c22cee, 0xf8878656, + 0xe1873e9c, 0x3cc29424, 0x5ee01d1d, 0x83a5b7a5, + 0xf90696d8, 0x24433c60, 0x4661b559, 0x9b241fe1, + 0x8224a72b, 0x5f610d93, 0x3d4384aa, 0xe0062e12, + 0x0f42f53e, 0xd2075f86, 0xb025d6bf, 0x6d607c07, + 0x7460c4cd, 0xa9256e75, 0xcb07e74c, 0x16424df4, + 0x106227e5, 0xcd278d5d, 0xaf050464, 0x7240aedc, + 0x6b401616, 0xb605bcae, 0xd4273597, 0x09629f2f, + 0xe6264403, 0x3b63eebb, 0x59416782, 0x8404cd3a, + 0x9d0475f0, 0x4041df48, 0x22635671, 0xff26fcc9, + 0x2e238253, 0xf36628eb, 0x9144a1d2, 0x4c010b6a, + 0x5501b3a0, 0x88441918, 0xea669021, 0x37233a99, + 0xd867e1b5, 0x05224b0d, 0x6700c234, 0xba45688c, + 0xa345d046, 0x7e007afe, 0x1c22f3c7, 0xc167597f, + 0xc747336e, 0x1a0299d6, 0x782010ef, 0xa565ba57, + 0xbc65029d, 0x6120a825, 0x0302211c, 0xde478ba4, + 0x31035088, 0xec46fa30, 0x8e647309, 0x5321d9b1, + 0x4a21617b, 0x9764cbc3, 0xf54642fa, 0x2803e842 +}; + +// Used to fetch a naturally-aligned 32-bit word in little endian byte-order +static inline uint32_t LE_LOAD32(const uint8_t *p) { + return DecodeFixed32(reinterpret_cast(p)); +} + +static inline uint64_t LE_LOAD64(const uint8_t *p) { + return DecodeFixed64(reinterpret_cast(p)); +} + +static inline void Slow_CRC32(uint64_t* l, uint8_t const **p) { + uint32_t c = *l ^ LE_LOAD32(*p); + *p += 4; + *l = table3_[c & 0xff] ^ + table2_[(c >> 8) & 0xff] ^ + table1_[(c >> 16) & 0xff] ^ + table0_[c >> 24]; + // DO it twice. + c = *l ^ LE_LOAD32(*p); + *p += 4; + *l = table3_[c & 0xff] ^ + table2_[(c >> 8) & 0xff] ^ + table1_[(c >> 16) & 0xff] ^ + table0_[c >> 24]; +} + +static inline void Fast_CRC32(uint64_t* l, uint8_t const **p) { + #ifdef __SSE4_2__ + *l = _mm_crc32_u64(*l, LE_LOAD64(*p)); + *p += 8; + #else + Slow_CRC32(l, p); + #endif +} + +// Detect if SS42 or not. +static bool isSSE42() { + #ifdef __GNUC__ + uint32_t c_; + uint32_t d_; + __asm__("cpuid" : "=c"(c_), "=d"(d_) : "a"(1) : "ebx"); + return c_ & (1U << 20); // copied from CpuId.h in Folly. + #else + return false; + #endif +} + +typedef void (*Function)(uint64_t*, uint8_t const**); +static Function func = nullptr; + +static inline Function Choose_CRC32() { + return isSSE42() ? Fast_CRC32 : Slow_CRC32; +} + +static inline void CRC32(uint64_t* l, uint8_t const **p) { + if (func != nullptr) { + return func(l, p); + } + func = Choose_CRC32(); + func(l, p); +} + +uint32_t Extend(uint32_t crc, const char* buf, size_t size) { + const uint8_t *p = reinterpret_cast(buf); + const uint8_t *e = p + size; + uint64_t l = crc ^ 0xffffffffu; + +// Align n to (1 << m) byte boundary +#define ALIGN(n, m) ((n + ((1 << m) - 1)) & ~((1 << m) - 1)) + +#define STEP1 do { \ + int c = (l & 0xff) ^ *p++; \ + l = table0_[c] ^ (l >> 8); \ +} while (0) + + + // Point x at first 16-byte aligned byte in string. This might be + // just past the end of the string. + const uintptr_t pval = reinterpret_cast(p); + const uint8_t* x = reinterpret_cast(ALIGN(pval, 4)); + if (x <= e) { + // Process bytes until finished or p is 16-byte aligned + while (p != x) { + STEP1; + } + } + // Process bytes 16 at a time + while ((e-p) >= 16) { + CRC32(&l, &p); + CRC32(&l, &p); + } + // Process bytes 8 at a time + while ((e-p) >= 8) { + CRC32(&l, &p); + } + // Process the last few bytes + while (p != e) { + STEP1; + } +#undef STEP1 +#undef ALIGN + return l ^ 0xffffffffu; +} + +} // namespace crc32c +} // namespace leveldb diff --git a/util/crc32c.h b/util/crc32c.h new file mode 100644 index 00000000..1d7e5c07 --- /dev/null +++ b/util/crc32c.h @@ -0,0 +1,45 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_CRC32C_H_ +#define STORAGE_LEVELDB_UTIL_CRC32C_H_ + +#include +#include + +namespace leveldb { +namespace crc32c { + +// Return the crc32c of concat(A, data[0,n-1]) where init_crc is the +// crc32c of some string A. Extend() is often used to maintain the +// crc32c of a stream of data. +extern uint32_t Extend(uint32_t init_crc, const char* data, size_t n); + +// Return the crc32c of data[0,n-1] +inline uint32_t Value(const char* data, size_t n) { + return Extend(0, data, n); +} + +static const uint32_t kMaskDelta = 0xa282ead8ul; + +// Return a masked representation of crc. +// +// Motivation: it is problematic to compute the CRC of a string that +// contains embedded CRCs. Therefore we recommend that CRCs stored +// somewhere (e.g., in files) should be masked before being stored. +inline uint32_t Mask(uint32_t crc) { + // Rotate right by 15 bits and add a constant. + return ((crc >> 15) | (crc << 17)) + kMaskDelta; +} + +// Return the crc whose masked representation is masked_crc. +inline uint32_t Unmask(uint32_t masked_crc) { + uint32_t rot = masked_crc - kMaskDelta; + return ((rot >> 17) | (rot << 15)); +} + +} // namespace crc32c +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_CRC32C_H_ diff --git a/util/crc32c_test.cc b/util/crc32c_test.cc new file mode 100644 index 00000000..28ae5b79 --- /dev/null +++ b/util/crc32c_test.cc @@ -0,0 +1,72 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/crc32c.h" +#include "util/testharness.h" + +namespace leveldb { +namespace crc32c { + +class CRC { }; + +TEST(CRC, StandardResults) { + // From rfc3720 section B.4. + char buf[32]; + + memset(buf, 0, sizeof(buf)); + ASSERT_EQ(0x8a9136aaU, Value(buf, sizeof(buf))); + + memset(buf, 0xff, sizeof(buf)); + ASSERT_EQ(0x62a8ab43U, Value(buf, sizeof(buf))); + + for (int i = 0; i < 32; i++) { + buf[i] = i; + } + ASSERT_EQ(0x46dd794eU, Value(buf, sizeof(buf))); + + for (int i = 0; i < 32; i++) { + buf[i] = 31 - i; + } + ASSERT_EQ(0x113fdb5cU, Value(buf, sizeof(buf))); + + unsigned char data[48] = { + 0x01, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x18, + 0x28, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + }; + ASSERT_EQ(0xd9963a56, Value(reinterpret_cast(data), sizeof(data))); +} + +TEST(CRC, Values) { + ASSERT_NE(Value("a", 1), Value("foo", 3)); +} + +TEST(CRC, Extend) { + ASSERT_EQ(Value("hello world", 11), + Extend(Value("hello ", 6), "world", 5)); +} + +TEST(CRC, Mask) { + uint32_t crc = Value("foo", 3); + ASSERT_NE(crc, Mask(crc)); + ASSERT_NE(crc, Mask(Mask(crc))); + ASSERT_EQ(crc, Unmask(Mask(crc))); + ASSERT_EQ(crc, Unmask(Unmask(Mask(Mask(crc))))); +} + +} // namespace crc32c +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/util/env.cc b/util/env.cc new file mode 100644 index 00000000..0aaa03ae --- /dev/null +++ b/util/env.cc @@ -0,0 +1,100 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/env.h" + +namespace leveldb { + +Env::~Env() { +} + +SequentialFile::~SequentialFile() { +} + +RandomAccessFile::~RandomAccessFile() { +} + +WritableFile::~WritableFile() { +} + +Logger::~Logger() { +} + +FileLock::~FileLock() { +} + +void Log(Logger* info_log, const char* format, ...) { + if (info_log) { + va_list ap; + va_start(ap, format); + info_log->Logv(format, ap); + va_end(ap); + } +} + +void Log(const shared_ptr& info_log, const char* format, ...) { + if (info_log) { + va_list ap; + va_start(ap, format); + info_log->Logv(format, ap); + va_end(ap); + } +} + +static Status DoWriteStringToFile(Env* env, const Slice& data, + const std::string& fname, + bool should_sync) { + unique_ptr file; + Status s = env->NewWritableFile(fname, &file); + if (!s.ok()) { + return s; + } + s = file->Append(data); + if (s.ok() && should_sync) { + s = file->Sync(); + } + if (!s.ok()) { + env->DeleteFile(fname); + } + return s; +} + +Status WriteStringToFile(Env* env, const Slice& data, + const std::string& fname) { + return DoWriteStringToFile(env, data, fname, false); +} + +Status WriteStringToFileSync(Env* env, const Slice& data, + const std::string& fname) { + return DoWriteStringToFile(env, data, fname, true); +} + +Status ReadFileToString(Env* env, const std::string& fname, std::string* data) { + data->clear(); + unique_ptr file; + Status s = env->NewSequentialFile(fname, &file); + if (!s.ok()) { + return s; + } + static const int kBufferSize = 8192; + char* space = new char[kBufferSize]; + while (true) { + Slice fragment; + s = file->Read(kBufferSize, &fragment, space); + if (!s.ok()) { + break; + } + data->append(fragment.data(), fragment.size()); + if (fragment.empty()) { + break; + } + } + delete[] space; + return s; +} + +EnvWrapper::~EnvWrapper() { +} + +} // namespace leveldb diff --git a/util/env_hdfs.cc b/util/env_hdfs.cc new file mode 100644 index 00000000..4ebefb52 --- /dev/null +++ b/util/env_hdfs.cc @@ -0,0 +1,524 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// Copyright (c) 2012 Facebook. All rights reserved. + +#ifdef USE_HDFS +#ifndef LEVELDB_HDFS_FILE_C +#define LEVELDB_HDFS_FILE_C + +#include +#include +#include +#include +#include +#include +#include "leveldb/env.h" +#include "leveldb/status.h" +#include "hdfs/hdfs.h" +#include "hdfs/env_hdfs.h" + +// +// This file defines an HDFS environment for leveldb. It uses the libhdfs +// api to access HDFS. All HDFS files created by one instance of leveldb +// will reside on the same HDFS cluster. +// + +namespace leveldb { + +namespace { + +// Log error message +static Status IOError(const std::string& context, int err_number) { + return Status::IOError(context, strerror(err_number)); +} + +// assume that there is one global logger for now. It is not thread-safe, +// but need not be because the logger is initialized at db-open time. +static Logger* mylog = nullptr; + +// Used for reading a file from HDFS. It implements both sequential-read +// access methods as well as random read access methods. +class HdfsReadableFile: virtual public SequentialFile, virtual public RandomAccessFile { + private: + hdfsFS fileSys_; + std::string filename_; + hdfsFile hfile_; + + public: + HdfsReadableFile(hdfsFS fileSys, const std::string& fname) + : fileSys_(fileSys), filename_(fname), hfile_(nullptr) { + Log(mylog, "[hdfs] HdfsReadableFile opening file %s\n", + filename_.c_str()); + hfile_ = hdfsOpenFile(fileSys_, filename_.c_str(), O_RDONLY, 0, 0, 0); + Log(mylog, "[hdfs] HdfsReadableFile opened file %s hfile_=0x%p\n", + filename_.c_str(), hfile_); + } + + virtual ~HdfsReadableFile() { + Log(mylog, "[hdfs] HdfsReadableFile closing file %s\n", + filename_.c_str()); + hdfsCloseFile(fileSys_, hfile_); + Log(mylog, "[hdfs] HdfsReadableFile closed file %s\n", + filename_.c_str()); + hfile_ = nullptr; + } + + bool isValid() { + return hfile_ != nullptr; + } + + // sequential access, read data at current offset in file + virtual Status Read(size_t n, Slice* result, char* scratch) { + Status s; + Log(mylog, "[hdfs] HdfsReadableFile reading %s %ld\n", + filename_.c_str(), n); + size_t bytes_read = hdfsRead(fileSys_, hfile_, scratch, (tSize)n); + Log(mylog, "[hdfs] HdfsReadableFile read %s\n", filename_.c_str()); + *result = Slice(scratch, bytes_read); + if (bytes_read < n) { + if (feof()) { + // We leave status as ok if we hit the end of the file + } else { + // A partial read with an error: return a non-ok status + s = IOError(filename_, errno); + } + } + return s; + } + + // random access, read data from specified offset in file + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const { + Status s; + Log(mylog, "[hdfs] HdfsReadableFile preading %s\n", filename_.c_str()); + ssize_t bytes_read = hdfsPread(fileSys_, hfile_, offset, + (void*)scratch, (tSize)n); + Log(mylog, "[hdfs] HdfsReadableFile pread %s\n", filename_.c_str()); + *result = Slice(scratch, (bytes_read < 0) ? 0 : bytes_read); + if (bytes_read < 0) { + // An error: return a non-ok status + s = IOError(filename_, errno); + } + return s; + } + + virtual Status Skip(uint64_t n) { + Log(mylog, "[hdfs] HdfsReadableFile skip %s\n", filename_.c_str()); + // get current offset from file + tOffset current = hdfsTell(fileSys_, hfile_); + if (current < 0) { + return IOError(filename_, errno); + } + // seek to new offset in file + tOffset newoffset = current + n; + int val = hdfsSeek(fileSys_, hfile_, newoffset); + if (val < 0) { + return IOError(filename_, errno); + } + return Status::OK(); + } + + private: + + // returns true if we are at the end of file, false otherwise + bool feof() { + Log(mylog, "[hdfs] HdfsReadableFile feof %s\n", filename_.c_str()); + if (hdfsTell(fileSys_, hfile_) == fileSize()) { + return true; + } + return false; + } + + // the current size of the file + tOffset fileSize() { + Log(mylog, "[hdfs] HdfsReadableFile fileSize %s\n", filename_.c_str()); + hdfsFileInfo* pFileInfo = hdfsGetPathInfo(fileSys_, filename_.c_str()); + tOffset size = 0L; + if (pFileInfo != nullptr) { + size = pFileInfo->mSize; + hdfsFreeFileInfo(pFileInfo, 1); + } else { + throw leveldb::HdfsFatalException("fileSize on unknown file " + + filename_); + } + return size; + } +}; + +// Appends to an existing file in HDFS. +class HdfsWritableFile: public WritableFile { + private: + hdfsFS fileSys_; + std::string filename_; + hdfsFile hfile_; + + public: + HdfsWritableFile(hdfsFS fileSys, const std::string& fname) + : fileSys_(fileSys), filename_(fname) , hfile_(nullptr) { + Log(mylog, "[hdfs] HdfsWritableFile opening %s\n", filename_.c_str()); + hfile_ = hdfsOpenFile(fileSys_, filename_.c_str(), O_WRONLY, 0, 0, 0); + Log(mylog, "[hdfs] HdfsWritableFile opened %s\n", filename_.c_str()); + assert(hfile_ != nullptr); + } + virtual ~HdfsWritableFile() { + if (hfile_ != nullptr) { + Log(mylog, "[hdfs] HdfsWritableFile closing %s\n", filename_.c_str()); + hdfsCloseFile(fileSys_, hfile_); + Log(mylog, "[hdfs] HdfsWritableFile closed %s\n", filename_.c_str()); + hfile_ = nullptr; + } + } + + // If the file was successfully created, then this returns true. + // Otherwise returns false. + bool isValid() { + return hfile_ != nullptr; + } + + // The name of the file, mostly needed for debug logging. + const std::string& getName() { + return filename_; + } + + virtual Status Append(const Slice& data) { + Log(mylog, "[hdfs] HdfsWritableFile Append %s\n", filename_.c_str()); + const char* src = data.data(); + size_t left = data.size(); + size_t ret = hdfsWrite(fileSys_, hfile_, src, left); + Log(mylog, "[hdfs] HdfsWritableFile Appended %s\n", filename_.c_str()); + if (ret != left) { + return IOError(filename_, errno); + } + return Status::OK(); + } + + virtual Status Flush() { + return Status::OK(); + } + + virtual Status Sync() { + Status s; + Log(mylog, "[hdfs] HdfsWritableFile Sync %s\n", filename_.c_str()); + if (hdfsFlush(fileSys_, hfile_) == -1) { + return IOError(filename_, errno); + } + if (hdfsSync(fileSys_, hfile_) == -1) { + return IOError(filename_, errno); + } + Log(mylog, "[hdfs] HdfsWritableFile Synced %s\n", filename_.c_str()); + return Status::OK(); + } + + // This is used by HdfsLogger to write data to the debug log file + virtual Status Append(const char* src, size_t size) { + if (hdfsWrite(fileSys_, hfile_, src, size) != (tSize)size) { + return IOError(filename_, errno); + } + return Status::OK(); + } + + virtual Status Close() { + Log(mylog, "[hdfs] HdfsWritableFile closing %s\n", filename_.c_str()); + if (hdfsCloseFile(fileSys_, hfile_) != 0) { + return IOError(filename_, errno); + } + Log(mylog, "[hdfs] HdfsWritableFile closed %s\n", filename_.c_str()); + hfile_ = nullptr; + return Status::OK(); + } +}; + +// The object that implements the debug logs to reside in HDFS. +class HdfsLogger : public Logger { + private: + HdfsWritableFile* file_; + uint64_t (*gettid_)(); // Return the thread id for the current thread + + public: + HdfsLogger(HdfsWritableFile* f, uint64_t (*gettid)()) + : file_(f), gettid_(gettid) { + Log(mylog, "[hdfs] HdfsLogger opened %s\n", + file_->getName().c_str()); + } + + virtual ~HdfsLogger() { + Log(mylog, "[hdfs] HdfsLogger closed %s\n", + file_->getName().c_str()); + delete file_; + if (mylog != nullptr && mylog == this) { + mylog = nullptr; + } + } + + virtual void Logv(const char* format, va_list ap) { + const uint64_t thread_id = (*gettid_)(); + + // We try twice: the first time with a fixed-size stack allocated buffer, + // and the second time with a much larger dynamically allocated buffer. + char buffer[500]; + for (int iter = 0; iter < 2; iter++) { + char* base; + int bufsize; + if (iter == 0) { + bufsize = sizeof(buffer); + base = buffer; + } else { + bufsize = 30000; + base = new char[bufsize]; + } + char* p = base; + char* limit = base + bufsize; + + struct timeval now_tv; + gettimeofday(&now_tv, nullptr); + const time_t seconds = now_tv.tv_sec; + struct tm t; + localtime_r(&seconds, &t); + p += snprintf(p, limit - p, + "%04d/%02d/%02d-%02d:%02d:%02d.%06d %llx ", + t.tm_year + 1900, + t.tm_mon + 1, + t.tm_mday, + t.tm_hour, + t.tm_min, + t.tm_sec, + static_cast(now_tv.tv_usec), + static_cast(thread_id)); + + // Print the message + if (p < limit) { + va_list backup_ap; + va_copy(backup_ap, ap); + p += vsnprintf(p, limit - p, format, backup_ap); + va_end(backup_ap); + } + + // Truncate to available space if necessary + if (p >= limit) { + if (iter == 0) { + continue; // Try again with larger buffer + } else { + p = limit - 1; + } + } + + // Add newline if necessary + if (p == base || p[-1] != '\n') { + *p++ = '\n'; + } + + assert(p <= limit); + file_->Append(base, p-base); + file_->Flush(); + if (base != buffer) { + delete[] base; + } + break; + } + } +}; + +} // namespace + +// Finally, the hdfs environment + +// open a file for sequential reading +Status HdfsEnv::NewSequentialFile(const std::string& fname, + SequentialFile** result) { + HdfsReadableFile* f = new HdfsReadableFile(fileSys_, fname); + if (f == nullptr) { + *result = nullptr; + return IOError(fname, errno); + } + *result = dynamic_cast(f); + return Status::OK(); +} + +// open a file for random reading +Status HdfsEnv::NewRandomAccessFile(const std::string& fname, + RandomAccessFile** result) { + HdfsReadableFile* f = new HdfsReadableFile(fileSys_, fname); + if (f == nullptr) { + *result = nullptr; + return IOError(fname, errno); + } + *result = dynamic_cast(f); + return Status::OK(); +} + +// create a new file for writing +Status HdfsEnv::NewWritableFile(const std::string& fname, + WritableFile** result) { + Status s; + HdfsWritableFile* f = new HdfsWritableFile(fileSys_, fname); + if (f == nullptr || !f->isValid()) { + *result = nullptr; + return IOError(fname, errno); + } + *result = dynamic_cast(f); + return Status::OK(); +} + +bool HdfsEnv::FileExists(const std::string& fname) { + int value = hdfsExists(fileSys_, fname.c_str()); + if (value == 0) { + return true; + } + return false; +} + +Status HdfsEnv::GetChildren(const std::string& path, + std::vector* result) { + int value = hdfsExists(fileSys_, path.c_str()); + switch (value) { + case 0: { + int numEntries = 0; + hdfsFileInfo* pHdfsFileInfo = 0; + pHdfsFileInfo = hdfsListDirectory(fileSys_, path.c_str(), &numEntries); + if (numEntries >= 0) { + for(int i = 0; i < numEntries; i++) { + char* pathname = pHdfsFileInfo[i].mName; + char* filename = rindex(pathname, '/'); + if (filename != nullptr) { + result->push_back(filename+1); + } + } + if (pHdfsFileInfo != nullptr) { + hdfsFreeFileInfo(pHdfsFileInfo, numEntries); + } + } else { + // numEntries < 0 indicates error + Log(mylog, "hdfsListDirectory call failed with error "); + throw HdfsFatalException("hdfsListDirectory call failed negative error.\n"); + } + break; + } + case 1: // directory does not exist, exit + break; + default: // anything else should be an error + Log(mylog, "hdfsListDirectory call failed with error "); + throw HdfsFatalException("hdfsListDirectory call failed with error.\n"); + } + return Status::OK(); +} + +Status HdfsEnv::DeleteFile(const std::string& fname) { + if (hdfsDelete(fileSys_, fname.c_str()) == 0) { + return Status::OK(); + } + return IOError(fname, errno); +}; + +Status HdfsEnv::CreateDir(const std::string& name) { + if (hdfsCreateDirectory(fileSys_, name.c_str()) == 0) { + return Status::OK(); + } + return IOError(name, errno); +}; + +Status HdfsEnv::CreateDirIfMissing(const std::string& name) { + const int value = hdfsExists(fileSys_, name.c_str()); + // Not atomic. state might change b/w hdfsExists and CreateDir. + if (value == 0) { + return Status::OK(); + } else { + return CreateDir(name); + } +}; + +Status HdfsEnv::DeleteDir(const std::string& name) { + return DeleteFile(name); +}; + +Status HdfsEnv::GetFileSize(const std::string& fname, uint64_t* size) { + *size = 0L; + hdfsFileInfo* pFileInfo = hdfsGetPathInfo(fileSys_, fname.c_str()); + if (pFileInfo != nullptr) { + *size = pFileInfo->mSize; + hdfsFreeFileInfo(pFileInfo, 1); + return Status::OK(); + } + return IOError(fname, errno); +} + +Status HdfsEnv::GetFileModificationTime(const std::string& fname, + uint64_t* time) { + hdfsFileInfo* pFileInfo = hdfsGetPathInfo(fileSys_, fname.c_str()); + if (pFileInfo != nullptr) { + *time = static_cast(pFileInfo->mLastMod); + hdfsFreeFileInfo(pFileInfo, 1); + return Status::OK(); + } + return IOError(fname, errno); + +} + +// The rename is not atomic. HDFS does not allow a renaming if the +// target already exists. So, we delete the target before attemting the +// rename. +Status HdfsEnv::RenameFile(const std::string& src, const std::string& target) { + hdfsDelete(fileSys_, target.c_str()); + if (hdfsRename(fileSys_, src.c_str(), target.c_str()) == 0) { + return Status::OK(); + } + return IOError(src, errno); +} + +Status HdfsEnv::LockFile(const std::string& fname, FileLock** lock) { + // there isn's a very good way to atomically check and create + // a file via libhdfs + *lock = nullptr; + return Status::OK(); +} + +Status HdfsEnv::UnlockFile(FileLock* lock) { + return Status::OK(); +} + +Status HdfsEnv::NewLogger(const std::string& fname, + shared_ptr* result) { + HdfsWritableFile* f = new HdfsWritableFile(fileSys_, fname); + if (f == nullptr || !f->isValid()) { + *result = nullptr; + return IOError(fname, errno); + } + HdfsLogger* h = new HdfsLogger(f, &HdfsEnv::gettid); + *result = h; + if (mylog == nullptr) { + // mylog = h; // uncomment this for detailed logging + } + return Status::OK(); +} + +} // namespace leveldb + +#endif // LEVELDB_HDFS_FILE_C + +#else // USE_HDFS + +// dummy placeholders used when HDFS is not available +#include "leveldb/env.h" +#include "hdfs/env_hdfs.h" +namespace leveldb { + Status HdfsEnv::NewSequentialFile(const std::string& fname, + unique_ptr* result) { + return Status::NotSupported("Not compiled with hdfs support"); + } +} + +#endif diff --git a/util/env_posix.cc b/util/env_posix.cc new file mode 100644 index 00000000..e9b561ab --- /dev/null +++ b/util/env_posix.cc @@ -0,0 +1,978 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(OS_LINUX) +#include +#endif +#if defined(LEVELDB_PLATFORM_ANDROID) +#include +#endif +#include "leveldb/env.h" +#include "leveldb/slice.h" +#include "port/port.h" +#include "util/coding.h" +#include "util/logging.h" +#include "util/posix_logger.h" + +bool useOsBuffer = 1; // cache data in OS buffers +bool useFsReadAhead = 1; // allow filesystem to do readaheads +bool useMmapRead = 0; // do not use mmaps for reading files +bool useMmapWrite = 1; // use mmaps for appending to files + +namespace leveldb { + +namespace { + +// list of pathnames that are locked +static std::set lockedFiles; +static port::Mutex mutex_lockedFiles; + +static Status IOError(const std::string& context, int err_number) { + return Status::IOError(context, strerror(err_number)); +} + +class PosixSequentialFile: public SequentialFile { + private: + std::string filename_; + FILE* file_; + + public: + PosixSequentialFile(const std::string& fname, FILE* f) + : filename_(fname), file_(f) { } + virtual ~PosixSequentialFile() { fclose(file_); } + + virtual Status Read(size_t n, Slice* result, char* scratch) { + Status s; + size_t r = fread_unlocked(scratch, 1, n, file_); + *result = Slice(scratch, r); + if (r < n) { + if (feof(file_)) { + // We leave status as ok if we hit the end of the file + } else { + // A partial read with an error: return a non-ok status + s = IOError(filename_, errno); + } + } + return s; + } + + virtual Status Skip(uint64_t n) { + if (fseek(file_, n, SEEK_CUR)) { + return IOError(filename_, errno); + } + return Status::OK(); + } +}; + +// pread() based random-access +class PosixRandomAccessFile: public RandomAccessFile { + private: + std::string filename_; + int fd_; + + public: + PosixRandomAccessFile(const std::string& fname, int fd) + : filename_(fname), fd_(fd) { + if (!useFsReadAhead) { + // disable read-aheads + posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM); + } + } + virtual ~PosixRandomAccessFile() { close(fd_); } + + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const { + Status s; + ssize_t r = pread(fd_, scratch, n, static_cast(offset)); + *result = Slice(scratch, (r < 0) ? 0 : r); + if (r < 0) { + // An error: return a non-ok status + s = IOError(filename_, errno); + } + if (!useOsBuffer) { + // we need to fadvise away the entire range of pages because + // we do not want readahead pages to be cached. + posix_fadvise(fd_, 0, 0, POSIX_FADV_DONTNEED); // free OS pages + } + return s; + } + +#if defined(OS_LINUX) + virtual size_t GetUniqueId(char* id, size_t max_size) const { + // TODO: possibly allow this function to handle tighter bounds. + if (max_size < kMaxVarint64Length*3) { + return 0; + } + + struct stat buf; + int result = fstat(fd_, &buf); + if (result == -1) { + return 0; + } + + long version = 0; + result = ioctl(fd_, FS_IOC_GETVERSION, &version); + if (result == -1) { + return 0; + } + uint64_t uversion = (uint64_t)version; + + char* rid = id; + rid = EncodeVarint64(rid, buf.st_dev); + rid = EncodeVarint64(rid, buf.st_ino); + rid = EncodeVarint64(rid, uversion); + assert(rid >= id); + return static_cast(rid-id); + } +#endif +}; + +// mmap() based random-access +class PosixMmapReadableFile: public RandomAccessFile { + private: + std::string filename_; + void* mmapped_region_; + size_t length_; + + public: + // base[0,length-1] contains the mmapped contents of the file. + PosixMmapReadableFile(const std::string& fname, void* base, size_t length) + : filename_(fname), mmapped_region_(base), length_(length) { } + virtual ~PosixMmapReadableFile() { munmap(mmapped_region_, length_); } + + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const { + Status s; + if (offset + n > length_) { + *result = Slice(); + s = IOError(filename_, EINVAL); + } else { + *result = Slice(reinterpret_cast(mmapped_region_) + offset, n); + } + return s; + } +}; + +// We preallocate up to an extra megabyte and use memcpy to append new +// data to the file. This is safe since we either properly close the +// file before reading from it, or for log files, the reading code +// knows enough to skip zero suffixes. +class PosixMmapFile : public WritableFile { + private: + std::string filename_; + int fd_; + size_t page_size_; + size_t map_size_; // How much extra memory to map at a time + char* base_; // The mapped region + char* limit_; // Limit of the mapped region + char* dst_; // Where to write next (in range [base_,limit_]) + char* last_sync_; // Where have we synced up to + uint64_t file_offset_; // Offset of base_ in file + + // Have we done an munmap of unsynced data? + bool pending_sync_; + + // Roundup x to a multiple of y + static size_t Roundup(size_t x, size_t y) { + return ((x + y - 1) / y) * y; + } + + size_t TruncateToPageBoundary(size_t s) { + s -= (s & (page_size_ - 1)); + assert((s % page_size_) == 0); + return s; + } + + bool UnmapCurrentRegion() { + bool result = true; + if (base_ != nullptr) { + if (last_sync_ < limit_) { + // Defer syncing this data until next Sync() call, if any + pending_sync_ = true; + } + if (munmap(base_, limit_ - base_) != 0) { + result = false; + } + file_offset_ += limit_ - base_; + base_ = nullptr; + limit_ = nullptr; + last_sync_ = nullptr; + dst_ = nullptr; + + // Increase the amount we map the next time, but capped at 1MB + if (map_size_ < (1<<20)) { + map_size_ *= 2; + } + } + return result; + } + + bool MapNewRegion() { + assert(base_ == nullptr); + if (ftruncate(fd_, file_offset_ + map_size_) < 0) { + return false; + } + void* ptr = mmap(nullptr, map_size_, PROT_READ | PROT_WRITE, MAP_SHARED, + fd_, file_offset_); + if (ptr == MAP_FAILED) { + return false; + } + base_ = reinterpret_cast(ptr); + limit_ = base_ + map_size_; + dst_ = base_; + last_sync_ = base_; + return true; + } + + public: + PosixMmapFile(const std::string& fname, int fd, size_t page_size) + : filename_(fname), + fd_(fd), + page_size_(page_size), + map_size_(Roundup(65536, page_size)), + base_(nullptr), + limit_(nullptr), + dst_(nullptr), + last_sync_(nullptr), + file_offset_(0), + pending_sync_(false) { + assert((page_size & (page_size - 1)) == 0); + } + + + ~PosixMmapFile() { + if (fd_ >= 0) { + PosixMmapFile::Close(); + } + } + + virtual Status Append(const Slice& data) { + const char* src = data.data(); + size_t left = data.size(); + PrepareWrite(GetFileSize(), left); + while (left > 0) { + assert(base_ <= dst_); + assert(dst_ <= limit_); + size_t avail = limit_ - dst_; + if (avail == 0) { + if (!UnmapCurrentRegion() || + !MapNewRegion()) { + return IOError(filename_, errno); + } + } + + size_t n = (left <= avail) ? left : avail; + memcpy(dst_, src, n); + dst_ += n; + src += n; + left -= n; + } + return Status::OK(); + } + + virtual Status Close() { + Status s; + size_t unused = limit_ - dst_; + if (!UnmapCurrentRegion()) { + s = IOError(filename_, errno); + } else if (unused > 0) { + // Trim the extra space at the end of the file + if (ftruncate(fd_, file_offset_ - unused) < 0) { + s = IOError(filename_, errno); + } + } + + if (close(fd_) < 0) { + if (s.ok()) { + s = IOError(filename_, errno); + } + } + + fd_ = -1; + base_ = nullptr; + limit_ = nullptr; + return s; + } + + virtual Status Flush() { + return Status::OK(); + } + + virtual Status Sync() { + Status s; + + if (pending_sync_) { + // Some unmapped data was not synced + pending_sync_ = false; + if (fdatasync(fd_) < 0) { + s = IOError(filename_, errno); + } + } + + if (dst_ > last_sync_) { + // Find the beginnings of the pages that contain the first and last + // bytes to be synced. + size_t p1 = TruncateToPageBoundary(last_sync_ - base_); + size_t p2 = TruncateToPageBoundary(dst_ - base_ - 1); + last_sync_ = dst_; + if (msync(base_ + p1, p2 - p1 + page_size_, MS_SYNC) < 0) { + s = IOError(filename_, errno); + } + } + + return s; + } + + /** + * Flush data as well as metadata to stable storage. + */ + virtual Status Fsync() { + if (pending_sync_) { + // Some unmapped data was not synced + pending_sync_ = false; + if (fsync(fd_) < 0) { + return IOError(filename_, errno); + } + } + // This invocation to Sync will not issue the call to + // fdatasync because pending_sync_ has already been cleared. + return Sync(); + } + + /** + * Get the size of valid data in the file. This will not match the + * size that is returned from the filesystem because we use mmap + * to extend file by map_size every time. + */ + virtual uint64_t GetFileSize() { + size_t used = dst_ - base_; + return file_offset_ + used; + } + +#ifdef OS_LINUX + virtual Status Allocate(off_t offset, off_t len) { + if (!fallocate(fd_, FALLOC_FL_KEEP_SIZE, offset, len)) { + return Status::OK(); + } else { + return IOError(filename_, errno); + } + } +#endif +}; + +// Use posix write to write data to a file. +class PosixWritableFile : public WritableFile { + private: + const std::string filename_; + int fd_; + size_t cursize_; // current size of cached data in buf_ + size_t capacity_; // max size of buf_ + char* buf_; // a buffer to cache writes + uint64_t filesize_; + bool pending_sync_; + bool pending_fsync_; + + public: + PosixWritableFile(const std::string& fname, int fd, size_t capacity) : + filename_(fname), + fd_(fd), + cursize_(0), + capacity_(capacity), + buf_(new char[capacity]), + filesize_(0), + pending_sync_(false), + pending_fsync_(false) { + } + + ~PosixWritableFile() { + if (fd_ >= 0) { + PosixWritableFile::Close(); + } + delete buf_; + buf_ = 0; + } + + virtual Status Append(const Slice& data) { + char* src = (char *)data.data(); + size_t left = data.size(); + Status s; + pending_sync_ = true; + pending_fsync_ = true; + + PrepareWrite(GetFileSize(), left); + // if there is no space in the cache, then flush + if (cursize_ + left > capacity_) { + s = Flush(); + if (!s.ok()) { + return s; + } + // Increase the buffer size, but capped at 1MB + if (capacity_ < (1<<20)) { + delete buf_; + capacity_ *= 2; + buf_ = new char[capacity_]; + } + assert(cursize_ == 0); + } + + // if the write fits into the cache, then write to cache + // otherwise do a write() syscall to write to OS buffers. + if (cursize_ + left <= capacity_) { + memcpy(buf_+cursize_, src, left); + cursize_ += left; + } else { + while (left != 0) { + ssize_t done = write(fd_, src, left); + if (done < 0) { + return IOError(filename_, errno); + } + left -= done; + src += done; + } + } + filesize_ += data.size(); + return Status::OK(); + } + + virtual Status Close() { + Status s; + s = Flush(); // flush cache to OS + if (!s.ok()) { + } + if (close(fd_) < 0) { + if (s.ok()) { + s = IOError(filename_, errno); + } + } + fd_ = -1; + return s; + } + + // write out the cached data to the OS cache + virtual Status Flush() { + size_t left = cursize_; + char* src = buf_; + while (left != 0) { + ssize_t done = write(fd_, src, left); + if (done < 0) { + return IOError(filename_, errno); + } + left -= done; + src += done; + } + cursize_ = 0; + return Status::OK(); + } + + virtual Status Sync() { + if (pending_sync_ && fdatasync(fd_) < 0) { + return IOError(filename_, errno); + } + pending_sync_ = false; + return Status::OK(); + } + + virtual Status Fsync() { + if (pending_fsync_ && fsync(fd_) < 0) { + return IOError(filename_, errno); + } + pending_fsync_ = false; + pending_sync_ = false; + return Status::OK(); + } + + virtual uint64_t GetFileSize() { + return filesize_; + } + +#ifdef OS_LINUX + virtual Status Allocate(off_t offset, off_t len) { + if (!fallocate(fd_, FALLOC_FL_KEEP_SIZE, offset, len)) { + return Status::OK(); + } else { + return IOError(filename_, errno); + } + } +#endif +}; + +static int LockOrUnlock(const std::string& fname, int fd, bool lock) { + mutex_lockedFiles.Lock(); + if (lock) { + // If it already exists in the lockedFiles set, then it is already locked, + // and fail this lock attempt. Otherwise, insert it into lockedFiles. + // This check is needed because fcntl() does not detect lock conflict + // if the fcntl is issued by the same thread that earlier acquired + // this lock. + if (lockedFiles.insert(fname).second == false) { + mutex_lockedFiles.Unlock(); + errno = ENOLCK; + return -1; + } + } else { + // If we are unlocking, then verify that we had locked it earlier, + // it should already exist in lockedFiles. Remove it from lockedFiles. + if (lockedFiles.erase(fname) != 1) { + mutex_lockedFiles.Unlock(); + errno = ENOLCK; + return -1; + } + } + errno = 0; + struct flock f; + memset(&f, 0, sizeof(f)); + f.l_type = (lock ? F_WRLCK : F_UNLCK); + f.l_whence = SEEK_SET; + f.l_start = 0; + f.l_len = 0; // Lock/unlock entire file + int value = fcntl(fd, F_SETLK, &f); + if (value == -1 && lock) { + // if there is an error in locking, then remove the pathname from lockedfiles + lockedFiles.erase(fname); + } + mutex_lockedFiles.Unlock(); + return value; +} + +class PosixFileLock : public FileLock { + public: + int fd_; + std::string filename; +}; + +class PosixEnv : public Env { + public: + PosixEnv(); + virtual ~PosixEnv() { + fprintf(stderr, "Destroying Env::Default()\n"); + exit(1); + } + + virtual Status NewSequentialFile(const std::string& fname, + unique_ptr* result) { + result->reset(); + FILE* f = fopen(fname.c_str(), "r"); + if (f == nullptr) { + *result = nullptr; + return IOError(fname, errno); + } else { + result->reset(new PosixSequentialFile(fname, f)); + return Status::OK(); + } + } + + virtual Status NewRandomAccessFile(const std::string& fname, + unique_ptr* result) { + result->reset(); + Status s; + int fd = open(fname.c_str(), O_RDONLY); + if (fd < 0) { + s = IOError(fname, errno); + } else if (useMmapRead && sizeof(void*) >= 8) { + // Use of mmap for random reads has been removed because it + // kills performance when storage is fast. + // Use mmap when virtual address-space is plentiful. + uint64_t size; + s = GetFileSize(fname, &size); + if (s.ok()) { + void* base = mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0); + if (base != MAP_FAILED) { + result->reset(new PosixMmapReadableFile(fname, base, size)); + } else { + s = IOError(fname, errno); + } + } + close(fd); + } else { + result->reset(new PosixRandomAccessFile(fname, fd)); + } + return s; + } + + virtual Status NewWritableFile(const std::string& fname, + unique_ptr* result) { + result->reset(); + Status s; + const int fd = open(fname.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0644); + if (fd < 0) { + s = IOError(fname, errno); + } else { + if (useMmapWrite) { + result->reset(new PosixMmapFile(fname, fd, page_size_)); + } else { + result->reset(new PosixWritableFile(fname, fd, 65536)); + } + } + return s; + } + + virtual bool FileExists(const std::string& fname) { + return access(fname.c_str(), F_OK) == 0; + } + + virtual Status GetChildren(const std::string& dir, + std::vector* result) { + result->clear(); + DIR* d = opendir(dir.c_str()); + if (d == nullptr) { + return IOError(dir, errno); + } + struct dirent* entry; + while ((entry = readdir(d)) != nullptr) { + result->push_back(entry->d_name); + } + closedir(d); + return Status::OK(); + } + + virtual Status DeleteFile(const std::string& fname) { + Status result; + if (unlink(fname.c_str()) != 0) { + result = IOError(fname, errno); + } + return result; + }; + + virtual Status CreateDir(const std::string& name) { + Status result; + if (mkdir(name.c_str(), 0755) != 0) { + result = IOError(name, errno); + } + return result; + }; + + virtual Status CreateDirIfMissing(const std::string& name) { + Status result; + if (mkdir(name.c_str(), 0755) != 0) { + if (errno != EEXIST) { + result = IOError(name, errno); + } else if (!DirExists(name)) { // Check that name is actually a + // directory. + // Message is taken from mkdir + result = Status::IOError("`"+name+"' exists but is not a directory"); + } + } + return result; + }; + + virtual Status DeleteDir(const std::string& name) { + Status result; + if (rmdir(name.c_str()) != 0) { + result = IOError(name, errno); + } + return result; + }; + + virtual Status GetFileSize(const std::string& fname, uint64_t* size) { + Status s; + struct stat sbuf; + if (stat(fname.c_str(), &sbuf) != 0) { + *size = 0; + s = IOError(fname, errno); + } else { + *size = sbuf.st_size; + } + return s; + } + + virtual Status GetFileModificationTime(const std::string& fname, + uint64_t* file_mtime) { + struct stat s; + if (stat(fname.c_str(), &s) !=0) { + return IOError(fname, errno); + } + *file_mtime = static_cast(s.st_mtime); + return Status::OK(); + } + virtual Status RenameFile(const std::string& src, const std::string& target) { + Status result; + if (rename(src.c_str(), target.c_str()) != 0) { + result = IOError(src, errno); + } + return result; + } + + virtual Status LockFile(const std::string& fname, FileLock** lock) { + *lock = nullptr; + Status result; + int fd = open(fname.c_str(), O_RDWR | O_CREAT, 0644); + if (fd < 0) { + result = IOError(fname, errno); + } else if (LockOrUnlock(fname, fd, true) == -1) { + result = IOError("lock " + fname, errno); + close(fd); + } else { + PosixFileLock* my_lock = new PosixFileLock; + my_lock->fd_ = fd; + my_lock->filename = fname; + *lock = my_lock; + } + return result; + } + + virtual Status UnlockFile(FileLock* lock) { + PosixFileLock* my_lock = reinterpret_cast(lock); + Status result; + if (LockOrUnlock(my_lock->filename, my_lock->fd_, false) == -1) { + result = IOError("unlock", errno); + } + close(my_lock->fd_); + delete my_lock; + return result; + } + + virtual void Schedule(void (*function)(void*), void* arg); + + virtual void StartThread(void (*function)(void* arg), void* arg); + + virtual Status GetTestDirectory(std::string* result) { + const char* env = getenv("TEST_TMPDIR"); + if (env && env[0] != '\0') { + *result = env; + } else { + char buf[100]; + snprintf(buf, sizeof(buf), "/tmp/leveldbtest-%d", int(geteuid())); + *result = buf; + } + // Directory may already exist + CreateDir(*result); + return Status::OK(); + } + + static uint64_t gettid() { + pthread_t tid = pthread_self(); + uint64_t thread_id = 0; + memcpy(&thread_id, &tid, std::min(sizeof(thread_id), sizeof(tid))); + return thread_id; + } + + virtual Status NewLogger(const std::string& fname, + shared_ptr* result) { + FILE* f = fopen(fname.c_str(), "w"); + if (f == nullptr) { + result->reset(); + return IOError(fname, errno); + } else { + result->reset(new PosixLogger(f, &PosixEnv::gettid)); + return Status::OK(); + } + } + + virtual uint64_t NowMicros() { + struct timeval tv; + gettimeofday(&tv, nullptr); + return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec; + } + + virtual void SleepForMicroseconds(int micros) { + usleep(micros); + } + + virtual Status GetHostName(char* name, uint64_t len) { + int ret = gethostname(name, len); + if (ret < 0) { + if (errno == EFAULT || errno == EINVAL) + return Status::InvalidArgument(strerror(errno)); + else + return IOError("GetHostName", errno); + } + return Status::OK(); + } + + virtual Status GetCurrentTime(int64_t* unix_time) { + time_t ret = time(nullptr); + if (ret == (time_t) -1) { + return IOError("GetCurrentTime", errno); + } + *unix_time = (int64_t) ret; + return Status::OK(); + } + + virtual Status GetAbsolutePath(const std::string& db_path, + std::string* output_path) { + if (db_path.find('/') == 0) { + *output_path = db_path; + return Status::OK(); + } + + char the_path[256]; + char* ret = getcwd(the_path, 256); + if (ret == nullptr) { + return Status::IOError(strerror(errno)); + } + + *output_path = ret; + return Status::OK(); + } + + // Allow increasing the number of worker threads. + virtual void SetBackgroundThreads(int num) { + if (num > num_threads_) { + num_threads_ = num; + bgthread_.resize(num_threads_); + } + } + + virtual std::string TimeToString(uint64_t secondsSince1970) { + const time_t seconds = (time_t)secondsSince1970; + struct tm t; + int maxsize = 64; + std::string dummy; + dummy.reserve(maxsize); + dummy.resize(maxsize); + char* p = &dummy[0]; + localtime_r(&seconds, &t); + snprintf(p, maxsize, + "%04d/%02d/%02d-%02d:%02d:%02d ", + t.tm_year + 1900, + t.tm_mon + 1, + t.tm_mday, + t.tm_hour, + t.tm_min, + t.tm_sec); + return dummy; + } + + private: + void PthreadCall(const char* label, int result) { + if (result != 0) { + fprintf(stderr, "pthread %s: %s\n", label, strerror(result)); + exit(1); + } + } + + // Returns true iff the named directory exists and is a directory. + virtual bool DirExists(const std::string& dname) { + struct stat statbuf; + if (stat(dname.c_str(), &statbuf) == 0) { + return S_ISDIR(statbuf.st_mode); + } + return false; // stat() failed return false + } + + + // BGThread() is the body of the background thread + void BGThread(); + static void* BGThreadWrapper(void* arg) { + reinterpret_cast(arg)->BGThread(); + return nullptr; + } + + size_t page_size_; + pthread_mutex_t mu_; + pthread_cond_t bgsignal_; + std::vector bgthread_; + int started_bgthread_; + int num_threads_; + + // Entry per Schedule() call + struct BGItem { void* arg; void (*function)(void*); }; + typedef std::deque BGQueue; + int queue_size_; // number of items in BGQueue + BGQueue queue_; +}; + +PosixEnv::PosixEnv() : page_size_(getpagesize()), + started_bgthread_(0), + num_threads_(1), + queue_size_(0) { + PthreadCall("mutex_init", pthread_mutex_init(&mu_, nullptr)); + PthreadCall("cvar_init", pthread_cond_init(&bgsignal_, nullptr)); + bgthread_.resize(num_threads_); +} + +void PosixEnv::Schedule(void (*function)(void*), void* arg) { + PthreadCall("lock", pthread_mutex_lock(&mu_)); + + // Start background thread if necessary + for (; started_bgthread_ < num_threads_; started_bgthread_++) { + PthreadCall( + "create thread", + pthread_create(&bgthread_[started_bgthread_], + nullptr, + &PosixEnv::BGThreadWrapper, + this)); + fprintf(stdout, "Created bg thread 0x%lx\n", bgthread_[started_bgthread_]); + } + + // always wake up at least one waiting thread. + PthreadCall("signal", pthread_cond_signal(&bgsignal_)); + + // Add to priority queue + queue_.push_back(BGItem()); + queue_.back().function = function; + queue_.back().arg = arg; + queue_size_++; + + PthreadCall("unlock", pthread_mutex_unlock(&mu_)); +} + +void PosixEnv::BGThread() { + while (true) { + // Wait until there is an item that is ready to run + PthreadCall("lock", pthread_mutex_lock(&mu_)); + while (queue_.empty()) { + PthreadCall("wait", pthread_cond_wait(&bgsignal_, &mu_)); + } + + void (*function)(void*) = queue_.front().function; + void* arg = queue_.front().arg; + queue_.pop_front(); + queue_size_--; + + PthreadCall("unlock", pthread_mutex_unlock(&mu_)); + (*function)(arg); + } +} + +namespace { +struct StartThreadState { + void (*user_function)(void*); + void* arg; +}; +} +static void* StartThreadWrapper(void* arg) { + StartThreadState* state = reinterpret_cast(arg); + state->user_function(state->arg); + delete state; + return nullptr; +} + +void PosixEnv::StartThread(void (*function)(void* arg), void* arg) { + pthread_t t; + StartThreadState* state = new StartThreadState; + state->user_function = function; + state->arg = arg; + PthreadCall("start thread", + pthread_create(&t, nullptr, &StartThreadWrapper, state)); +} + +} // namespace + +static pthread_once_t once = PTHREAD_ONCE_INIT; +static Env* default_env; +static void InitDefaultEnv() { default_env = new PosixEnv; } + +Env* Env::Default() { + pthread_once(&once, InitDefaultEnv); + return default_env; +} + +} // namespace leveldb diff --git a/util/env_test.cc b/util/env_test.cc new file mode 100644 index 00000000..67dc409c --- /dev/null +++ b/util/env_test.cc @@ -0,0 +1,246 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/env.h" + +#include +#include "port/port.h" +#include "util/coding.h" +#include "util/testharness.h" + +namespace leveldb { + +static const int kDelayMicros = 100000; + +class EnvPosixTest { + private: + port::Mutex mu_; + std::string events_; + + public: + Env* env_; + EnvPosixTest() : env_(Env::Default()) { } +}; + +static void SetBool(void* ptr) { + reinterpret_cast(ptr)->NoBarrier_Store(ptr); +} + +TEST(EnvPosixTest, RunImmediately) { + port::AtomicPointer called (nullptr); + env_->Schedule(&SetBool, &called); + Env::Default()->SleepForMicroseconds(kDelayMicros); + ASSERT_TRUE(called.NoBarrier_Load() != nullptr); +} + +TEST(EnvPosixTest, RunMany) { + port::AtomicPointer last_id (nullptr); + + struct CB { + port::AtomicPointer* last_id_ptr; // Pointer to shared slot + uintptr_t id; // Order# for the execution of this callback + + CB(port::AtomicPointer* p, int i) : last_id_ptr(p), id(i) { } + + static void Run(void* v) { + CB* cb = reinterpret_cast(v); + void* cur = cb->last_id_ptr->NoBarrier_Load(); + ASSERT_EQ(cb->id-1, reinterpret_cast(cur)); + cb->last_id_ptr->Release_Store(reinterpret_cast(cb->id)); + } + }; + + // Schedule in different order than start time + CB cb1(&last_id, 1); + CB cb2(&last_id, 2); + CB cb3(&last_id, 3); + CB cb4(&last_id, 4); + env_->Schedule(&CB::Run, &cb1); + env_->Schedule(&CB::Run, &cb2); + env_->Schedule(&CB::Run, &cb3); + env_->Schedule(&CB::Run, &cb4); + + Env::Default()->SleepForMicroseconds(kDelayMicros); + void* cur = last_id.Acquire_Load(); + ASSERT_EQ(4U, reinterpret_cast(cur)); +} + +struct State { + port::Mutex mu; + int val; + int num_running; +}; + +static void ThreadBody(void* arg) { + State* s = reinterpret_cast(arg); + s->mu.Lock(); + s->val += 1; + s->num_running -= 1; + s->mu.Unlock(); +} + +TEST(EnvPosixTest, StartThread) { + State state; + state.val = 0; + state.num_running = 3; + for (int i = 0; i < 3; i++) { + env_->StartThread(&ThreadBody, &state); + } + while (true) { + state.mu.Lock(); + int num = state.num_running; + state.mu.Unlock(); + if (num == 0) { + break; + } + Env::Default()->SleepForMicroseconds(kDelayMicros); + } + ASSERT_EQ(state.val, 3); +} + +bool IsSingleVarint(const std::string& s) { + Slice slice(s); + + uint64_t v; + if (!GetVarint64(&slice, &v)) { + return false; + } + + return slice.size() == 0; +} + +bool IsUniqueIDValid(const std::string& s) { + return !s.empty() && !IsSingleVarint(s); +} + +const size_t MAX_ID_SIZE = 100; +char temp_id[MAX_ID_SIZE]; + +TEST(EnvPosixTest, RandomAccessUniqueID) { + // Create file. + std::string fname = test::TmpDir() + "/" + "testfile"; + unique_ptr wfile; + ASSERT_OK(env_->NewWritableFile(fname, &wfile)); + + unique_ptr file; + + // Get Unique ID + ASSERT_OK(env_->NewRandomAccessFile(fname, &file)); + size_t id_size = file->GetUniqueId(temp_id, MAX_ID_SIZE); + ASSERT_TRUE(id_size > 0); + std::string unique_id1(temp_id, id_size); + ASSERT_TRUE(IsUniqueIDValid(unique_id1)); + + // Get Unique ID again + ASSERT_OK(env_->NewRandomAccessFile(fname, &file)); + id_size = file->GetUniqueId(temp_id, MAX_ID_SIZE); + ASSERT_TRUE(id_size > 0); + std::string unique_id2(temp_id, id_size); + ASSERT_TRUE(IsUniqueIDValid(unique_id2)); + + // Get Unique ID again after waiting some time. + env_->SleepForMicroseconds(1000000); + ASSERT_OK(env_->NewRandomAccessFile(fname, &file)); + id_size = file->GetUniqueId(temp_id, MAX_ID_SIZE); + ASSERT_TRUE(id_size > 0); + std::string unique_id3(temp_id, id_size); + ASSERT_TRUE(IsUniqueIDValid(unique_id3)); + + // Check IDs are the same. + ASSERT_EQ(unique_id1, unique_id2); + ASSERT_EQ(unique_id2, unique_id3); + + // Delete the file + env_->DeleteFile(fname); +} + +// Returns true if any of the strings in ss are the prefix of another string. +bool HasPrefix(const std::unordered_set& ss) { + for (const std::string& s: ss) { + if (s.empty()) { + return true; + } + for (size_t i = 1; i < s.size(); ++i) { + if (ss.count(s.substr(0, i)) != 0) { + return true; + } + } + } + return false; +} + +TEST(EnvPosixTest, RandomAccessUniqueIDConcurrent) { + // Check whether a bunch of concurrently existing files have unique IDs. + + // Create the files + std::vector fnames; + for (int i = 0; i < 1000; ++i) { + fnames.push_back(test::TmpDir() + "/" + "testfile" + std::to_string(i)); + + // Create file. + unique_ptr wfile; + ASSERT_OK(env_->NewWritableFile(fnames[i], &wfile)); + } + + // Collect and check whether the IDs are unique. + std::unordered_set ids; + for (const std::string fname: fnames) { + unique_ptr file; + std::string unique_id; + ASSERT_OK(env_->NewRandomAccessFile(fname, &file)); + size_t id_size = file->GetUniqueId(temp_id, MAX_ID_SIZE); + ASSERT_TRUE(id_size > 0); + unique_id = std::string(temp_id, id_size); + ASSERT_TRUE(IsUniqueIDValid(unique_id)); + + ASSERT_TRUE(ids.count(unique_id) == 0); + ids.insert(unique_id); + } + + // Delete the files + for (const std::string fname: fnames) { + ASSERT_OK(env_->DeleteFile(fname)); + } + + ASSERT_TRUE(!HasPrefix(ids)); +} + +TEST(EnvPosixTest, RandomAccessUniqueIDDeletes) { + std::string fname = test::TmpDir() + "/" + "testfile"; + + // Check that after file is deleted we don't get same ID again in a new file. + std::unordered_set ids; + for (int i = 0; i < 1000; ++i) { + // Create file. + { + unique_ptr wfile; + ASSERT_OK(env_->NewWritableFile(fname, &wfile)); + } + + // Get Unique ID + std::string unique_id; + { + unique_ptr file; + ASSERT_OK(env_->NewRandomAccessFile(fname, &file)); + size_t id_size = file->GetUniqueId(temp_id, MAX_ID_SIZE); + ASSERT_TRUE(id_size > 0); + unique_id = std::string(temp_id, id_size); + } + + ASSERT_TRUE(IsUniqueIDValid(unique_id)); + ASSERT_TRUE(ids.count(unique_id) == 0); + ids.insert(unique_id); + + // Delete the file + ASSERT_OK(env_->DeleteFile(fname)); + } + + ASSERT_TRUE(!HasPrefix(ids)); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/util/filelock_test.cc b/util/filelock_test.cc new file mode 100644 index 00000000..ea24527c --- /dev/null +++ b/util/filelock_test.cc @@ -0,0 +1,57 @@ +// Copyright (c) 2012 Facebook. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "leveldb/status.h" +#include "leveldb/env.h" + +#include +#include "util/coding.h" +#include "util/testharness.h" + +namespace leveldb { + +class LockTest { + public: + static LockTest* current_; + std::string file_; + leveldb::Env* env_; + + LockTest() : file_(test::TmpDir() + "/db_testlock_file"), + env_(leveldb::Env::Default()) { + current_ = this; + } + + ~LockTest() { + } + + Status LockFile(FileLock** db_lock) { + return env_->LockFile(file_, db_lock); + } + + Status UnlockFile(FileLock* db_lock) { + return env_->UnlockFile(db_lock); + } +}; +LockTest* LockTest::current_; + +TEST(LockTest, LockBySameThread) { + FileLock* lock1; + FileLock* lock2; + + // acquire a lock on a file + ASSERT_OK(LockFile(&lock1)); + + // re-acquire the lock on the same file. This should fail. + ASSERT_TRUE(LockFile(&lock2).IsIOError()); + + // release the lock + ASSERT_OK(UnlockFile(lock1)); + +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/util/filter_policy.cc b/util/filter_policy.cc new file mode 100644 index 00000000..7b045c8c --- /dev/null +++ b/util/filter_policy.cc @@ -0,0 +1,11 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/filter_policy.h" + +namespace leveldb { + +FilterPolicy::~FilterPolicy() { } + +} // namespace leveldb diff --git a/util/hash.cc b/util/hash.cc new file mode 100644 index 00000000..ba181808 --- /dev/null +++ b/util/hash.cc @@ -0,0 +1,45 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include "util/coding.h" +#include "util/hash.h" + +namespace leveldb { + +uint32_t Hash(const char* data, size_t n, uint32_t seed) { + // Similar to murmur hash + const uint32_t m = 0xc6a4a793; + const uint32_t r = 24; + const char* limit = data + n; + uint32_t h = seed ^ (n * m); + + // Pick up four bytes at a time + while (data + 4 <= limit) { + uint32_t w = DecodeFixed32(data); + data += 4; + h += w; + h *= m; + h ^= (h >> 16); + } + + // Pick up remaining bytes + switch (limit - data) { + case 3: + h += data[2] << 16; + // fall through + case 2: + h += data[1] << 8; + // fall through + case 1: + h += data[0]; + h *= m; + h ^= (h >> r); + break; + } + return h; +} + + +} // namespace leveldb diff --git a/util/hash.h b/util/hash.h new file mode 100644 index 00000000..8889d56b --- /dev/null +++ b/util/hash.h @@ -0,0 +1,19 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Simple hash function used for internal data structures + +#ifndef STORAGE_LEVELDB_UTIL_HASH_H_ +#define STORAGE_LEVELDB_UTIL_HASH_H_ + +#include +#include + +namespace leveldb { + +extern uint32_t Hash(const char* data, size_t n, uint32_t seed); + +} + +#endif // STORAGE_LEVELDB_UTIL_HASH_H_ diff --git a/util/histogram.cc b/util/histogram.cc new file mode 100644 index 00000000..0d52878e --- /dev/null +++ b/util/histogram.cc @@ -0,0 +1,190 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/histogram.h" + +#include +#include +#include +#include "port/port.h" + +namespace leveldb { + +HistogramBucketMapper::HistogramBucketMapper() : + // Add newer bucket index here. + // Should be alwyas added in sorted order. + bucketValues_({ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20, 25, 30, 35, 40, 45, + 50, 60, 70, 80, 90, 100, 120, 140, 160, 180, 200, 250, 300, 350, 400, 450, + 500, 600, 700, 800, 900, 1000, 1200, 1400, 1600, 1800, 2000, 2500, 3000, + 3500, 4000, 4500, 5000, 6000, 7000, 8000, 9000, 10000, 12000, 14000, + 16000, 18000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 60000, + 70000, 80000, 90000, 100000, 120000, 140000, 160000, 180000, 200000, + 250000, 300000, 350000, 400000, 450000, 500000, 600000, 700000, 800000, + 900000, 1000000, 1200000, 1400000, 1600000, 1800000, 2000000, 2500000, + 3000000, 3500000, 4000000, 4500000, 5000000, 6000000, 7000000, 8000000, + 9000000, 10000000, 12000000, 14000000, 16000000, 18000000, 20000000, + 25000000, 30000000, 35000000, 40000000, 45000000, 50000000, 60000000, + 70000000, 80000000, 90000000, 100000000, 120000000, 140000000, 160000000, + 180000000, 200000000, 250000000, 300000000, 350000000, 400000000, + 450000000, 500000000, 600000000, 700000000, 800000000, 900000000, + 1000000000}), + maxBucketValue_(bucketValues_.back()), + minBucketValue_(bucketValues_.front()) { + for (size_t i =0; i < bucketValues_.size(); ++i) { + valueIndexMap_[bucketValues_[i]] = i; + } +} + +const size_t HistogramBucketMapper::IndexForValue(const uint64_t value) const { + if (value >= maxBucketValue_) { + return bucketValues_.size() - 1; + } else if ( value >= minBucketValue_ ) { + std::map::const_iterator lowerBound = + valueIndexMap_.lower_bound(value); + if (lowerBound != valueIndexMap_.end()) { + return lowerBound->second; + } else { + return 0; + } + } else { + return 0; + } +} + +namespace { + const HistogramBucketMapper bucketMapper; +} + + +HistogramImpl::HistogramImpl() : + min_(bucketMapper.LastValue()), + max_(0), + num_(0), + sum_(0), + sum_squares_(0), + buckets_(std::vector(bucketMapper.BucketCount(), 0)) {} + +void HistogramImpl::Clear() { + min_ = bucketMapper.LastValue(); + max_ = 0; + num_ = 0; + sum_ = 0; + sum_squares_ = 0; + buckets_.resize(bucketMapper.BucketCount(), 0); +} + +void HistogramImpl::Add(uint64_t value) { + const size_t index = bucketMapper.IndexForValue(value); + buckets_[index] += 1; + if (min_ > value) min_ = value; + if (max_ < value) max_ = value; + num_++; + sum_ += value; + sum_squares_ += (value * value); +} + +void HistogramImpl::Add(double value) { + Add(static_cast(value)); +} + +void HistogramImpl::Merge(const HistogramImpl& other) { + if (other.min_ < min_) min_ = other.min_; + if (other.max_ > max_) max_ = other.max_; + num_ += other.num_; + sum_ += other.sum_; + sum_squares_ += other.sum_squares_; + for (int b = 0; b < bucketMapper.BucketCount(); b++) { + buckets_[b] += other.buckets_[b]; + } +} + +double HistogramImpl::Median() const { + return Percentile(50.0); +} + +double HistogramImpl::Percentile(double p) const { + double threshold = num_ * (p / 100.0); + double sum = 0; + for (int b = 0; b < bucketMapper.BucketCount(); b++) { + sum += buckets_[b]; + if (sum >= threshold) { + // Scale linearly within this bucket + double left_point = (b == 0) ? 0 : bucketMapper.BucketLimit(b-1); + double right_point = bucketMapper.BucketLimit(b); + double left_sum = sum - buckets_[b]; + double right_sum = sum; + double pos = 0; + double right_left_diff = right_sum - left_sum; + if (right_left_diff != 0) { + pos = (threshold - left_sum) / (right_sum - left_sum); + } + double r = left_point + (right_point - left_point) * pos; + if (r < min_) r = min_; + if (r > max_) r = max_; + return r; + } + } + return max_; +} + +double HistogramImpl::Average() const { + if (num_ == 0.0) return 0; + return sum_ / num_; +} + +double HistogramImpl::StandardDeviation() const { + if (num_ == 0.0) return 0; + double variance = (sum_squares_ * num_ - sum_ * sum_) / (num_ * num_); + return sqrt(variance); +} + +std::string HistogramImpl::ToString() const { + std::string r; + char buf[200]; + snprintf(buf, sizeof(buf), + "Count: %.0f Average: %.4f StdDev: %.2f\n", + num_, Average(), StandardDeviation()); + r.append(buf); + snprintf(buf, sizeof(buf), + "Min: %.4f Median: %.4f Max: %.4f\n", + (num_ == 0.0 ? 0.0 : min_), Median(), max_); + r.append(buf); + snprintf(buf, sizeof(buf), + "Percentiles: P50: %.2f P75: %.2f P99: %.2f P99.9: %.2f\n", + Percentile(50), Percentile(75), Percentile(99), Percentile(99.9)); + r.append(buf); + r.append("------------------------------------------------------\n"); + const double mult = 100.0 / num_; + double sum = 0; + for (int b = 0; b < bucketMapper.BucketCount(); b++) { + if (buckets_[b] <= 0.0) continue; + sum += buckets_[b]; + snprintf(buf, sizeof(buf), + "[ %7ld, %7ld ) %8ld %7.3f%% %7.3f%% ", + ((b == 0) ? 0 : bucketMapper.BucketLimit(b-1)), // left + bucketMapper.BucketLimit(b), // right + buckets_[b], // count + mult * buckets_[b], // percentage + mult * sum); // cumulative percentage + r.append(buf); + + // Add hash marks based on percentage; 20 marks for 100%. + int marks = static_cast(20*(buckets_[b] / num_) + 0.5); + r.append(marks, '#'); + r.push_back('\n'); + } + return r; +} + +void HistogramImpl::Data(HistogramData * const data) const { + assert(data); + data->median = Median(); + data->percentile95 = Percentile(95); + data->percentile99 = Percentile(99); + data->average = Average(); + data->standard_deviation = StandardDeviation(); +} + +} // namespace levedb diff --git a/util/histogram.h b/util/histogram.h new file mode 100644 index 00000000..5350b02b --- /dev/null +++ b/util/histogram.h @@ -0,0 +1,79 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_HISTOGRAM_H_ +#define STORAGE_LEVELDB_UTIL_HISTOGRAM_H_ + +#include "leveldb/statistics.h" + +#include +#include +#include +#include + +namespace leveldb { + +class HistogramBucketMapper { + public: + + HistogramBucketMapper(); + + // converts a value to the bucket index. + const size_t IndexForValue(const uint64_t value) const; + // number of buckets required. + + const size_t BucketCount() const { + return bucketValues_.size(); + } + + uint64_t LastValue() const { + return maxBucketValue_; + } + + uint64_t FirstValue() const { + return minBucketValue_; + } + + uint64_t BucketLimit(const uint64_t bucketNumber) const { + assert(bucketNumber < BucketCount()); + return bucketValues_[bucketNumber]; + } + + private: + const std::vector bucketValues_; + const uint64_t maxBucketValue_; + const uint64_t minBucketValue_; + std::map valueIndexMap_; +}; + +class HistogramImpl { + public: + HistogramImpl(); + virtual ~HistogramImpl() {} + virtual void Clear(); + virtual void Add(uint64_t value); + virtual void Add(double value); + void Merge(const HistogramImpl& other); + + virtual std::string ToString() const; + + virtual double Median() const; + virtual double Percentile(double p) const; + virtual double Average() const; + virtual double StandardDeviation() const; + virtual void Data(HistogramData * const data) const; + + private: + double min_; + double max_; + double num_; + double sum_; + double sum_squares_; + std::vector buckets_; + +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_HISTOGRAM_H_ diff --git a/util/histogram_test.cc b/util/histogram_test.cc new file mode 100644 index 00000000..158682af --- /dev/null +++ b/util/histogram_test.cc @@ -0,0 +1,57 @@ +#include "util/histogram.h" + +#include "util/testharness.h" + +namespace leveldb { + +class HistogramTest { }; + +TEST(HistogramTest, BasicOperation) { + + HistogramImpl histogram; + for (uint64_t i = 1; i <= 100; i++) { + histogram.Add(i); + } + + { + double median = histogram.Median(); + // ASSERT_LE(median, 50); + ASSERT_GT(median, 0); + } + + { + double percentile100 = histogram.Percentile(100.0); + ASSERT_LE(percentile100, 100.0); + ASSERT_GT(percentile100, 0.0); + double percentile99 = histogram.Percentile(99.0); + double percentile85 = histogram.Percentile(85.0); + ASSERT_LE(percentile99, 99.0); + ASSERT_TRUE(percentile99 >= percentile85); + } + + ASSERT_EQ(histogram.Average(), 50.5); // avg is acurately caluclated. +} + +TEST(HistogramTest, EmptyHistogram) { + HistogramImpl histogram; + ASSERT_EQ(histogram.Median(), 0.0); + ASSERT_EQ(histogram.Percentile(85.0), 0.0); + ASSERT_EQ(histogram.Average(), 0.0); +} + +TEST(HistogramTest, ClearHistogram) { + HistogramImpl histogram; + for (uint64_t i = 1; i <= 100; i++) { + histogram.Add(i); + } + histogram.Clear(); + ASSERT_EQ(histogram.Median(), 0); + ASSERT_EQ(histogram.Percentile(85.0), 0); + ASSERT_EQ(histogram.Average(), 0); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/util/ldb_cmd.cc b/util/ldb_cmd.cc new file mode 100644 index 00000000..3553527c --- /dev/null +++ b/util/ldb_cmd.cc @@ -0,0 +1,1143 @@ +// Copyright (c) 2012 Facebook. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "util/ldb_cmd.h" + +#include +#include + +#include "leveldb/write_batch.h" +#include "db/dbformat.h" +#include "db/log_reader.h" +#include "db/write_batch_internal.h" + +namespace leveldb { + +const string LDBCommand::ARG_DB = "db"; +const string LDBCommand::ARG_HEX = "hex"; +const string LDBCommand::ARG_KEY_HEX = "key_hex"; +const string LDBCommand::ARG_VALUE_HEX = "value_hex"; +const string LDBCommand::ARG_FROM = "from"; +const string LDBCommand::ARG_TO = "to"; +const string LDBCommand::ARG_MAX_KEYS = "max_keys"; +const string LDBCommand::ARG_BLOOM_BITS = "bloom_bits"; +const string LDBCommand::ARG_COMPRESSION_TYPE = "compression_type"; +const string LDBCommand::ARG_BLOCK_SIZE = "block_size"; +const string LDBCommand::ARG_AUTO_COMPACTION = "auto_compaction"; +const string LDBCommand::ARG_WRITE_BUFFER_SIZE = "write_buffer_size"; +const string LDBCommand::ARG_FILE_SIZE = "file_size"; +const string LDBCommand::ARG_CREATE_IF_MISSING = "create_if_missing"; + +const char* LDBCommand::DELIM = " ==> "; + +LDBCommand* LDBCommand::InitFromCmdLineArgs(int argc, char** argv) { + vector args; + for (int i = 1; i < argc; i++) { + args.push_back(argv[i]); + } + return InitFromCmdLineArgs(args); +} + +/** + * Parse the command-line arguments and create the appropriate LDBCommand2 + * instance. + * The command line arguments must be in the following format: + * ./ldb --db=PATH_TO_DB [--commonOpt1=commonOpt1Val] .. + * COMMAND ... [-cmdSpecificOpt1=cmdSpecificOpt1Val] .. + * This is similar to the command line format used by HBaseClientTool. + * Command name is not included in args. + * Returns nullptr if the command-line cannot be parsed. + */ +LDBCommand* LDBCommand::InitFromCmdLineArgs(const vector& args) { + // --x=y command line arguments are added as x->y map entries. + map options; + + // Command-line arguments of the form --hex end up in this array as hex + vector flags; + + // Everything other than options and flags. Represents commands + // and their parameters. For eg: put key1 value1 go into this vector. + vector cmdTokens; + + const string OPTION_PREFIX = "--"; + + for (vector::const_iterator itr = args.begin(); + itr != args.end(); itr++) { + string arg = *itr; + if (boost::starts_with(arg, OPTION_PREFIX)){ + vector splits; + boost::split(splits, arg, boost::is_any_of("=")); + if (splits.size() == 2) { + string optionKey = splits[0].substr(OPTION_PREFIX.size()); + options[optionKey] = splits[1]; + } else { + string optionKey = splits[0].substr(OPTION_PREFIX.size()); + flags.push_back(optionKey); + } + } else { + cmdTokens.push_back(string(arg)); + } + } + + if (cmdTokens.size() < 1) { + fprintf(stderr, "Command not specified!"); + return nullptr; + } + + string cmd = cmdTokens[0]; + vector cmdParams(cmdTokens.begin()+1, cmdTokens.end()); + + if (cmd == GetCommand::Name()) { + return new GetCommand(cmdParams, options, flags); + } else if (cmd == PutCommand::Name()) { + return new PutCommand(cmdParams, options, flags); + } else if (cmd == BatchPutCommand::Name()) { + return new BatchPutCommand(cmdParams, options, flags); + } else if (cmd == ScanCommand::Name()) { + return new ScanCommand(cmdParams, options, flags); + } else if (cmd == DeleteCommand::Name()) { + return new DeleteCommand(cmdParams, options, flags); + } else if (cmd == ApproxSizeCommand::Name()) { + return new ApproxSizeCommand(cmdParams, options, flags); + } else if (cmd == DBQuerierCommand::Name()) { + return new DBQuerierCommand(cmdParams, options, flags); + } else if (cmd == CompactorCommand::Name()) { + return new CompactorCommand(cmdParams, options, flags); + } else if (cmd == WALDumperCommand::Name()) { + return new WALDumperCommand(cmdParams, options, flags); + } else if (cmd == ReduceDBLevelsCommand::Name()) { + return new ReduceDBLevelsCommand(cmdParams, options, flags); + } else if (cmd == DBDumperCommand::Name()) { + return new DBDumperCommand(cmdParams, options, flags); + } else if (cmd == DBLoaderCommand::Name()) { + return new DBLoaderCommand(cmdParams, options, flags); + } + + return nullptr; +} + +/** + * Parses the specific integer option and fills in the value. + * Returns true if the option is found. + * Returns false if the option is not found or if there is an error parsing the + * value. If there is an error, the specified exec_state is also + * updated. + */ +bool LDBCommand::ParseIntOption(const map& options, + string option, int& value, LDBCommandExecuteResult& exec_state) { + + map::const_iterator itr = options_.find(option); + if (itr != options_.end()) { + try { + value = boost::lexical_cast(itr->second); + return true; + } catch( const boost::bad_lexical_cast & ) { + exec_state = LDBCommandExecuteResult::FAILED(option + + " has an invalid value."); + } + } + return false; +} + +leveldb::Options LDBCommand::PrepareOptionsForOpenDB() { + + leveldb::Options opt; + opt.create_if_missing = false; + + map::const_iterator itr; + + int bits; + if (ParseIntOption(options_, ARG_BLOOM_BITS, bits, exec_state_)) { + if (bits > 0) { + opt.filter_policy = leveldb::NewBloomFilterPolicy(bits); + } else { + exec_state_ = LDBCommandExecuteResult::FAILED(ARG_BLOOM_BITS + + " must be > 0."); + } + } + + int block_size; + if (ParseIntOption(options_, ARG_BLOCK_SIZE, block_size, exec_state_)) { + if (block_size > 0) { + opt.block_size = block_size; + } else { + exec_state_ = LDBCommandExecuteResult::FAILED(ARG_BLOCK_SIZE + + " must be > 0."); + } + } + + itr = options_.find(ARG_AUTO_COMPACTION); + if (itr != options_.end()) { + opt.disable_auto_compactions = ! StringToBool(itr->second); + } + + itr = options_.find(ARG_COMPRESSION_TYPE); + if (itr != options_.end()) { + string comp = itr->second; + if (comp == "no") { + opt.compression = leveldb::kNoCompression; + } else if (comp == "snappy") { + opt.compression = leveldb::kSnappyCompression; + } else if (comp == "zlib") { + opt.compression = leveldb::kZlibCompression; + } else if (comp == "bzip2") { + opt.compression = leveldb::kBZip2Compression; + } else { + // Unknown compression. + exec_state_ = LDBCommandExecuteResult::FAILED( + "Unknown compression level: " + comp); + } + } + + int write_buffer_size; + if (ParseIntOption(options_, ARG_WRITE_BUFFER_SIZE, write_buffer_size, + exec_state_)) { + if (write_buffer_size > 0) { + opt.write_buffer_size = write_buffer_size; + } else { + exec_state_ = LDBCommandExecuteResult::FAILED(ARG_WRITE_BUFFER_SIZE + + " must be > 0."); + } + } + + int file_size; + if (ParseIntOption(options_, ARG_FILE_SIZE, file_size, exec_state_)) { + if (file_size > 0) { + opt.target_file_size_base = file_size; + } else { + exec_state_ = LDBCommandExecuteResult::FAILED(ARG_FILE_SIZE + + " must be > 0."); + } + } + + return opt; +} + +bool LDBCommand::ParseKeyValue(const string& line, string* key, string* value, + bool is_key_hex, bool is_value_hex) { + size_t pos = line.find(DELIM); + if (pos != std::string::npos) { + *key = line.substr(0, pos); + *value = line.substr(pos + strlen(DELIM)); + if (is_key_hex) { + *key = HexToString(*key); + } + if (is_value_hex) { + *value = HexToString(*value); + } + return true; + } else { + return false; + } +} + +/** + * Make sure that ONLY the command-line options and flags expected by this + * command are specified on the command-line. Extraneous options are usually + * the result of user error. + * Returns true if all checks pass. Else returns false, and prints an + * appropriate error msg to stderr. + */ +bool LDBCommand::ValidateCmdLineOptions() { + + for (map::const_iterator itr = options_.begin(); + itr != options_.end(); itr++) { + if (std::find(valid_cmd_line_options_.begin(), + valid_cmd_line_options_.end(), itr->first) == + valid_cmd_line_options_.end()) { + fprintf(stderr, "Invalid command-line option %s\n", itr->first.c_str()); + return false; + } + } + + for (vector::const_iterator itr = flags_.begin(); + itr != flags_.end(); itr++) { + if (std::find(valid_cmd_line_options_.begin(), + valid_cmd_line_options_.end(), *itr) == + valid_cmd_line_options_.end()) { + fprintf(stderr, "Invalid command-line flag %s\n", itr->c_str()); + return false; + } + } + + if (options_.find(ARG_DB) == options_.end()) { + fprintf(stderr, "%s must be specified\n", ARG_DB.c_str()); + return false; + } + + return true; +} + +CompactorCommand::CompactorCommand(const vector& params, + const map& options, const vector& flags) : + LDBCommand(options, flags, false, + BuildCmdLineOptions({ARG_FROM, ARG_TO, ARG_HEX, ARG_KEY_HEX, + ARG_VALUE_HEX})), + null_from_(true), null_to_(true) { + + map::const_iterator itr = options.find(ARG_FROM); + if (itr != options.end()) { + null_from_ = false; + from_ = itr->second; + } + + itr = options.find(ARG_TO); + if (itr != options.end()) { + null_to_ = false; + to_ = itr->second; + } + + if (is_key_hex_) { + if (!null_from_) { + from_ = HexToString(from_); + } + if (!null_to_) { + to_ = HexToString(to_); + } + } +} + +void CompactorCommand::Help(string& ret) { + ret.append(" "); + ret.append(CompactorCommand::Name()); + ret.append(HelpRangeCmdArgs()); + ret.append("\n"); +} + +void CompactorCommand::DoCommand() { + + leveldb::Slice* begin = nullptr; + leveldb::Slice* end = nullptr; + if (!null_from_) { + begin = new leveldb::Slice(from_); + } + if (!null_to_) { + end = new leveldb::Slice(to_); + } + + db_->CompactRange(begin, end); + exec_state_ = LDBCommandExecuteResult::SUCCEED(""); + + delete begin; + delete end; +} + +const string DBLoaderCommand::ARG_DISABLE_WAL = "disable_wal"; +const string DBLoaderCommand::ARG_BULK_LOAD = "bulk_load"; +const string DBLoaderCommand::ARG_COMPACT = "compact"; + +DBLoaderCommand::DBLoaderCommand(const vector& params, + const map& options, const vector& flags) : + LDBCommand(options, flags, false, + BuildCmdLineOptions({ARG_HEX, ARG_KEY_HEX, ARG_VALUE_HEX, + ARG_FROM, ARG_TO, ARG_CREATE_IF_MISSING, + ARG_DISABLE_WAL, ARG_BULK_LOAD, + ARG_COMPACT})), + create_if_missing_(false), disable_wal_(false), bulk_load_(false), + compact_(false) { + + create_if_missing_ = IsFlagPresent(flags, ARG_CREATE_IF_MISSING); + disable_wal_ = IsFlagPresent(flags, ARG_DISABLE_WAL); + bulk_load_ = IsFlagPresent(flags, ARG_BULK_LOAD); + compact_ = IsFlagPresent(flags, ARG_COMPACT); +} + +void DBLoaderCommand::Help(string& ret) { + ret.append(" "); + ret.append(DBLoaderCommand::Name()); + ret.append(" [--" + ARG_CREATE_IF_MISSING + "]"); + ret.append(" [--" + ARG_DISABLE_WAL + "]"); + ret.append(" [--" + ARG_BULK_LOAD + "]"); + ret.append(" [--" + ARG_COMPACT + "]"); + ret.append("\n"); +} + +leveldb::Options DBLoaderCommand::PrepareOptionsForOpenDB() { + leveldb::Options opt = LDBCommand::PrepareOptionsForOpenDB(); + opt.create_if_missing = create_if_missing_; + if (bulk_load_) { + opt.PrepareForBulkLoad(); + } + return opt; +} + +void DBLoaderCommand::DoCommand() { + if (!db_) { + return; + } + + WriteOptions write_options; + if (disable_wal_) { + write_options.disableWAL = true; + } + + int bad_lines = 0; + string line; + while (std::getline(std::cin, line, '\n')) { + string key; + string value; + if (ParseKeyValue(line, &key, &value, is_key_hex_, is_value_hex_)) { + db_->Put(write_options, Slice(key), Slice(value)); + } else if (0 == line.find("Keys in range:")) { + // ignore this line + } else if (0 == line.find("Created bg thread 0x")) { + // ignore this line + } else { + bad_lines ++; + } + } + + if (bad_lines > 0) { + std::cout << "Warning: " << bad_lines << " bad lines ignored." << std::endl; + } + if (compact_) { + db_->CompactRange(NULL, NULL); + } +} + +const string DBDumperCommand::ARG_COUNT_ONLY = "count_only"; +const string DBDumperCommand::ARG_STATS = "stats"; + +DBDumperCommand::DBDumperCommand(const vector& params, + const map& options, const vector& flags) : + LDBCommand(options, flags, true, + BuildCmdLineOptions({ARG_HEX, ARG_KEY_HEX, ARG_VALUE_HEX, + ARG_FROM, ARG_TO, ARG_MAX_KEYS, + ARG_COUNT_ONLY, ARG_STATS})), + null_from_(true), + null_to_(true), + max_keys_(-1), + count_only_(false), + print_stats_(false) { + + map::const_iterator itr = options.find(ARG_FROM); + if (itr != options.end()) { + null_from_ = false; + from_ = itr->second; + } + + itr = options.find(ARG_TO); + if (itr != options.end()) { + null_to_ = false; + to_ = itr->second; + } + + itr = options.find(ARG_MAX_KEYS); + if (itr != options.end()) { + try { + max_keys_ = boost::lexical_cast(itr->second); + } catch( const boost::bad_lexical_cast & ) { + exec_state_ = LDBCommandExecuteResult::FAILED(ARG_MAX_KEYS + + " has an invalid value"); + } + } + + print_stats_ = IsFlagPresent(flags, ARG_STATS); + count_only_ = IsFlagPresent(flags, ARG_COUNT_ONLY); + + if (is_key_hex_) { + if (!null_from_) { + from_ = HexToString(from_); + } + if (!null_to_) { + to_ = HexToString(to_); + } + } +} + +void DBDumperCommand::Help(string& ret) { + ret.append(" "); + ret.append(DBDumperCommand::Name()); + ret.append(HelpRangeCmdArgs()); + ret.append(" [--" + ARG_MAX_KEYS + "=]"); + ret.append(" [--" + ARG_COUNT_ONLY + "]"); + ret.append(" [--" + ARG_STATS + "]"); + ret.append("\n"); +} + +void DBDumperCommand::DoCommand() { + if (!db_) { + return; + } + // Parse command line args + uint64_t count = 0; + if (print_stats_) { + string stats; + if (db_->GetProperty("leveldb.stats", &stats)) { + fprintf(stdout, "%s\n", stats.c_str()); + } + } + + // Setup key iterator + leveldb::Iterator* iter = db_->NewIterator(leveldb::ReadOptions()); + leveldb::Status st = iter->status(); + if (!st.ok()) { + exec_state_ = LDBCommandExecuteResult::FAILED("Iterator error." + + st.ToString()); + } + + if (!null_from_) { + iter->Seek(from_); + } else { + iter->SeekToFirst(); + } + + int max_keys = max_keys_; + for (; iter->Valid(); iter->Next()) { + // If end marker was specified, we stop before it + if (!null_to_ && (iter->key().ToString() >= to_)) + break; + // Terminate if maximum number of keys have been dumped + if (max_keys == 0) + break; + if (max_keys > 0) { + --max_keys; + } + ++count; + if (!count_only_) { + string str = PrintKeyValue(iter->key().ToString(), + iter->value().ToString(), + is_key_hex_, is_value_hex_); + fprintf(stdout, "%s\n", str.c_str()); + } + } + fprintf(stdout, "Keys in range: %lld\n", (long long) count); + // Clean up + delete iter; +} + +const string ReduceDBLevelsCommand::ARG_NEW_LEVELS = "new_levels"; +const string ReduceDBLevelsCommand::ARG_PRINT_OLD_LEVELS = "print_old_levels"; + +ReduceDBLevelsCommand::ReduceDBLevelsCommand(const vector& params, + const map& options, const vector& flags) : + LDBCommand(options, flags, false, + BuildCmdLineOptions({ARG_NEW_LEVELS, ARG_PRINT_OLD_LEVELS})), + old_levels_(1 << 16), + new_levels_(-1), + print_old_levels_(false) { + + + ParseIntOption(options_, ARG_NEW_LEVELS, new_levels_, exec_state_); + print_old_levels_ = IsFlagPresent(flags, ARG_PRINT_OLD_LEVELS); + + if(new_levels_ <= 0) { + exec_state_ = LDBCommandExecuteResult::FAILED( + " Use --" + ARG_NEW_LEVELS + " to specify a new level number\n"); + } +} + +vector ReduceDBLevelsCommand::PrepareArgs(const string& db_path, + int new_levels, bool print_old_level) { + vector ret; + ret.push_back("reduce_levels"); + ret.push_back("--" + ARG_DB + "=" + db_path); + ret.push_back("--" + ARG_NEW_LEVELS + "=" + std::to_string(new_levels)); + if(print_old_level) { + ret.push_back("--" + ARG_PRINT_OLD_LEVELS); + } + return ret; +} + +void ReduceDBLevelsCommand::Help(string& ret) { + ret.append(" "); + ret.append(ReduceDBLevelsCommand::Name()); + ret.append(" --" + ARG_NEW_LEVELS + "="); + ret.append(" [--" + ARG_PRINT_OLD_LEVELS + "]"); + ret.append("\n"); +} + +leveldb::Options ReduceDBLevelsCommand::PrepareOptionsForOpenDB() { + leveldb::Options opt = LDBCommand::PrepareOptionsForOpenDB(); + opt.num_levels = old_levels_; + // Disable size compaction + opt.max_bytes_for_level_base = 1UL << 50; + opt.max_bytes_for_level_multiplier = 1; + opt.max_mem_compaction_level = 0; + return opt; +} + +Status ReduceDBLevelsCommand::GetOldNumOfLevels(leveldb::Options& opt, + int* levels) { + TableCache* tc = new TableCache(db_path_, &opt, 10); + const InternalKeyComparator* cmp = new InternalKeyComparator( + opt.comparator); + VersionSet* versions = new VersionSet(db_path_, &opt, + tc, cmp); + // We rely the VersionSet::Recover to tell us the internal data structures + // in the db. And the Recover() should never do any change + // (like LogAndApply) to the manifest file. + Status st = versions->Recover(); + if (!st.ok()) { + return st; + } + int max = -1; + for (int i = 0; i < versions->NumberLevels(); i++) { + if (versions->NumLevelFiles(i)) { + max = i; + } + } + + *levels = max + 1; + delete versions; + return st; +} + +void ReduceDBLevelsCommand::DoCommand() { + if (new_levels_ <= 1) { + exec_state_ = LDBCommandExecuteResult::FAILED( + "Invalid number of levels.\n"); + return; + } + + leveldb::Status st; + leveldb::Options opt = PrepareOptionsForOpenDB(); + int old_level_num = -1; + st = GetOldNumOfLevels(opt, &old_level_num); + if (!st.ok()) { + exec_state_ = LDBCommandExecuteResult::FAILED(st.ToString()); + return; + } + + if (print_old_levels_) { + fprintf(stdout, "The old number of levels in use is %d\n", old_level_num); + } + + if (old_level_num <= new_levels_) { + return; + } + + old_levels_ = old_level_num; + + OpenDB(); + if (!db_) { + return; + } + // Compact the whole DB to put all files to the highest level. + fprintf(stdout, "Compacting the db...\n"); + db_->CompactRange(nullptr, nullptr); + CloseDB(); + + TableCache* tc = new TableCache(db_path_, &opt, 10); + const InternalKeyComparator* cmp = new InternalKeyComparator( + opt.comparator); + VersionSet* versions = new VersionSet(db_path_, &opt, + tc, cmp); + // We rely the VersionSet::Recover to tell us the internal data structures + // in the db. And the Recover() should never do any change (like LogAndApply) + // to the manifest file. + st = versions->Recover(); + if (!st.ok()) { + exec_state_ = LDBCommandExecuteResult::FAILED(st.ToString()); + return; + } + + port::Mutex mu; + mu.Lock(); + st = versions->ReduceNumberOfLevels(new_levels_, &mu); + mu.Unlock(); + + if (!st.ok()) { + exec_state_ = LDBCommandExecuteResult::FAILED(st.ToString()); + return; + } +} + +class InMemoryHandler : public WriteBatch::Handler { + public: + + virtual void Put(const Slice& key, const Slice& value) { + putMap_[key.ToString()] = value.ToString(); + } + virtual void Delete(const Slice& key) { + deleteList_.push_back(key.ToString(true)); + } + virtual ~InMemoryHandler() { }; + + map PutMap() { + return putMap_; + } + vector DeleteList() { + return deleteList_; + } + + private: + std::map putMap_; + std::vector deleteList_; +}; + +const string WALDumperCommand::ARG_WAL_FILE = "walfile"; +const string WALDumperCommand::ARG_PRINT_VALUE = "print_value"; +const string WALDumperCommand::ARG_PRINT_HEADER = "header"; + +WALDumperCommand::WALDumperCommand(const vector& params, + const map& options, const vector& flags) : + LDBCommand(options, flags, true, + BuildCmdLineOptions( + {ARG_WAL_FILE, ARG_PRINT_HEADER, ARG_PRINT_VALUE})), + print_header_(false), print_values_(false) { + + wal_file_.clear(); + + map::const_iterator itr = options.find(ARG_WAL_FILE); + if (itr != options.end()) { + wal_file_ = itr->second; + } + + + print_header_ = IsFlagPresent(flags, ARG_PRINT_HEADER); + print_values_ = IsFlagPresent(flags, ARG_PRINT_VALUE); + if (wal_file_.empty()) { + exec_state_ = LDBCommandExecuteResult::FAILED( + "Argument " + ARG_WAL_FILE + " must be specified."); + } +} + +void WALDumperCommand::Help(string& ret) { + ret.append(" "); + ret.append(WALDumperCommand::Name()); + ret.append(" --" + ARG_WAL_FILE + "="); + ret.append(" --[" + ARG_PRINT_HEADER + "] "); + ret.append(" --[ " + ARG_PRINT_VALUE + "] "); + ret.append("\n"); +} + +void WALDumperCommand::DoCommand() { + struct StdErrReporter : public log::Reader::Reporter { + virtual void Corruption(size_t bytes, const Status& s) { + std::cerr<<"Corruption detected in log file "< file; + Env* env_ = Env::Default(); + Status status = env_->NewSequentialFile(wal_file_, &file); + if (!status.ok()) { + exec_state_ = LDBCommandExecuteResult::FAILED("Failed to open WAL file " + + status.ToString()); + } else { + StdErrReporter reporter; + log::Reader reader(std::move(file), &reporter, true, 0); + string scratch; + WriteBatch batch; + Slice record; + std::stringstream row; + if (print_header_) { + std::cout<<"Sequence,Count,ByteSize,Physical Offset,Key(s)"; + if (print_values_) { + std::cout << " : value "; + } + std::cout << "\n"; + } + while(reader.ReadRecord(&record, &scratch)) { + row.str(""); + if (record.size() < 12) { + reporter.Corruption( + record.size(), Status::Corruption("log record too small")); + } else { + WriteBatchInternal::SetContents(&batch, record); + row<& params, + const map& options, const vector& flags) : + LDBCommand(options, flags, true, + BuildCmdLineOptions({ARG_HEX, ARG_KEY_HEX, ARG_VALUE_HEX})) { + + if (params.size() != 1) { + exec_state_ = LDBCommandExecuteResult::FAILED( + " must be specified for the get command"); + } else { + key_ = params.at(0); + } + + if (is_key_hex_) { + key_ = HexToString(key_); + } +} + +void GetCommand::Help(string& ret) { + ret.append(" "); + ret.append(GetCommand::Name()); + ret.append(" "); + ret.append("\n"); +} + +void GetCommand::DoCommand() { + string value; + leveldb::Status st = db_->Get(leveldb::ReadOptions(), key_, &value); + if (st.ok()) { + fprintf(stdout, "%s\n", + (is_value_hex_ ? StringToHex(value) : value).c_str()); + } else { + exec_state_ = LDBCommandExecuteResult::FAILED(st.ToString()); + } +} + + +ApproxSizeCommand::ApproxSizeCommand(const vector& params, + const map& options, const vector& flags) : + LDBCommand(options, flags, true, + BuildCmdLineOptions({ARG_HEX, ARG_KEY_HEX, ARG_VALUE_HEX, + ARG_FROM, ARG_TO})) { + + if (options.find(ARG_FROM) != options.end()) { + start_key_ = options.find(ARG_FROM)->second; + } else { + exec_state_ = LDBCommandExecuteResult::FAILED(ARG_FROM + + " must be specified for approxsize command"); + return; + } + + if (options.find(ARG_TO) != options.end()) { + end_key_ = options.find(ARG_TO)->second; + } else { + exec_state_ = LDBCommandExecuteResult::FAILED(ARG_TO + + " must be specified for approxsize command"); + return; + } + + if (is_key_hex_) { + start_key_ = HexToString(start_key_); + end_key_ = HexToString(end_key_); + } +} + +void ApproxSizeCommand::Help(string& ret) { + ret.append(" "); + ret.append(ApproxSizeCommand::Name()); + ret.append(HelpRangeCmdArgs()); + ret.append("\n"); +} + +void ApproxSizeCommand::DoCommand() { + + leveldb::Range ranges[1]; + ranges[0] = leveldb::Range(start_key_, end_key_); + uint64_t sizes[1]; + db_->GetApproximateSizes(ranges, 1, sizes); + fprintf(stdout, "%ld\n", sizes[0]); + /* Wierd that GetApproximateSizes() returns void, although documentation + * says that it returns a Status object. + if (!st.ok()) { + exec_state_ = LDBCommandExecuteResult::FAILED(st.ToString()); + } + */ +} + + +BatchPutCommand::BatchPutCommand(const vector& params, + const map& options, const vector& flags) : + LDBCommand(options, flags, false, + BuildCmdLineOptions({ARG_HEX, ARG_KEY_HEX, ARG_VALUE_HEX, + ARG_CREATE_IF_MISSING})) { + + if (params.size() < 2) { + exec_state_ = LDBCommandExecuteResult::FAILED( + "At least one pair must be specified batchput."); + } else if (params.size() % 2 != 0) { + exec_state_ = LDBCommandExecuteResult::FAILED( + "Equal number of s and s must be specified for batchput."); + } else { + for (size_t i = 0; i < params.size(); i += 2) { + string key = params.at(i); + string value = params.at(i+1); + key_values_.push_back(std::pair( + is_key_hex_ ? HexToString(key) : key, + is_value_hex_ ? HexToString(value) : value)); + } + } +} + +void BatchPutCommand::Help(string& ret) { + ret.append(" "); + ret.append(BatchPutCommand::Name()); + ret.append(" [ ] [..]"); + ret.append("\n"); +} + +void BatchPutCommand::DoCommand() { + leveldb::WriteBatch batch; + + for (vector>::const_iterator itr + = key_values_.begin(); itr != key_values_.end(); itr++) { + batch.Put(itr->first, itr->second); + } + leveldb::Status st = db_->Write(leveldb::WriteOptions(), &batch); + if (st.ok()) { + fprintf(stdout, "OK\n"); + } else { + exec_state_ = LDBCommandExecuteResult::FAILED(st.ToString()); + } +} + +leveldb::Options BatchPutCommand::PrepareOptionsForOpenDB() { + leveldb::Options opt = LDBCommand::PrepareOptionsForOpenDB(); + opt.create_if_missing = IsFlagPresent(flags_, ARG_CREATE_IF_MISSING); + return opt; +} + + +ScanCommand::ScanCommand(const vector& params, + const map& options, const vector& flags) : + LDBCommand(options, flags, true, + BuildCmdLineOptions({ARG_HEX, ARG_KEY_HEX, ARG_VALUE_HEX, + ARG_FROM, ARG_TO, ARG_MAX_KEYS})), + start_key_specified_(false), + end_key_specified_(false), + max_keys_scanned_(-1) { + + map::const_iterator itr = options.find(ARG_FROM); + if (itr != options.end()) { + start_key_ = itr->second; + if (is_key_hex_) { + start_key_ = HexToString(start_key_); + } + start_key_specified_ = true; + } + itr = options.find(ARG_TO); + if (itr != options.end()) { + end_key_ = itr->second; + if (is_key_hex_) { + end_key_ = HexToString(end_key_); + } + end_key_specified_ = true; + } + + itr = options.find(ARG_MAX_KEYS); + if (itr != options.end()) { + try { + max_keys_scanned_ = boost::lexical_cast< int >(itr->second); + } catch( const boost::bad_lexical_cast & ) { + exec_state_ = LDBCommandExecuteResult::FAILED(ARG_MAX_KEYS + + " has an invalid value"); + } + } +} + +void ScanCommand::Help(string& ret) { + ret.append(" "); + ret.append(ScanCommand::Name()); + ret.append(HelpRangeCmdArgs()); + ret.append("--" + ARG_MAX_KEYS + "=N] "); + ret.append("\n"); +} + +void ScanCommand::DoCommand() { + + int num_keys_scanned = 0; + Iterator* it = db_->NewIterator(leveldb::ReadOptions()); + if (start_key_specified_) { + it->Seek(start_key_); + } else { + it->SeekToFirst(); + } + for ( ; + it->Valid() && (!end_key_specified_ || it->key().ToString() < end_key_); + it->Next()) { + string key = it->key().ToString(); + string value = it->value().ToString(); + fprintf(stdout, "%s : %s\n", + (is_key_hex_ ? StringToHex(key) : key).c_str(), + (is_value_hex_ ? StringToHex(value) : value).c_str() + ); + num_keys_scanned++; + if (max_keys_scanned_ >= 0 && num_keys_scanned >= max_keys_scanned_) { + break; + } + } + if (!it->status().ok()) { // Check for any errors found during the scan + exec_state_ = LDBCommandExecuteResult::FAILED(it->status().ToString()); + } + delete it; +} + + +DeleteCommand::DeleteCommand(const vector& params, + const map& options, const vector& flags) : + LDBCommand(options, flags, false, + BuildCmdLineOptions({ARG_HEX, ARG_KEY_HEX, ARG_VALUE_HEX})) { + + if (params.size() != 1) { + exec_state_ = LDBCommandExecuteResult::FAILED( + "KEY must be specified for the delete command"); + } else { + key_ = params.at(0); + if (is_key_hex_) { + key_ = HexToString(key_); + } + } +} + +void DeleteCommand::Help(string& ret) { + ret.append(" "); + ret.append(DeleteCommand::Name() + " "); + ret.append("\n"); +} + +void DeleteCommand::DoCommand() { + leveldb::Status st = db_->Delete(leveldb::WriteOptions(), key_); + if (st.ok()) { + fprintf(stdout, "OK\n"); + } else { + exec_state_ = LDBCommandExecuteResult::FAILED(st.ToString()); + } +} + + +PutCommand::PutCommand(const vector& params, + const map& options, const vector& flags) : + LDBCommand(options, flags, false, + BuildCmdLineOptions({ARG_HEX, ARG_KEY_HEX, ARG_VALUE_HEX, + ARG_CREATE_IF_MISSING})) { + + if (params.size() != 2) { + exec_state_ = LDBCommandExecuteResult::FAILED( + " and must be specified for the put command"); + } else { + key_ = params.at(0); + value_ = params.at(1); + } + + if (is_key_hex_) { + key_ = HexToString(key_); + } + + if (is_value_hex_) { + value_ = HexToString(value_); + } +} + +void PutCommand::Help(string& ret) { + ret.append(" "); + ret.append(PutCommand::Name()); + ret.append(" "); + ret.append("\n"); +} + +void PutCommand::DoCommand() { + leveldb::Status st = db_->Put(leveldb::WriteOptions(), key_, value_); + if (st.ok()) { + fprintf(stdout, "OK\n"); + } else { + exec_state_ = LDBCommandExecuteResult::FAILED(st.ToString()); + } +} + +leveldb::Options PutCommand::PrepareOptionsForOpenDB() { + leveldb::Options opt = LDBCommand::PrepareOptionsForOpenDB(); + opt.create_if_missing = IsFlagPresent(flags_, ARG_CREATE_IF_MISSING); + return opt; +} + + +const char* DBQuerierCommand::HELP_CMD = "help"; +const char* DBQuerierCommand::GET_CMD = "get"; +const char* DBQuerierCommand::PUT_CMD = "put"; +const char* DBQuerierCommand::DELETE_CMD = "delete"; + +DBQuerierCommand::DBQuerierCommand(const vector& params, + const map& options, const vector& flags) : + LDBCommand(options, flags, false, + BuildCmdLineOptions({ARG_HEX, ARG_KEY_HEX, ARG_VALUE_HEX})) { + +} + +void DBQuerierCommand::Help(string& ret) { + ret.append(" "); + ret.append(DBQuerierCommand::Name()); + ret.append("\n"); + ret.append(" Starts a REPL shell. Type help for list of available " + "commands."); + ret.append("\n"); +} + +void DBQuerierCommand::DoCommand() { + if (!db_) { + return; + } + + leveldb::ReadOptions read_options; + leveldb::WriteOptions write_options; + + string line; + string key; + string value; + while (getline(std::cin, line, '\n')) { + + // Parse line into vector + vector tokens; + size_t pos = 0; + while (true) { + size_t pos2 = line.find(' ', pos); + if (pos2 == string::npos) { + break; + } + tokens.push_back(line.substr(pos, pos2-pos)); + pos = pos2 + 1; + } + tokens.push_back(line.substr(pos)); + + const string& cmd = tokens[0]; + + if (cmd == HELP_CMD) { + fprintf(stdout, + "get \n" + "put \n" + "delete \n"); + } else if (cmd == DELETE_CMD && tokens.size() == 2) { + key = (is_key_hex_ ? HexToString(tokens[1]) : tokens[1]); + db_->Delete(write_options, Slice(key)); + fprintf(stdout, "Successfully deleted %s\n", tokens[1].c_str()); + } else if (cmd == PUT_CMD && tokens.size() == 3) { + key = (is_key_hex_ ? HexToString(tokens[1]) : tokens[1]); + value = (is_value_hex_ ? HexToString(tokens[2]) : tokens[2]); + db_->Put(write_options, Slice(key), Slice(value)); + fprintf(stdout, "Successfully put %s %s\n", + tokens[1].c_str(), tokens[2].c_str()); + } else if (cmd == GET_CMD && tokens.size() == 2) { + key = (is_key_hex_ ? HexToString(tokens[1]) : tokens[1]); + if (db_->Get(read_options, Slice(key), &value).ok()) { + fprintf(stdout, "%s\n", PrintKeyValue(key, value, + is_key_hex_, is_value_hex_).c_str()); + } else { + fprintf(stdout, "Not found %s\n", tokens[1].c_str()); + } + } else { + fprintf(stdout, "Unknown command %s\n", line.c_str()); + } + } +} + + +} diff --git a/util/ldb_cmd.h b/util/ldb_cmd.h new file mode 100644 index 00000000..210c78f4 --- /dev/null +++ b/util/ldb_cmd.h @@ -0,0 +1,565 @@ +// Copyright (c) 2012 Facebook. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef LEVELDB_UTIL_LDB_CMD_H_ +#define LEVELDB_UTIL_LDB_CMD_H_ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/options.h" +#include "leveldb/iterator.h" +#include "leveldb/slice.h" +#include "db/version_set.h" +#include "util/logging.h" +#include "util/ldb_cmd_execute_result.h" + +using std::string; +using std::map; +using std::vector; +using std::ostringstream; + +namespace leveldb { + +class LDBCommand { +public: + + // Command-line arguments + static const string ARG_DB; + static const string ARG_HEX; + static const string ARG_KEY_HEX; + static const string ARG_VALUE_HEX; + static const string ARG_FROM; + static const string ARG_TO; + static const string ARG_MAX_KEYS; + static const string ARG_BLOOM_BITS; + static const string ARG_COMPRESSION_TYPE; + static const string ARG_BLOCK_SIZE; + static const string ARG_AUTO_COMPACTION; + static const string ARG_WRITE_BUFFER_SIZE; + static const string ARG_FILE_SIZE; + static const string ARG_CREATE_IF_MISSING; + + static LDBCommand* InitFromCmdLineArgs(const vector& args); + static LDBCommand* InitFromCmdLineArgs(int argc, char** argv); + bool ValidateCmdLineOptions(); + + virtual leveldb::Options PrepareOptionsForOpenDB(); + + virtual bool NoDBOpen() { + return false; + } + + virtual ~LDBCommand() { + if (db_ != nullptr) { + delete db_; + db_ = nullptr; + } + } + + /* Run the command, and return the execute result. */ + void Run() { + if (!exec_state_.IsNotStarted()) { + return; + } + + if (db_ == nullptr && !NoDBOpen()) { + OpenDB(); + if (!exec_state_.IsNotStarted()) { + return; + } + } + + DoCommand(); + if (exec_state_.IsNotStarted()) { + exec_state_ = LDBCommandExecuteResult::SUCCEED(""); + } + + if (db_ != nullptr) { + CloseDB (); + } + } + + virtual void DoCommand() = 0; + + LDBCommandExecuteResult GetExecuteState() { + return exec_state_; + } + + void ClearPreviousRunState() { + exec_state_.Reset(); + } + + static string HexToString(const string& str) { + string parsed; + if (!boost::starts_with(str, "0x")) { + fprintf(stderr, "Invalid hex input %s. Must start with 0x\n", + str.c_str()); + throw "Invalid hex input"; + } + + for (unsigned int i = 2; i < str.length();) { + int c; + sscanf(str.c_str() + i, "%2X", &c); + parsed.push_back(c); + i += 2; + } + return parsed; + } + + static string StringToHex(const string& str) { + string result = "0x"; + char buf[10]; + for (size_t i = 0; i < str.length(); i++) { + snprintf(buf, 10, "%02X", (unsigned char)str[i]); + result += buf; + } + return result; + } + + static const char* DELIM; + +protected: + + LDBCommandExecuteResult exec_state_; + std::string db_path_; + leveldb::DB* db_; + + /** + * true implies that this command can work if the db is opened in read-only + * mode. + */ + bool is_read_only_; + + /** If true, the key is input/output as hex in get/put/scan/delete etc. */ + bool is_key_hex_; + + /** If true, the value is input/output as hex in get/put/scan/delete etc. */ + bool is_value_hex_; + + /** + * Map of options passed on the command-line. + */ + const map options_; + + /** + * Flags passed on the command-line. + */ + const vector flags_; + + /** List of command-line options valid for this command */ + const vector valid_cmd_line_options_; + + bool ParseKeyValue(const string& line, string* key, string* value, + bool is_key_hex, bool is_value_hex); + + LDBCommand(const map& options, const vector& flags, + bool is_read_only, const vector& valid_cmd_line_options) : + db_(nullptr), + is_read_only_(is_read_only), + is_key_hex_(false), + is_value_hex_(false), + options_(options), + flags_(flags), + valid_cmd_line_options_(valid_cmd_line_options) { + + map::const_iterator itr = options.find(ARG_DB); + if (itr != options.end()) { + db_path_ = itr->second; + } + + is_key_hex_ = IsKeyHex(options, flags); + is_value_hex_ = IsValueHex(options, flags); + } + + void OpenDB() { + leveldb::Options opt = PrepareOptionsForOpenDB(); + if (!exec_state_.IsNotStarted()) { + return; + } + // Open the DB. + leveldb::Status st; + if (is_read_only_) { + st = leveldb::DB::OpenForReadOnly(opt, db_path_, &db_); + } else { + st = leveldb::DB::Open(opt, db_path_, &db_); + } + if (!st.ok()) { + std::string msg = st.ToString(); + exec_state_ = LDBCommandExecuteResult::FAILED(msg); + } + } + + void CloseDB () { + if (db_ != nullptr) { + delete db_; + db_ = nullptr; + } + } + + static string PrintKeyValue(const string& key, const string& value, + bool is_key_hex, bool is_value_hex) { + string result; + result.append(is_key_hex ? StringToHex(key) : key); + result.append(DELIM); + result.append(is_value_hex ? StringToHex(value) : value); + return result; + } + + static string PrintKeyValue(const string& key, const string& value, + bool is_hex) { + return PrintKeyValue(key, value, is_hex, is_hex); + } + + /** + * Return true if the specified flag is present in the specified flags vector + */ + static bool IsFlagPresent(const vector& flags, const string& flag) { + return (std::find(flags.begin(), flags.end(), flag) != flags.end()); + } + + static string HelpRangeCmdArgs() { + ostringstream str_stream; + str_stream << " "; + str_stream << "[--" << ARG_FROM << "] "; + str_stream << "[--" << ARG_TO << "] "; + return str_stream.str(); + } + + /** + * A helper function that returns a list of command line options + * used by this command. It includes the common options and the ones + * passed in. + */ + vector BuildCmdLineOptions(vector options) { + vector ret = {ARG_DB, ARG_BLOOM_BITS, ARG_BLOCK_SIZE, + ARG_AUTO_COMPACTION, ARG_COMPRESSION_TYPE, + ARG_WRITE_BUFFER_SIZE, ARG_FILE_SIZE}; + ret.insert(ret.end(), options.begin(), options.end()); + return ret; + } + + bool ParseIntOption(const map& options, string option, + int& value, LDBCommandExecuteResult& exec_state); + +private: + + /** + * Interpret command line options and flags to determine if the key + * should be input/output in hex. + */ + bool IsKeyHex(const map& options, + const vector& flags) { + return (IsFlagPresent(flags, ARG_HEX) || + IsFlagPresent(flags, ARG_KEY_HEX) || + ParseBooleanOption(options, ARG_HEX, false) || + ParseBooleanOption(options, ARG_KEY_HEX, false)); + } + + /** + * Interpret command line options and flags to determine if the value + * should be input/output in hex. + */ + bool IsValueHex(const map& options, + const vector& flags) { + return (IsFlagPresent(flags, ARG_HEX) || + IsFlagPresent(flags, ARG_VALUE_HEX) || + ParseBooleanOption(options, ARG_HEX, false) || + ParseBooleanOption(options, ARG_VALUE_HEX, false)); + } + + /** + * Returns the value of the specified option as a boolean. + * default_val is used if the option is not found in options. + * Throws an exception if the value of the option is not + * "true" or "false" (case insensitive). + */ + bool ParseBooleanOption(const map& options, + const string& option, bool default_val) { + + map::const_iterator itr = options.find(option); + if (itr != options.end()) { + string option_val = itr->second; + return StringToBool(itr->second); + } + return default_val; + } + + /** + * Converts val to a boolean. + * val must be either true or false (case insensitive). + * Otherwise an exception is thrown. + */ + bool StringToBool(string val) { + boost::algorithm::to_lower(val); + if (val == "true") { + return true; + } else if (val == "false") { + return false; + } else { + throw "Invalid value for boolean argument"; + } + } + +}; + +class CompactorCommand: public LDBCommand { +public: + static string Name() { return "compact"; } + + CompactorCommand(const vector& params, + const map& options, const vector& flags); + + static void Help(string& ret); + + virtual void DoCommand(); + +private: + bool null_from_; + string from_; + bool null_to_; + string to_; +}; + +class DBDumperCommand: public LDBCommand { +public: + static string Name() { return "dump"; } + + DBDumperCommand(const vector& params, + const map& options, const vector& flags); + + static void Help(string& ret); + + virtual void DoCommand(); + +private: + bool null_from_; + string from_; + bool null_to_; + string to_; + int max_keys_; + bool count_only_; + bool print_stats_; + + static const string ARG_COUNT_ONLY; + static const string ARG_STATS; +}; + +class DBLoaderCommand: public LDBCommand { +public: + static string Name() { return "load"; } + + DBLoaderCommand(string& db_name, vector& args); + + DBLoaderCommand(const vector& params, + const map& options, const vector& flags); + + static void Help(string& ret); + virtual void DoCommand(); + + virtual leveldb::Options PrepareOptionsForOpenDB(); + +private: + bool create_if_missing_; + bool disable_wal_; + bool bulk_load_; + bool compact_; + + static const string ARG_DISABLE_WAL; + static const string ARG_BULK_LOAD; + static const string ARG_COMPACT; +}; + +class ReduceDBLevelsCommand : public LDBCommand { +public: + static string Name() { return "reduce_levels"; } + + ReduceDBLevelsCommand(const vector& params, + const map& options, const vector& flags); + + virtual leveldb::Options PrepareOptionsForOpenDB(); + + virtual void DoCommand(); + + virtual bool NoDBOpen() { + return true; + } + + static void Help(string& msg); + + static vector PrepareArgs(const string& db_path, int new_levels, + bool print_old_level = false); + +private: + int old_levels_; + int new_levels_; + bool print_old_levels_; + + static const string ARG_NEW_LEVELS; + static const string ARG_PRINT_OLD_LEVELS; + + Status GetOldNumOfLevels(leveldb::Options& opt, int* levels); +}; + +class WALDumperCommand : public LDBCommand { +public: + static string Name() { return "dump_wal"; } + + WALDumperCommand(const vector& params, + const map& options, const vector& flags); + + virtual bool NoDBOpen() { + return true; + } + + static void Help(string& ret); + virtual void DoCommand(); + +private: + bool print_header_; + string wal_file_; + bool print_values_; + + static const string ARG_WAL_FILE; + static const string ARG_PRINT_HEADER; + static const string ARG_PRINT_VALUE; +}; + + +class GetCommand : public LDBCommand { +public: + static string Name() { return "get"; } + + GetCommand(const vector& params, const map& options, + const vector& flags); + + virtual void DoCommand(); + + static void Help(string& ret); + +private: + string key_; +}; + +class ApproxSizeCommand : public LDBCommand { +public: + static string Name() { return "approxsize"; } + + ApproxSizeCommand(const vector& params, + const map& options, const vector& flags); + + virtual void DoCommand(); + + static void Help(string& ret); + +private: + string start_key_; + string end_key_; +}; + +class BatchPutCommand : public LDBCommand { +public: + static string Name() { return "batchput"; } + + BatchPutCommand(const vector& params, + const map& options, const vector& flags); + + virtual void DoCommand(); + + static void Help(string& ret); + + virtual leveldb::Options PrepareOptionsForOpenDB(); + +private: + /** + * The key-values to be inserted. + */ + vector> key_values_; +}; + +class ScanCommand : public LDBCommand { +public: + static string Name() { return "scan"; } + + ScanCommand(const vector& params, const map& options, + const vector& flags); + + virtual void DoCommand(); + + static void Help(string& ret); + +private: + string start_key_; + string end_key_; + bool start_key_specified_; + bool end_key_specified_; + int max_keys_scanned_; +}; + +class DeleteCommand : public LDBCommand { +public: + static string Name() { return "delete"; } + + DeleteCommand(const vector& params, + const map& options, const vector& flags); + + virtual void DoCommand(); + + static void Help(string& ret); + +private: + string key_; +}; + +class PutCommand : public LDBCommand { +public: + static string Name() { return "put"; } + + PutCommand(const vector& params, const map& options, + const vector& flags); + + virtual void DoCommand(); + + static void Help(string& ret); + + virtual leveldb::Options PrepareOptionsForOpenDB(); + +private: + string key_; + string value_; +}; + +/** + * Command that starts up a REPL shell that allows + * get/put/delete. + */ +class DBQuerierCommand: public LDBCommand { +public: + static string Name() { return "query"; } + + DBQuerierCommand(const vector& params, + const map& options, const vector& flags); + + static void Help(string& ret); + + virtual void DoCommand(); + +private: + static const char* HELP_CMD; + static const char* GET_CMD; + static const char* PUT_CMD; + static const char* DELETE_CMD; +}; + +} +#endif diff --git a/util/ldb_cmd_execute_result.h b/util/ldb_cmd_execute_result.h new file mode 100644 index 00000000..fb94a20b --- /dev/null +++ b/util/ldb_cmd_execute_result.h @@ -0,0 +1,74 @@ +#ifndef LEVELDB_UTIL_LDB_CMD_EXECUTE_RESULT_H_ +#define LEVELDB_UTIL_LDB_CMD_EXECUTE_RESULT_H_ + +namespace leveldb { + +class LDBCommandExecuteResult { +public: + enum State { + EXEC_NOT_STARTED = 0, EXEC_SUCCEED = 1, EXEC_FAILED = 2, + }; + + LDBCommandExecuteResult() { + state_ = EXEC_NOT_STARTED; + message_ = ""; + } + + LDBCommandExecuteResult(State state, std::string& msg) { + state_ = state; + message_ = msg; + } + + std::string ToString() { + std::string ret; + switch (state_) { + case EXEC_SUCCEED: + break; + case EXEC_FAILED: + ret.append("Failed: "); + break; + case EXEC_NOT_STARTED: + ret.append("Not started: "); + } + if (!message_.empty()) { + ret.append(message_); + } + return ret; + } + + void Reset() { + state_ = EXEC_NOT_STARTED; + message_ = ""; + } + + bool IsSucceed() { + return state_ == EXEC_SUCCEED; + } + + bool IsNotStarted() { + return state_ == EXEC_NOT_STARTED; + } + + bool IsFailed() { + return state_ == EXEC_FAILED; + } + + static LDBCommandExecuteResult SUCCEED(std::string msg) { + return LDBCommandExecuteResult(EXEC_SUCCEED, msg); + } + + static LDBCommandExecuteResult FAILED(std::string msg) { + return LDBCommandExecuteResult(EXEC_FAILED, msg); + } + +private: + State state_; + std::string message_; + + bool operator==(const LDBCommandExecuteResult&); + bool operator!=(const LDBCommandExecuteResult&); +}; + +} + +#endif diff --git a/util/logging.cc b/util/logging.cc new file mode 100644 index 00000000..9fb46304 --- /dev/null +++ b/util/logging.cc @@ -0,0 +1,81 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/logging.h" + +#include +#include +#include +#include +#include "leveldb/env.h" +#include "leveldb/slice.h" + +namespace leveldb { + +void AppendNumberTo(std::string* str, uint64_t num) { + char buf[30]; + snprintf(buf, sizeof(buf), "%llu", (unsigned long long) num); + str->append(buf); +} + +void AppendEscapedStringTo(std::string* str, const Slice& value) { + for (size_t i = 0; i < value.size(); i++) { + char c = value[i]; + if (c >= ' ' && c <= '~') { + str->push_back(c); + } else { + char buf[10]; + snprintf(buf, sizeof(buf), "\\x%02x", + static_cast(c) & 0xff); + str->append(buf); + } + } +} + +std::string NumberToString(uint64_t num) { + std::string r; + AppendNumberTo(&r, num); + return r; +} + +std::string EscapeString(const Slice& value) { + std::string r; + AppendEscapedStringTo(&r, value); + return r; +} + +bool ConsumeChar(Slice* in, char c) { + if (!in->empty() && (*in)[0] == c) { + in->remove_prefix(1); + return true; + } else { + return false; + } +} + +bool ConsumeDecimalNumber(Slice* in, uint64_t* val) { + uint64_t v = 0; + int digits = 0; + while (!in->empty()) { + char c = (*in)[0]; + if (c >= '0' && c <= '9') { + ++digits; + const unsigned int delta = (c - '0'); + static const uint64_t kMaxUint64 = ~static_cast(0); + if (v > kMaxUint64/10 || + (v == kMaxUint64/10 && delta > kMaxUint64%10)) { + // Overflow + return false; + } + v = (v * 10) + delta; + in->remove_prefix(1); + } else { + break; + } + } + *val = v; + return (digits > 0); +} + +} // namespace leveldb diff --git a/util/logging.h b/util/logging.h new file mode 100644 index 00000000..b0c5da81 --- /dev/null +++ b/util/logging.h @@ -0,0 +1,47 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Must not be included from any .h files to avoid polluting the namespace +// with macros. + +#ifndef STORAGE_LEVELDB_UTIL_LOGGING_H_ +#define STORAGE_LEVELDB_UTIL_LOGGING_H_ + +#include +#include +#include +#include "port/port.h" + +namespace leveldb { + +class Slice; +class WritableFile; + +// Append a human-readable printout of "num" to *str +extern void AppendNumberTo(std::string* str, uint64_t num); + +// Append a human-readable printout of "value" to *str. +// Escapes any non-printable characters found in "value". +extern void AppendEscapedStringTo(std::string* str, const Slice& value); + +// Return a human-readable printout of "num" +extern std::string NumberToString(uint64_t num); + +// Return a human-readable version of "value". +// Escapes any non-printable characters found in "value". +extern std::string EscapeString(const Slice& value); + +// If *in starts with "c", advances *in past the first character and +// returns true. Otherwise, returns false. +extern bool ConsumeChar(Slice* in, char c); + +// Parse a human-readable number from "*in" into *value. On success, +// advances "*in" past the consumed number and sets "*val" to the +// numeric value. Otherwise, returns false and leaves *in in an +// unspecified state. +extern bool ConsumeDecimalNumber(Slice* in, uint64_t* val); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_LOGGING_H_ diff --git a/util/murmurhash.cc b/util/murmurhash.cc new file mode 100644 index 00000000..2c650d8b --- /dev/null +++ b/util/murmurhash.cc @@ -0,0 +1,178 @@ +/* + Murmurhash from http://sites.google.com/site/murmurhash/ + + All code is released to the public domain. For business purposes, Murmurhash is + under the MIT license. +*/ +#include "murmurhash.h" + +#if defined(__x86_64__) + +// ------------------------------------------------------------------- +// +// The same caveats as 32-bit MurmurHash2 apply here - beware of alignment +// and endian-ness issues if used across multiple platforms. +// +// 64-bit hash for 64-bit platforms + +uint64_t MurmurHash64A ( const void * key, int len, unsigned int seed ) +{ + const uint64_t m = 0xc6a4a7935bd1e995; + const int r = 47; + + uint64_t h = seed ^ (len * m); + + const uint64_t * data = (const uint64_t *)key; + const uint64_t * end = data + (len/8); + + while(data != end) + { + uint64_t k = *data++; + + k *= m; + k ^= k >> r; + k *= m; + + h ^= k; + h *= m; + } + + const unsigned char * data2 = (const unsigned char*)data; + + switch(len & 7) + { + case 7: h ^= ((uint64_t)data2[6]) << 48; + case 6: h ^= ((uint64_t)data2[5]) << 40; + case 5: h ^= ((uint64_t)data2[4]) << 32; + case 4: h ^= ((uint64_t)data2[3]) << 24; + case 3: h ^= ((uint64_t)data2[2]) << 16; + case 2: h ^= ((uint64_t)data2[1]) << 8; + case 1: h ^= ((uint64_t)data2[0]); + h *= m; + }; + + h ^= h >> r; + h *= m; + h ^= h >> r; + + return h; +} + +#elif defined(__i386__) + +// ------------------------------------------------------------------- +// +// Note - This code makes a few assumptions about how your machine behaves - +// +// 1. We can read a 4-byte value from any address without crashing +// 2. sizeof(int) == 4 +// +// And it has a few limitations - +// +// 1. It will not work incrementally. +// 2. It will not produce the same results on little-endian and big-endian +// machines. + +unsigned int MurmurHash2 ( const void * key, int len, unsigned int seed ) +{ + // 'm' and 'r' are mixing constants generated offline. + // They're not really 'magic', they just happen to work well. + + const unsigned int m = 0x5bd1e995; + const int r = 24; + + // Initialize the hash to a 'random' value + + unsigned int h = seed ^ len; + + // Mix 4 bytes at a time into the hash + + const unsigned char * data = (const unsigned char *)key; + + while(len >= 4) + { + unsigned int k = *(unsigned int *)data; + + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + + data += 4; + len -= 4; + } + + // Handle the last few bytes of the input array + + switch(len) + { + case 3: h ^= data[2] << 16; + case 2: h ^= data[1] << 8; + case 1: h ^= data[0]; + h *= m; + }; + + // Do a few final mixes of the hash to ensure the last few + // bytes are well-incorporated. + + h ^= h >> 13; + h *= m; + h ^= h >> 15; + + return h; +} + +#else + +// ------------------------------------------------------------------- +// +// Same as MurmurHash2, but endian- and alignment-neutral. +// Half the speed though, alas. + +unsigned int MurmurHashNeutral2 ( const void * key, int len, unsigned int seed ) +{ + const unsigned int m = 0x5bd1e995; + const int r = 24; + + unsigned int h = seed ^ len; + + const unsigned char * data = (const unsigned char *)key; + + while(len >= 4) + { + unsigned int k; + + k = data[0]; + k |= data[1] << 8; + k |= data[2] << 16; + k |= data[3] << 24; + + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + + data += 4; + len -= 4; + } + + switch(len) + { + case 3: h ^= data[2] << 16; + case 2: h ^= data[1] << 8; + case 1: h ^= data[0]; + h *= m; + }; + + h ^= h >> 13; + h *= m; + h ^= h >> 15; + + return h; +} + +#endif diff --git a/util/murmurhash.h b/util/murmurhash.h new file mode 100644 index 00000000..1f476b66 --- /dev/null +++ b/util/murmurhash.h @@ -0,0 +1,32 @@ +/* + Murmurhash from http://sites.google.com/site/murmurhash/ + + All code is released to the public domain. For business purposes, Murmurhash is + under the MIT license. +*/ +#ifndef MURMURHASH_H +#define MURMURHASH_H + +#include + +#if defined(__x86_64__) +#define MURMUR_HASH MurmurHash64A +uint64_t MurmurHash64A ( const void * key, int len, unsigned int seed ); +#define MurmurHash MurmurHash64A +typedef uint64_t murmur_t; + +#elif defined(__i386__) +#define MURMUR_HASH MurmurHash2 +unsigned int MurmurHash2 ( const void * key, int len, unsigned int seed ); +#define MurmurHash MurmurHash2 +typedef unsigned int murmur_t; + +#else +#define MURMUR_HASH MurmurHashNeutral2 +unsigned int MurmurHashNeutral2 ( const void * key, int len, unsigned int seed ); +#define MurmurHash MurmurHashNeutral2 +typedef unsigned int murmur_t; + +#endif + +#endif /* MURMURHASH_H */ diff --git a/util/mutexlock.h b/util/mutexlock.h new file mode 100644 index 00000000..8817e55c --- /dev/null +++ b/util/mutexlock.h @@ -0,0 +1,78 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_ +#define STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_ + +#include "port/port.h" + +namespace leveldb { + +// Helper class that locks a mutex on construction and unlocks the mutex when +// the destructor of the MutexLock object is invoked. +// +// Typical usage: +// +// void MyClass::MyMethod() { +// MutexLock l(&mu_); // mu_ is an instance variable +// ... some complex code, possibly with multiple return paths ... +// } + +class MutexLock { + public: + explicit MutexLock(port::Mutex *mu) : mu_(mu) { + this->mu_->Lock(); + } + ~MutexLock() { this->mu_->Unlock(); } + + private: + port::Mutex *const mu_; + // No copying allowed + MutexLock(const MutexLock&); + void operator=(const MutexLock&); +}; + +// +// Acquire a ReadLock on the specified RWMutex. +// The Lock will be automatically released then the +// object goes out of scope. +// +class ReadLock { + public: + explicit ReadLock(port::RWMutex *mu) : mu_(mu) { + this->mu_->ReadLock(); + } + ~ReadLock() { this->mu_->Unlock(); } + + private: + port::RWMutex *const mu_; + // No copying allowed + ReadLock(const ReadLock&); + void operator=(const ReadLock&); +}; + + +// +// Acquire a WriteLock on the specified RWMutex. +// The Lock will be automatically released then the +// object goes out of scope. +// +class WriteLock { + public: + explicit WriteLock(port::RWMutex *mu) : mu_(mu) { + this->mu_->WriteLock(); + } + ~WriteLock() { this->mu_->Unlock(); } + + private: + port::RWMutex *const mu_; + // No copying allowed + WriteLock(const WriteLock&); + void operator=(const WriteLock&); +}; + +} // namespace leveldb + + +#endif // STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_ diff --git a/util/options.cc b/util/options.cc new file mode 100644 index 00000000..9597b7c8 --- /dev/null +++ b/util/options.cc @@ -0,0 +1,178 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/options.h" + +#include + +#include "leveldb/comparator.h" +#include "leveldb/env.h" +#include "leveldb/filter_policy.h" +#include "leveldb/cache.h" + +namespace leveldb { + +Options::Options() + : comparator(BytewiseComparator()), + create_if_missing(false), + error_if_exists(false), + paranoid_checks(false), + env(Env::Default()), + info_log(nullptr), + write_buffer_size(4<<20), + max_write_buffer_number(2), + max_open_files(1000), + block_size(4096), + block_restart_interval(16), + compression(kSnappyCompression), + filter_policy(nullptr), + num_levels(7), + level0_file_num_compaction_trigger(4), + level0_slowdown_writes_trigger(8), + level0_stop_writes_trigger(12), + max_mem_compaction_level(2), + target_file_size_base(2 * 1048576), + target_file_size_multiplier(1), + max_bytes_for_level_base(10 * 1048576), + max_bytes_for_level_multiplier(10), + expanded_compaction_factor(25), + source_compaction_factor(1), + max_grandparent_overlap_factor(10), + statistics(nullptr), + disableDataSync(false), + use_fsync(false), + db_stats_log_interval(1800), + db_log_dir(""), + disable_seek_compaction(false), + delete_obsolete_files_period_micros(0), + max_background_compactions(1), + max_log_file_size(0), + log_file_time_to_roll(0), + keep_log_file_num(1000), + rate_limit(0.0), + rate_limit_delay_milliseconds(1000), + max_manifest_file_size(std::numeric_limits::max()), + no_block_cache(false), + table_cache_numshardbits(4), + compaction_filter_args(nullptr), + CompactionFilter(nullptr), + disable_auto_compactions(false), + WAL_ttl_seconds(0), + manifest_preallocation_size(4 * 1024 * 1024), + purge_redundant_kvs_while_flush(true) { + +} + +void +Options::Dump(Logger* log) const +{ + Log(log," Options.comparator: %s", comparator->Name()); + Log(log," Options.create_if_missing: %d", create_if_missing); + Log(log," Options.error_if_exists: %d", error_if_exists); + Log(log," Options.paranoid_checks: %d", paranoid_checks); + Log(log," Options.env: %p", env); + Log(log," Options.info_log: %p", info_log.get()); + Log(log," Options.write_buffer_size: %zd", write_buffer_size); + Log(log," Options.max_write_buffer_number: %d", max_write_buffer_number); + Log(log," Options.max_open_files: %d", max_open_files); + Log(log," Options.block_cache: %p", block_cache.get()); + if (block_cache) { + Log(log," Options.block_cache_size: %zd", + block_cache->GetCapacity()); + } + Log(log," Options.block_size: %zd", block_size); + Log(log," Options.block_restart_interval: %d", block_restart_interval); + if (!compression_per_level.empty()) { + for (int i = 0; i < compression_per_level.size(); i++) { + Log(log," Options.compression[%d]: %d", + i, compression_per_level[i]); + } + } else { + Log(log," Options.compression: %d", compression); + } + Log(log," Options.filter_policy: %s", + filter_policy == nullptr ? "nullptr" : filter_policy->Name()); + Log(log," Options.num_levels: %d", num_levels); + Log(log," Options.disableDataSync: %d", disableDataSync); + Log(log," Options.use_fsync: %d", use_fsync); + Log(log," Options.max_log_file_size: %ld", max_log_file_size); + Log(log,"Options.max_manifest_file_size: %ld", + max_manifest_file_size); + Log(log," Options.log_file_time_to_roll: %ld", log_file_time_to_roll); + Log(log," Options.keep_log_file_num: %ld", keep_log_file_num); + Log(log," Options.db_stats_log_interval: %d", + db_stats_log_interval); + Log(log," Options.purge_redundant_kvs_while_flush: %d", + purge_redundant_kvs_while_flush); + Log(log," Options.compression_opts.window_bits: %d", + compression_opts.window_bits); + Log(log," Options.compression_opts.level: %d", + compression_opts.level); + Log(log," Options.compression_opts.strategy: %d", + compression_opts.strategy); + Log(log," Options.level0_file_num_compaction_trigger: %d", + level0_file_num_compaction_trigger); + Log(log," Options.level0_slowdown_writes_trigger: %d", + level0_slowdown_writes_trigger); + Log(log," Options.level0_stop_writes_trigger: %d", + level0_stop_writes_trigger); + Log(log," Options.max_mem_compaction_level: %d", + max_mem_compaction_level); + Log(log," Options.target_file_size_base: %d", + target_file_size_base); + Log(log," Options.target_file_size_multiplier: %d", + target_file_size_multiplier); + Log(log," Options.max_bytes_for_level_base: %ld", + max_bytes_for_level_base); + Log(log," Options.max_bytes_for_level_multiplier: %d", + max_bytes_for_level_multiplier); + Log(log," Options.expanded_compaction_factor: %d", + expanded_compaction_factor); + Log(log," Options.source_compaction_factor: %d", + source_compaction_factor); + Log(log," Options.max_grandparent_overlap_factor: %d", + max_grandparent_overlap_factor); + Log(log," Options.db_log_dir: %s", + db_log_dir.c_str()); + Log(log," Options.disable_seek_compaction: %d", + disable_seek_compaction); + Log(log," Options.no_block_cache: %d", + no_block_cache); + Log(log," Options.table_cache_numshardbits: %d", + table_cache_numshardbits); + Log(log," Options.delete_obsolete_files_period_micros: %ld", + delete_obsolete_files_period_micros); + Log(log," Options.max_background_compactions: %d", + max_background_compactions); + Log(log," Options.rate_limit: %.2f", + rate_limit); + Log(log," Options.rate_limit_delay_milliseconds: %d", + rate_limit_delay_milliseconds); + Log(log," Options.compaction_filter_args: %p", + compaction_filter_args); + Log(log," Options.CompactionFilter: %p", + CompactionFilter); + Log(log," Options.disable_auto_compactions: %d", + disable_auto_compactions); + Log(log," Options.WAL_ttl_seconds: %ld", + WAL_ttl_seconds); + Log(log," Options.manifest_preallocation_size: %ld", + manifest_preallocation_size); +} // Options::Dump + +Options* +Options::PrepareForBulkLoad() +{ + level0_file_num_compaction_trigger = (1<<30); + level0_slowdown_writes_trigger = (1<<30); + level0_stop_writes_trigger = (1<<30); + disable_auto_compactions = true; + disable_seek_compaction = true; + disableDataSync = true; + source_compaction_factor = (1<<30); + + return this; +} + +} // namespace leveldb diff --git a/util/posix_logger.h b/util/posix_logger.h new file mode 100644 index 00000000..b1fbfd97 --- /dev/null +++ b/util/posix_logger.h @@ -0,0 +1,132 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Logger implementation that can be shared by all environments +// where enough posix functionality is available. + +#ifndef STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ +#define STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ + +#include +#include +#include +#include +#include +#include +#ifdef OS_LINUX +#include +#endif +#include "leveldb/env.h" + +namespace leveldb { + +const int kDebugLogChunkSize = 128 * 1024; + +class PosixLogger : public Logger { + private: + FILE* file_; + uint64_t (*gettid_)(); // Return the thread id for the current thread + + size_t log_size_; + int fd_; + public: + PosixLogger(FILE* f, uint64_t (*gettid)()) : + file_(f), gettid_(gettid), log_size_(0), fd_(fileno(f)) { } + virtual ~PosixLogger() { + fclose(file_); + } + virtual void Logv(const char* format, va_list ap) { + const uint64_t thread_id = (*gettid_)(); + + // We try twice: the first time with a fixed-size stack allocated buffer, + // and the second time with a much larger dynamically allocated buffer. + char buffer[500]; + for (int iter = 0; iter < 2; iter++) { + char* base; + int bufsize; + if (iter == 0) { + bufsize = sizeof(buffer); + base = buffer; + } else { + bufsize = 30000; + base = new char[bufsize]; + } + char* p = base; + char* limit = base + bufsize; + + struct timeval now_tv; + gettimeofday(&now_tv, nullptr); + const time_t seconds = now_tv.tv_sec; + struct tm t; + localtime_r(&seconds, &t); + p += snprintf(p, limit - p, + "%04d/%02d/%02d-%02d:%02d:%02d.%06d %llx ", + t.tm_year + 1900, + t.tm_mon + 1, + t.tm_mday, + t.tm_hour, + t.tm_min, + t.tm_sec, + static_cast(now_tv.tv_usec), + static_cast(thread_id)); + + // Print the message + if (p < limit) { + va_list backup_ap; + va_copy(backup_ap, ap); + p += vsnprintf(p, limit - p, format, backup_ap); + va_end(backup_ap); + } + + // Truncate to available space if necessary + if (p >= limit) { + if (iter == 0) { + continue; // Try again with larger buffer + } else { + p = limit - 1; + } + } + + // Add newline if necessary + if (p == base || p[-1] != '\n') { + *p++ = '\n'; + } + + assert(p <= limit); + +#ifdef OS_LINUX + // If this write would cross a boundary of kDebugLogChunkSize + // space, pre-allocate more space to avoid overly large + // allocations from filesystem allocsize options. + const size_t write_size = p - base; + const int last_allocation_chunk = + ((kDebugLogChunkSize - 1 + log_size_) / kDebugLogChunkSize); + const int desired_allocation_chunk = + ((kDebugLogChunkSize - 1 + log_size_ + write_size) / + kDebugLogChunkSize); + if (last_allocation_chunk != desired_allocation_chunk) { + fallocate(fd_, FALLOC_FL_KEEP_SIZE, 0, + desired_allocation_chunk * kDebugLogChunkSize); + } +#endif + + fwrite(base, 1, write_size, file_); + fflush(file_); + + log_size_ += write_size; + + if (base != buffer) { + delete[] base; + } + break; + } + } + size_t GetLogFileSize() const { + return log_size_; + } +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ diff --git a/util/random.h b/util/random.h new file mode 100644 index 00000000..07538242 --- /dev/null +++ b/util/random.h @@ -0,0 +1,59 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_RANDOM_H_ +#define STORAGE_LEVELDB_UTIL_RANDOM_H_ + +#include + +namespace leveldb { + +// A very simple random number generator. Not especially good at +// generating truly random bits, but good enough for our needs in this +// package. +class Random { + private: + uint32_t seed_; + public: + explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) { } + uint32_t Next() { + static const uint32_t M = 2147483647L; // 2^31-1 + static const uint64_t A = 16807; // bits 14, 8, 7, 5, 2, 1, 0 + // We are computing + // seed_ = (seed_ * A) % M, where M = 2^31-1 + // + // seed_ must not be zero or M, or else all subsequent computed values + // will be zero or M respectively. For all other values, seed_ will end + // up cycling through every number in [1,M-1] + uint64_t product = seed_ * A; + + // Compute (product % M) using the fact that ((x << 31) % M) == x. + seed_ = static_cast((product >> 31) + (product & M)); + // The first reduction may overflow by 1 bit, so we may need to + // repeat. mod == M is not possible; using > allows the faster + // sign-bit-based test. + if (seed_ > M) { + seed_ -= M; + } + return seed_; + } + // Returns a uniformly distributed value in the range [0..n-1] + // REQUIRES: n > 0 + uint32_t Uniform(int n) { return Next() % n; } + + // Randomly returns true ~"1/n" of the time, and false otherwise. + // REQUIRES: n > 0 + bool OneIn(int n) { return (Next() % n) == 0; } + + // Skewed: pick "base" uniformly from range [0,max_log] and then + // return "base" random bits. The effect is to pick a number in the + // range [0,2^max_log-1] with exponential bias towards smaller numbers. + uint32_t Skewed(int max_log) { + return Uniform(1 << Uniform(max_log + 1)); + } +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_RANDOM_H_ diff --git a/util/stats_logger.h b/util/stats_logger.h new file mode 100644 index 00000000..a0799730 --- /dev/null +++ b/util/stats_logger.h @@ -0,0 +1,24 @@ +#ifndef STATS_LOGGER_H_ +#define STATS_LOGGER_H_ + +namespace leveldb { + +class StatsLogger { + + public: + + virtual void Log_Deploy_Stats(const std::string& db_version, + const std::string& machine_info, + const std::string& data_dir, + const uint64_t data_size, + const uint32_t file_number, + const std::string& data_size_per_level, + const std::string& file_number_per_level, + const int64_t& ts_unix) = 0; + virtual ~StatsLogger() {} + +}; + +} + +#endif diff --git a/util/status.cc b/util/status.cc new file mode 100644 index 00000000..5591381a --- /dev/null +++ b/util/status.cc @@ -0,0 +1,75 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include "port/port.h" +#include "leveldb/status.h" + +namespace leveldb { + +const char* Status::CopyState(const char* state) { + uint32_t size; + memcpy(&size, state, sizeof(size)); + char* result = new char[size + 5]; + memcpy(result, state, size + 5); + return result; +} + +Status::Status(Code code, const Slice& msg, const Slice& msg2) { + assert(code != kOk); + const uint32_t len1 = msg.size(); + const uint32_t len2 = msg2.size(); + const uint32_t size = len1 + (len2 ? (2 + len2) : 0); + char* result = new char[size + 5]; + memcpy(result, &size, sizeof(size)); + result[4] = static_cast(code); + memcpy(result + 5, msg.data(), len1); + if (len2) { + result[5 + len1] = ':'; + result[6 + len1] = ' '; + memcpy(result + 7 + len1, msg2.data(), len2); + } + state_ = result; +} + +std::string Status::ToString() const { + if (state_ == nullptr) { + return "OK"; + } else { + char tmp[30]; + const char* type; + switch (code()) { + case kOk: + type = "OK"; + break; + case kNotFound: + type = "NotFound: "; + break; + case kCorruption: + type = "Corruption: "; + break; + case kNotSupported: + type = "Not implemented: "; + break; + case kInvalidArgument: + type = "Invalid argument: "; + break; + case kIOError: + type = "IO error: "; + break; + default: + snprintf(tmp, sizeof(tmp), "Unknown code(%d): ", + static_cast(code())); + type = tmp; + break; + } + std::string result(type); + uint32_t length; + memcpy(&length, state_, sizeof(length)); + result.append(state_ + 5, length); + return result; + } +} + +} // namespace leveldb diff --git a/util/stop_watch.h b/util/stop_watch.h new file mode 100644 index 00000000..a9507bbf --- /dev/null +++ b/util/stop_watch.h @@ -0,0 +1,68 @@ +#ifndef STORAGE_LEVELDB_UTIL_STOP_WATCH_H_ +#define STORAGE_LEVELDB_UTIL_STOP_WATCH_H_ + +#include "leveldb/env.h" +#include "leveldb/statistics.h" +#include +namespace leveldb { + +class StopWatch { + public: + virtual uint64_t ElapsedMicros() = 0; + virtual ~StopWatch() {} +}; + +class DoNothingStopWatch : public StopWatch { + public: + virtual uint64_t ElapsedMicros() { + return 0; + } +}; + +// Auto-scoped. +// Records the statistic into the corresponding histogram. +class ScopedRecordingStopWatch : public StopWatch { + public: + ScopedRecordingStopWatch(Env * const env, + Statistics * const statistics, + const Histograms histogram_name) : + env_(env), + start_time_(env->NowMicros()), + statistics_(statistics), + histogram_name_(histogram_name) {} + + virtual uint64_t ElapsedMicros() { + return env_->NowMicros() - start_time_; + } + + virtual ~ScopedRecordingStopWatch() { + uint64_t elapsed_time = env_->NowMicros() - start_time_; + statistics_->measureTime(histogram_name_, elapsed_time); + } + + private: + Env* const env_; + const uint64_t start_time_; + Statistics* const statistics_; + const Histograms histogram_name_; + +}; + +namespace stats { +// Helper method +std::unique_ptr StartStopWatch(Env * const env, + Statistics * const statistics, + Histograms histogram_name) { + assert(env); + if (statistics != nullptr) { + return std::unique_ptr(new ScopedRecordingStopWatch( + env, + statistics, + histogram_name)); + } else { + return std::unique_ptr(new DoNothingStopWatch()); + } +}; +} // namespace stats +} // namespace leveldb +#endif // STORAGE_LEVELDB_UTIL_STOP_WATCH_H_ diff --git a/util/testharness.cc b/util/testharness.cc new file mode 100644 index 00000000..5a3c8427 --- /dev/null +++ b/util/testharness.cc @@ -0,0 +1,77 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/testharness.h" + +#include +#include +#include +#include + +namespace leveldb { +namespace test { + +namespace { +struct Test { + const char* base; + const char* name; + void (*func)(); +}; +std::vector* tests; +} + +bool RegisterTest(const char* base, const char* name, void (*func)()) { + if (tests == nullptr) { + tests = new std::vector; + } + Test t; + t.base = base; + t.name = name; + t.func = func; + tests->push_back(t); + return true; +} + +int RunAllTests() { + const char* matcher = getenv("LEVELDB_TESTS"); + + int num = 0; + if (tests != nullptr) { + for (unsigned int i = 0; i < tests->size(); i++) { + const Test& t = (*tests)[i]; + if (matcher != nullptr) { + std::string name = t.base; + name.push_back('.'); + name.append(t.name); + if (strstr(name.c_str(), matcher) == nullptr) { + continue; + } + } + fprintf(stderr, "==== Test %s.%s\n", t.base, t.name); + (*t.func)(); + ++num; + } + } + fprintf(stderr, "==== PASSED %d tests\n", num); + return 0; +} + +std::string TmpDir() { + std::string dir; + Status s = Env::Default()->GetTestDirectory(&dir); + ASSERT_TRUE(s.ok()) << s.ToString(); + return dir; +} + +int RandomSeed() { + const char* env = getenv("TEST_RANDOM_SEED"); + int result = (env != nullptr ? atoi(env) : 301); + if (result <= 0) { + result = 301; + } + return result; +} + +} // namespace test +} // namespace leveldb diff --git a/util/testharness.h b/util/testharness.h new file mode 100644 index 00000000..da4fe68b --- /dev/null +++ b/util/testharness.h @@ -0,0 +1,138 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ +#define STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ + +#include +#include +#include +#include "leveldb/env.h" +#include "leveldb/slice.h" +#include "util/random.h" + +namespace leveldb { +namespace test { + +// Run some of the tests registered by the TEST() macro. If the +// environment variable "LEVELDB_TESTS" is not set, runs all tests. +// Otherwise, runs only the tests whose name contains the value of +// "LEVELDB_TESTS" as a substring. E.g., suppose the tests are: +// TEST(Foo, Hello) { ... } +// TEST(Foo, World) { ... } +// LEVELDB_TESTS=Hello will run the first test +// LEVELDB_TESTS=o will run both tests +// LEVELDB_TESTS=Junk will run no tests +// +// Returns 0 if all tests pass. +// Dies or returns a non-zero value if some test fails. +extern int RunAllTests(); + +// Return the directory to use for temporary storage. +extern std::string TmpDir(); + +// Return a randomization seed for this run. Typically returns the +// same number on repeated invocations of this binary, but automated +// runs may be able to vary the seed. +extern int RandomSeed(); + +// An instance of Tester is allocated to hold temporary state during +// the execution of an assertion. +class Tester { + private: + bool ok_; + const char* fname_; + int line_; + std::stringstream ss_; + + public: + Tester(const char* f, int l) + : ok_(true), fname_(f), line_(l) { + } + + ~Tester() { + if (!ok_) { + fprintf(stderr, "%s:%d:%s\n", fname_, line_, ss_.str().c_str()); + exit(1); + } + } + + Tester& Is(bool b, const char* msg) { + if (!b) { + ss_ << " Assertion failure " << msg; + ok_ = false; + } + return *this; + } + + Tester& IsOk(const Status& s) { + if (!s.ok()) { + ss_ << " " << s.ToString(); + ok_ = false; + } + return *this; + } + +#define BINARY_OP(name,op) \ + template \ + Tester& name(const X& x, const Y& y) { \ + if (! (x op y)) { \ + ss_ << " failed: " << x << (" " #op " ") << y; \ + ok_ = false; \ + } \ + return *this; \ + } + + BINARY_OP(IsEq, ==) + BINARY_OP(IsNe, !=) + BINARY_OP(IsGe, >=) + BINARY_OP(IsGt, >) + BINARY_OP(IsLe, <=) + BINARY_OP(IsLt, <) +#undef BINARY_OP + + // Attach the specified value to the error message if an error has occurred + template + Tester& operator<<(const V& value) { + if (!ok_) { + ss_ << " " << value; + } + return *this; + } +}; + +#define ASSERT_TRUE(c) ::leveldb::test::Tester(__FILE__, __LINE__).Is((c), #c) +#define ASSERT_OK(s) ::leveldb::test::Tester(__FILE__, __LINE__).IsOk((s)) +#define ASSERT_EQ(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsEq((a),(b)) +#define ASSERT_NE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsNe((a),(b)) +#define ASSERT_GE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsGe((a),(b)) +#define ASSERT_GT(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsGt((a),(b)) +#define ASSERT_LE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsLe((a),(b)) +#define ASSERT_LT(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsLt((a),(b)) + +#define TCONCAT(a,b) TCONCAT1(a,b) +#define TCONCAT1(a,b) a##b + +#define TEST(base,name) \ +class TCONCAT(_Test_,name) : public base { \ + public: \ + void _Run(); \ + static void _RunIt() { \ + TCONCAT(_Test_,name) t; \ + t._Run(); \ + } \ +}; \ +bool TCONCAT(_Test_ignored_,name) = \ + ::leveldb::test::RegisterTest(#base, #name, &TCONCAT(_Test_,name)::_RunIt); \ +void TCONCAT(_Test_,name)::_Run() + +// Register the specified test. Typically not used directly, but +// invoked via the macro expansion of TEST. +extern bool RegisterTest(const char* base, const char* name, void (*func)()); + + +} // namespace test +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ diff --git a/util/testutil.cc b/util/testutil.cc new file mode 100644 index 00000000..0b110edc --- /dev/null +++ b/util/testutil.cc @@ -0,0 +1,51 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/testutil.h" + +#include "util/random.h" + +namespace leveldb { +namespace test { + +Slice RandomString(Random* rnd, int len, std::string* dst) { + dst->resize(len); + for (int i = 0; i < len; i++) { + (*dst)[i] = static_cast(' ' + rnd->Uniform(95)); // ' ' .. '~' + } + return Slice(*dst); +} + +std::string RandomKey(Random* rnd, int len) { + // Make sure to generate a wide variety of characters so we + // test the boundary conditions for short-key optimizations. + static const char kTestChars[] = { + '\0', '\1', 'a', 'b', 'c', 'd', 'e', '\xfd', '\xfe', '\xff' + }; + std::string result; + for (int i = 0; i < len; i++) { + result += kTestChars[rnd->Uniform(sizeof(kTestChars))]; + } + return result; +} + + +extern Slice CompressibleString(Random* rnd, double compressed_fraction, + int len, std::string* dst) { + int raw = static_cast(len * compressed_fraction); + if (raw < 1) raw = 1; + std::string raw_data; + RandomString(rnd, raw, &raw_data); + + // Duplicate the random data until we have filled "len" bytes + dst->clear(); + while (dst->size() < (unsigned int)len) { + dst->append(raw_data); + } + dst->resize(len); + return Slice(*dst); +} + +} // namespace test +} // namespace leveldb diff --git a/util/testutil.h b/util/testutil.h new file mode 100644 index 00000000..8b200db9 --- /dev/null +++ b/util/testutil.h @@ -0,0 +1,53 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_TESTUTIL_H_ +#define STORAGE_LEVELDB_UTIL_TESTUTIL_H_ + +#include "leveldb/env.h" +#include "leveldb/slice.h" +#include "util/random.h" + +namespace leveldb { +namespace test { + +// Store in *dst a random string of length "len" and return a Slice that +// references the generated data. +extern Slice RandomString(Random* rnd, int len, std::string* dst); + +// Return a random key with the specified length that may contain interesting +// characters (e.g. \x00, \xff, etc.). +extern std::string RandomKey(Random* rnd, int len); + +// Store in *dst a string of length "len" that will compress to +// "N*compressed_fraction" bytes and return a Slice that references +// the generated data. +extern Slice CompressibleString(Random* rnd, double compressed_fraction, + int len, std::string* dst); + +// A wrapper that allows injection of errors. +class ErrorEnv : public EnvWrapper { + public: + bool writable_file_error_; + int num_writable_file_errors_; + + ErrorEnv() : EnvWrapper(Env::Default()), + writable_file_error_(false), + num_writable_file_errors_(0) { } + + virtual Status NewWritableFile(const std::string& fname, + unique_ptr* result) { + result->reset(); + if (writable_file_error_) { + ++num_writable_file_errors_; + return Status::IOError(fname, "fake error"); + } + return target()->NewWritableFile(fname, result); + } +}; + +} // namespace test +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_TESTUTIL_H_ diff --git a/valgrind_test.sh b/valgrind_test.sh new file mode 100755 index 00000000..95c3af11 --- /dev/null +++ b/valgrind_test.sh @@ -0,0 +1,14 @@ +#!/bin/bash +#A shell script for Jenknis to run valgrind on rocksdb tests +#Returns 0 on success when there are no failed tests + +VALGRIND_DIR=VALGRIND_LOGS +make -j$(nproc) valgrind_check +NUM_FAILED_TESTS=`wc -l $VALGRIND_DIR/valgrind_failed_tests | awk '{print $1}'` +if [ $NUM_FAILED_TESTS -le 1 ]; then + echo No tests have valgrind errors + exit 0 +else + cat $VALGRIND_DIR/valgrind_failed_tests + exit 1 +fi